diff --git a/jerry-main/main-unix.c b/jerry-main/main-unix.c index 2e84ca78b..733f65cc7 100644 --- a/jerry-main/main-unix.c +++ b/jerry-main/main-unix.c @@ -325,7 +325,8 @@ typedef enum OPT_EXEC_SNAP, OPT_EXEC_SNAP_FUNC, OPT_LOG_LEVEL, - OPT_NO_PROMPT + OPT_NO_PROMPT, + OPT_CALL_ON_EXIT } main_opt_id_t; /** @@ -365,6 +366,8 @@ static const cli_opt_t main_opts[] = .help = "set log level (0-3)"), CLI_OPT_DEF (.id = OPT_NO_PROMPT, .longopt = "no-prompt", .help = "don't print prompt in REPL mode"), + CLI_OPT_DEF (.id = OPT_CALL_ON_EXIT, .longopt = "call-on-exit", .meta = "STRING", + .help = "invoke the specified function when the process is just about to exit"), CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE", .help = "input JS file(s) (If file is -, read standard input.)") }; @@ -488,6 +491,8 @@ main (int argc, bool is_wait_mode = false; bool no_prompt = false; + const char *exit_cb = NULL; + cli_state_t cli_state = cli_init (main_opts, argc - 1, argv + 1); for (int id = cli_consume_option (&cli_state); id != CLI_OPT_END; id = cli_consume_option (&cli_state)) { @@ -530,6 +535,11 @@ main (int argc, } break; } + case OPT_CALL_ON_EXIT: + { + exit_cb = cli_consume_string (&cli_state); + break; + } case OPT_SHOW_RE_OP: { if (check_feature (JERRY_FEATURE_REGEXP_DUMP, cli_state.arg)) @@ -935,6 +945,32 @@ main (int argc, jerry_release_value (ret_value); + if (exit_cb != NULL) + { + jerry_value_t global = jerry_get_global_object (); + jerry_value_t fn_str = jerry_create_string ((jerry_char_t *) exit_cb); + jerry_value_t callback_fn = jerry_get_property (global, fn_str); + + jerry_release_value (global); + jerry_release_value (fn_str); + + if (jerry_value_is_function (callback_fn)) + { + jerry_value_t ret_val = jerry_call_function (callback_fn, jerry_create_undefined (), NULL, 0); + + if (jerry_value_is_error (ret_val)) + { + ret_val = jerry_get_value_from_error (ret_val, true); + print_unhandled_exception (ret_val); + ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + jerry_release_value (ret_val); + } + + jerry_release_value (callback_fn); + } + jerry_cleanup (); #if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) free (context_p); diff --git a/tests/jerry/es2015/regression-test-issue-2544.js b/tests/jerry/es2015/regression-test-issue-2544.js index 07c5ca9d5..38054ee55 100644 --- a/tests/jerry/es2015/regression-test-issue-2544.js +++ b/tests/jerry/es2015/regression-test-issue-2544.js @@ -13,8 +13,9 @@ // limitations under the License. Object.defineProperty(Array.prototype, 0, { get : function () { throw $; } }); -var asyncPassed = false; -Promise.race([ , this]).then(Error).catch(function(err) { asyncPassed = (err instanceof ReferenceError); }); -new Promise(function() { - throw 5; -}).then(Error).catch(function() { assert(asyncPassed); }); +var global_err = undefined; +Promise.race([ , this]).then(Error).catch(function(err) { global_err = err; }); + +function __checkAsync() { + assert(global_err instanceof ReferenceError); +} diff --git a/tools/runners/run-test-suite.py b/tools/runners/run-test-suite.py index c92abaa18..33f8bd345 100755 --- a/tools/runners/run-test-suite.py +++ b/tools/runners/run-test-suite.py @@ -127,7 +127,7 @@ def run_normal_tests(args, tests): test_cmd = get_platform_cmd_prefix() if args.runtime: test_cmd.append(args.runtime) - test_cmd.append(args.engine) + test_cmd.extend([args.engine, '--call-on-exit', '__checkAsync']) total = len(tests) tested = 0 @@ -161,6 +161,7 @@ def run_snapshot_tests(args, tests): generate_snapshot_cmd.append(args.runtime) execute_snapshot_cmd.extend([args.engine, '--exec-snapshot', 'js.snapshot']) + execute_snapshot_cmd.extend(['--call-on-exit', '__checkAsync']) # engine: jerry[.exe] -> snapshot generator: jerry-snapshot[.exe] engine = os.path.splitext(args.engine)