From 39901e2b866f0e2d54d5cd1db9c86d3441390e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 14 Dec 2023 10:31:43 +0100 Subject: [PATCH] Fix async generator in case of exception in implicit await in the 'return' statement Ref: https://github.com/bellard/quickjs/commit/57105c7f23d196b2a6d954d70c290d021f8bbefc --- quickjs.c | 27 +++++++++++++++++++-------- test262_errors.txt | 2 -- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/quickjs.c b/quickjs.c index 09b7b1e..58476e6 100644 --- a/quickjs.c +++ b/quickjs.c @@ -17733,7 +17733,6 @@ static void js_async_generator_resume_next(JSContext *ctx, } else if (next->completion_type == GEN_MAGIC_RETURN) { s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN; js_async_generator_completed_return(ctx, s, next->result); - goto done; } else { js_async_generator_reject(ctx, s, next->result); } @@ -17764,7 +17763,7 @@ static void js_async_generator_resume_next(JSContext *ctx, js_async_generator_reject(ctx, s, value); JS_FreeValue(ctx, value); } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) { - int func_ret_code; + int func_ret_code, ret; value = s->func_state.frame.cur_sp[-1]; s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; func_ret_code = JS_VALUE_GET_INT(func_ret); @@ -17779,8 +17778,13 @@ static void js_async_generator_resume_next(JSContext *ctx, JS_FreeValue(ctx, value); break; case FUNC_RET_AWAIT: - js_async_generator_await(ctx, s, value); + ret = js_async_generator_await(ctx, s, value); JS_FreeValue(ctx, value); + if (ret < 0) { + /* exception: throw it */ + s->func_state.throw_flag = TRUE; + goto resume_exec; + } goto done; default: abort(); @@ -23874,6 +23878,18 @@ static void emit_return(JSParseState *s, BOOL hasval) BlockEnv *top; int drop_count; + if (s->cur_func->func_kind != JS_FUNC_NORMAL) { + if (!hasval) { + /* no value: direct return in case of async generator */ + emit_op(s, OP_undefined); + hasval = TRUE; + } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) { + /* the await must be done before handling the "finally" in + case it raises an exception */ + emit_op(s, OP_await); + } + } + drop_count = 0; top = s->cur_func->top_break; while (top != NULL) { @@ -23953,11 +23969,6 @@ static void emit_return(JSParseState *s, BOOL hasval) emit_label(s, label_return); emit_op(s, OP_return); } else if (s->cur_func->func_kind != JS_FUNC_NORMAL) { - if (!hasval) { - emit_op(s, OP_undefined); - } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) { - emit_op(s, OP_await); - } emit_op(s, OP_return_async); } else { emit_op(s, hasval ? OP_return : OP_return_undef); diff --git a/test262_errors.txt b/test262_errors.txt index 5058cae..e5dcaf0 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -1,6 +1,4 @@ test262/test/annexB/language/eval-code/direct/script-decl-lex-collision-in-sloppy-mode.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all -test262/test/built-ins/AsyncGeneratorPrototype/return/return-suspendedYield-broken-promise-try-catch.js:39: TypeError: $DONE() not called -test262/test/built-ins/AsyncGeneratorPrototype/return/return-suspendedYield-broken-promise-try-catch.js:39: strict mode: TypeError: $DONE() not called test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: Test262Error: Expected [a, abc] and [a, undefined] to have the same contents. ? quantifier test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: strict mode: Test262Error: Expected [a, abc] and [a, undefined] to have the same contents. ? quantifier test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:46: Test262Error: (Testing with BigInt64Array.)