From 165128257fb1be1c0504e6c238036e39164b403d Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Tue, 21 Nov 2023 23:57:10 +0100 Subject: [PATCH] Fix AsyncGenerator.prototype.return error handling (#109) A poisoned .constructor property is observable and the resulting exception should be delivered to the catch handler, not silently dropped, otherwise the generator hangs. --- quickjs.c | 17 +++++++++++++---- test262_errors.txt | 4 ---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/quickjs.c b/quickjs.c index b2f8f02..c65363f 100644 --- a/quickjs.c +++ b/quickjs.c @@ -17407,10 +17407,19 @@ static int js_async_generator_completed_return(JSContext *ctx, JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int res; - promise = js_promise_resolve(ctx, ctx->promise_ctor, - 1, (JSValueConst *)&value, 0); - if (JS_IsException(promise)) - return -1; + // Can fail looking up JS_ATOM_constructor when is_reject==0. + promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &value, + /*is_reject*/0); + // A poisoned .constructor property is observable and the resulting + // 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, + /*is_reject*/1); + JS_FreeValue(ctx, err); + if (JS_IsException(promise)) + return -1; + } if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator), resolving_funcs1, diff --git a/test262_errors.txt b/test262_errors.txt index d4c7450..4fc2d28 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -1,8 +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-state-completed-broken-promise.js:53: TypeError: $DONE() not called -test262/test/built-ins/AsyncGeneratorPrototype/return/return-state-completed-broken-promise.js:53: strict mode: TypeError: $DONE() not called -test262/test/built-ins/AsyncGeneratorPrototype/return/return-suspendedStart-broken-promise.js:34: TypeError: $DONE() not called -test262/test/built-ins/AsyncGeneratorPrototype/return/return-suspendedStart-broken-promise.js:34: strict mode: TypeError: $DONE() not called 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