diff --git a/src-json/define.json b/src-json/define.json index 8a74e26e22c..bffcb26c02c 100644 --- a/src-json/define.json +++ b/src-json/define.json @@ -402,12 +402,6 @@ "doc": "Enable the jit compiler for lua (version 5.2 only).", "platforms": ["lua"] }, - { - "name": "LuaStandalone", - "define": "lua-standalone", - "doc": "Print uncaught error before exiting the lua script.", - "platforms": ["lua"] - }, { "name": "LuaVanilla", "define": "lua-vanilla", diff --git a/src/generators/genlua.ml b/src/generators/genlua.ml index 65781d9653c..89071b721f4 100644 --- a/src/generators/genlua.ml +++ b/src/generators/genlua.ml @@ -47,7 +47,6 @@ type ctx = { mutable separator : bool; mutable found_expose : bool; mutable lua_jit : bool; - mutable lua_standalone : bool; mutable lua_vanilla : bool; mutable lua_ver : float; } @@ -1884,7 +1883,6 @@ let alloc_ctx com = separator = false; found_expose = false; lua_jit = Common.defined com Define.LuaJit; - lua_standalone = Common.defined com Define.LuaStandalone; lua_vanilla = Common.defined com Define.LuaVanilla; lua_ver = try float_of_string (Common.defined_value com Define.LuaVer) @@ -2148,36 +2146,28 @@ let generate com = print_file (Common.find_file com "lua/_lua/_hx_dyn_add.lua"); end; - if ctx.lua_standalone && Option.is_some com.main then begin - print_file (Common.find_file com "lua/_lua/_hx_handle_error.lua"); - end; + print_file (Common.find_file com "lua/_lua/_hx_handle_error.lua"); println ctx "_hx_static_init();"; List.iter (generate_enumMeta_fields ctx) com.types; Option.may (fun e -> - let luv_run = - (* Runs libuv loop if needed *) - mk_lua_code ctx.com.basic "_hx_luv.run()" [] ctx.com.basic.tvoid Globals.null_pos - in - if ctx.lua_standalone then begin - spr ctx "_G.xpcall("; - let fn = - { - tf_args = []; - tf_type = com.basic.tvoid; - tf_expr = mk (TBlock [e;luv_run]) com.basic.tvoid e.epos; - } - in - gen_value ctx { e with eexpr = TFunction fn; etype = TFun ([],com.basic.tvoid) }; - spr ctx ", _hx_handle_error)"; - end else begin - gen_expr ctx e; - newline ctx; - gen_expr ctx luv_run; - end; - newline ctx + spr ctx "local success, err = _G.xpcall("; + let luv_run = + (* Runs libuv loop if needed *) + mk_lua_code ctx.com.basic "_hx_luv.run()" [] ctx.com.basic.tvoid Globals.null_pos + in + let fn = + { + tf_args = []; + tf_type = com.basic.tvoid; + tf_expr = mk (TBlock [e;luv_run]) com.basic.tvoid e.epos; + } + in + gen_value ctx { e with eexpr = TFunction fn; etype = TFun ([],com.basic.tvoid) }; + println ctx ", _hx_handle_error)"; + println ctx "if not success then _G.error(err) end"; ) com.main; if anyExposed then diff --git a/std/lua/_lua/_hx_handle_error.lua b/std/lua/_lua/_hx_handle_error.lua index 5f7fa0e0e79..52f9740899d 100644 --- a/std/lua/_lua/_hx_handle_error.lua +++ b/std/lua/_lua/_hx_handle_error.lua @@ -1,12 +1,8 @@ function _hx_handle_error(obj) - if obj.value then - _G.print("runtime error:\n " .. _hx_tostring(obj.value)); - else - _G.print("runtime error:\n " .. tostring(obj)); - end - - if _G.debug and _G.debug.traceback then - _G.print(_G.debug.traceback()); - end - _G.os.exit(1) + local message = tostring(obj) + if _G.debug and _G.debug.traceback then + -- level 2 to skip _hx_handle_error + message = _G.debug.traceback(message, 2) + end + return setmetatable({}, { __tostring = function() return message end }) end diff --git a/std/lua/_std/haxe/Exception.hx b/std/lua/_std/haxe/Exception.hx index 0a99bd3eb9c..c267a7e6e95 100644 --- a/std/lua/_std/haxe/Exception.hx +++ b/std/lua/_std/haxe/Exception.hx @@ -49,6 +49,7 @@ class Exception { return __nativeException; } + @:keep // required for uncaught error handling public function toString():String { return message; } diff --git a/tests/misc/lua/projects/Issue10979/HaxeException.hx b/tests/misc/lua/projects/Issue10979/HaxeException.hx new file mode 100644 index 00000000000..0d1aceb257a --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/HaxeException.hx @@ -0,0 +1,5 @@ +class HaxeException { + static function main() { + throw "Exception thrown from Haxe"; + } +} diff --git a/tests/misc/lua/projects/Issue10979/NativeError.hx b/tests/misc/lua/projects/Issue10979/NativeError.hx new file mode 100644 index 00000000000..4bd4bf2b395 --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/NativeError.hx @@ -0,0 +1,6 @@ +class NativeError { + static function main() { + final object:Dynamic = null; + trace(object.value); + } +} diff --git a/tests/misc/lua/projects/Issue10979/RunScript.hx b/tests/misc/lua/projects/Issue10979/RunScript.hx new file mode 100644 index 00000000000..adfd292b1bb --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/RunScript.hx @@ -0,0 +1,38 @@ +using StringTools; + +function isLua5_1() { + final proc = new sys.io.Process("lua", ["-v"]); + final out = proc.stderr.readLine(); + proc.close(); + return out.startsWith("Lua 5.1."); +} + +function matchesExpectedMessage(actual:String) { + // lua 5.1 doesn't print custom error objects + if (actual == "(error object is not a string)") { + return true; + } + return new EReg(Sys.args()[1], "").match(actual); +} + +function main() { + final proc = new sys.io.Process("lua", [Sys.args()[0]]); + + // ignore "lua: " + final exceptionMessage = proc.stderr.readLine().substr(5); + + final hasExpectedMessage = matchesExpectedMessage(exceptionMessage); + // we don't want a bare error without a stack trace + final hasStackTrace = try { + proc.stderr.readLine().contains('stack traceback'); + } catch (_:haxe.io.Eof) { + false; + }; + + Sys.println('Error code: ${proc.exitCode()}'); + Sys.println('Has expected exception message: ${hasExpectedMessage}'); + // 5.1 interpreter doesn't handle custom objects + Sys.println('Has call stack: ${hasStackTrace || isLua5_1()}'); + + proc.close(); +} diff --git a/tests/misc/lua/projects/Issue10979/embedded-native.hxml b/tests/misc/lua/projects/Issue10979/embedded-native.hxml new file mode 100644 index 00000000000..b9acfcbd68f --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/embedded-native.hxml @@ -0,0 +1,4 @@ +--lua bin/native-error.lua +--main NativeError + +--cmd lua runner.lua 'bin/native-error' '%./bin/native%-error%.lua:%d+: attempt to index .+' diff --git a/tests/misc/lua/projects/Issue10979/embedded-native.hxml.stdout b/tests/misc/lua/projects/Issue10979/embedded-native.hxml.stdout new file mode 100644 index 00000000000..b530e9b2b9e --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/embedded-native.hxml.stdout @@ -0,0 +1,3 @@ +Success: false +Has expected exception message: true +Has call stack: true diff --git a/tests/misc/lua/projects/Issue10979/embedded.hxml b/tests/misc/lua/projects/Issue10979/embedded.hxml new file mode 100644 index 00000000000..7e648a43705 --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/embedded.hxml @@ -0,0 +1,4 @@ +--lua bin/haxe-exception.lua +--main HaxeException + +--cmd lua runner.lua 'bin/haxe-exception' 'Exception thrown from Haxe' diff --git a/tests/misc/lua/projects/Issue10979/embedded.hxml.stdout b/tests/misc/lua/projects/Issue10979/embedded.hxml.stdout new file mode 100644 index 00000000000..b530e9b2b9e --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/embedded.hxml.stdout @@ -0,0 +1,3 @@ +Success: false +Has expected exception message: true +Has call stack: true diff --git a/tests/misc/lua/projects/Issue10979/runner.lua b/tests/misc/lua/projects/Issue10979/runner.lua new file mode 100644 index 00000000000..56c6baeb33c --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/runner.lua @@ -0,0 +1,10 @@ +-- error in loaded script should be caught here, instead of exiting everything +local success, err = pcall(require, arg[1]) + +local exception_message = string.match(tostring(err), '^[^\n]+') +local has_expected_message = string.match(exception_message, arg[2]) ~= nil +local has_stack_trace = string.match(tostring(err), 'stack traceback') ~= nil + +print('Success: '..tostring(success)) +print('Has expected exception message: '..tostring(has_expected_message)) +print('Has call stack: '..tostring(has_stack_trace)) diff --git a/tests/misc/lua/projects/Issue10979/standalone-native.hxml b/tests/misc/lua/projects/Issue10979/standalone-native.hxml new file mode 100644 index 00000000000..65d3ea8c4e7 --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/standalone-native.hxml @@ -0,0 +1,7 @@ +--lua bin/native-error.lua +--main NativeError + +--next +--run RunScript +bin/native-error.lua +bin/native-error\.lua:\d+: attempt to index .* diff --git a/tests/misc/lua/projects/Issue10979/standalone-native.hxml.stdout b/tests/misc/lua/projects/Issue10979/standalone-native.hxml.stdout new file mode 100644 index 00000000000..5cdbdc6e67d --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/standalone-native.hxml.stdout @@ -0,0 +1,3 @@ +Error code: 1 +Has expected exception message: true +Has call stack: true diff --git a/tests/misc/lua/projects/Issue10979/standalone.hxml b/tests/misc/lua/projects/Issue10979/standalone.hxml new file mode 100644 index 00000000000..1505c2308e6 --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/standalone.hxml @@ -0,0 +1,7 @@ +--lua bin/haxe-exception.lua +--main HaxeException + +--next +--run RunScript +bin/haxe-exception.lua +Exception thrown from Haxe diff --git a/tests/misc/lua/projects/Issue10979/standalone.hxml.stdout b/tests/misc/lua/projects/Issue10979/standalone.hxml.stdout new file mode 100644 index 00000000000..5cdbdc6e67d --- /dev/null +++ b/tests/misc/lua/projects/Issue10979/standalone.hxml.stdout @@ -0,0 +1,3 @@ +Error code: 1 +Has expected exception message: true +Has call stack: true