commit ec2072ba0bc645fff57ebbf88666b43151194f36
parent 4879a078644e4590cc9ab65865f1944e2eddfda9
Author: Fabrice Bellard <fabrice@bellard.org>
Date: Wed, 13 Dec 2023 19:01:59 +0100
fixed async generator in case of exception in the implicit await in the 'return' statement
Diffstat:
2 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c
@@ -19369,7 +19369,7 @@ static int js_async_generator_completed_return(JSContext *ctx,
// exception should be delivered to the catch handler.
if (JS_IsException(promise)) {
JSValue err = JS_GetException(ctx);
- promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &err,
+ promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, (JSValueConst *)&err,
/*is_reject*/1);
JS_FreeValue(ctx, err);
if (JS_IsException(promise))
@@ -19422,7 +19422,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);
}
@@ -19453,7 +19452,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);
@@ -19468,8 +19467,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();
@@ -25623,6 +25627,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) {
@@ -25701,11 +25717,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/quickjs/test262_errors.txt b/quickjs/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/Function/internals/Construct/derived-this-uninitialized-realm.js:20: Test262Error: Expected a ReferenceError but got a different error constructor with the same name
test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a different error constructor with the same name
test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: Test262Error: Expected [a, abc] and [a, undefined] to have the same contents. ? quantifier