await bypasses catch when PromiseResolve throws

Aperta
#563 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
76/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c, javascript
Ambito
compilers

Direzione di ricerca

Start in quickjs.c at js_async_function_resume() and trace how PromiseResolve exceptions are handled when resuming an async function. Run the supplied qjs command at commit d73189d; done means the reproducer prints “caught: boom” instead of an unhandled rejection, while preserving normal async-function behavior.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Reproducer with the standalone qjs CLI (reproduced at d73189d, no embedding code):

./qjs -e 'const p = Promise.resolve(1);
Object.defineProperty(p, "constructor", { get() { throw Error("boom"); } });
(async () => {
    try { await p; } catch (e) { print("caught: " + e.message); }
})();'

Instead of entering catch, qjs reports Possibly unhandled promise rejection: Error: boom.

Expected behavior

Output: caught: boom. PromiseResolve propagates an exception thrown by the promise's constructor getter; Await propagates that abrupt completion at the await expression, where the surrounding try/catch handles it. QuickJS already resumes an async generator with throw_flag when preparing its await fails (js_async_generator_resume_next()); Node.js 25 also prints caught: boom for the equivalent example.

Possible patch

In js_async_function_resume(), throw the PromiseResolve exception into the suspended async function instead of rejecting its outer promise before its catch can run:

diff --git a/quickjs.c b/quickjs.c
--- a/quickjs.c
+++ b/quickjs.c
@@ -21056,1 +21056,2 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionState *s)
+ resume:
     func_ret = async_func_resume(ctx, s);
@@ -21082,8 +21083,10 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionState *s)
         promise = js_promise_resolve(ctx, ctx->promise_ctor,
                                      1, (JSValueConst *)&value, 0);
         JS_FreeValue(ctx, value);
-        if (JS_IsException(promise))
-            goto fail;
+        if (JS_IsException(promise)) {
+            s->throw_flag = TRUE;
+            goto resume;
+        }
Lingua principale
C
Stelle
11.1k
Fork
1.2k
Merge medio
11h 20m
PR unite (30g)
1

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di bellard/quickjs

Tutte le issue di bellard/quickjs

Issue simili

Altre issue su C

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.