Skip to content

Commit bf50cdb

Browse files
committed
Fix uncatchable error inside a promise (#810)
1 parent f22dee0 commit bf50cdb

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

quickjs.c

+32-8
Original file line numberDiff line numberDiff line change
@@ -17998,20 +17998,30 @@ static int js_async_function_resolve_create(JSContext *ctx,
1799817998
return 0;
1799917999
}
1800018000

18001-
static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
18001+
static BOOL js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
1800218002
{
18003+
BOOL is_success = TRUE;
1800318004
JSValue func_ret, ret2;
1800418005

1800518006
func_ret = async_func_resume(ctx, &s->func_state);
1800618007
if (JS_IsException(func_ret)) {
1800718008
JSValue error;
1800818009
fail:
1800918010
error = JS_GetException(ctx);
18010-
ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
18011+
if (unlikely(JS_IsUncatchableError(ctx, error))) {
18012+
JS_Throw(ctx, error);
18013+
is_success = FALSE;
18014+
} else {
18015+
ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
1801118016
1, &error);
18012-
JS_FreeValue(ctx, error);
18017+
if (unlikely(JS_IsException(ret2))) {
18018+
/* should only be uncatchable error */
18019+
is_success = FALSE;
18020+
}
18021+
JS_FreeValue(ctx, error);
18022+
JS_FreeValue(ctx, ret2);
18023+
}
1801318024
js_async_function_terminate(ctx->rt, s);
18014-
JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
1801518025
} else {
1801618026
JSValue value;
1801718027
value = s->func_state.frame.cur_sp[-1];
@@ -18020,7 +18030,11 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
1802018030
/* function returned */
1802118031
ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
1802218032
1, &value);
18023-
JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
18033+
if (unlikely(JS_IsException(ret2))) {
18034+
/* should only be uncatchable error */
18035+
is_success = FALSE;
18036+
}
18037+
JS_FreeValue(ctx, ret2);
1802418038
JS_FreeValue(ctx, value);
1802518039
js_async_function_terminate(ctx->rt, s);
1802618040
} else {
@@ -18053,6 +18067,7 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
1805318067
goto fail;
1805418068
}
1805518069
}
18070+
return is_success;
1805618071
}
1805718072

1805818073
static JSValue js_async_function_resolve_call(JSContext *ctx,
@@ -18077,7 +18092,9 @@ static JSValue js_async_function_resolve_call(JSContext *ctx,
1807718092
/* return value of await */
1807818093
s->func_state.frame.cur_sp[-1] = js_dup(arg);
1807918094
}
18080-
js_async_function_resume(ctx, s);
18095+
if (!js_async_function_resume(ctx, s)) {
18096+
return JS_EXCEPTION;
18097+
}
1808118098
return JS_UNDEFINED;
1808218099
}
1808318100

@@ -18109,7 +18126,9 @@ static JSValue js_async_function_call(JSContext *ctx, JSValue func_obj,
1810918126
}
1811018127
s->is_active = TRUE;
1811118128

18112-
js_async_function_resume(ctx, s);
18129+
if (!js_async_function_resume(ctx, s)) {
18130+
goto fail;
18131+
}
1811318132

1811418133
js_async_function_free(ctx->rt, s);
1811518134

@@ -48605,8 +48624,13 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc,
4860548624
res = JS_Call(ctx, handler, JS_UNDEFINED, 1, &arg);
4860648625
}
4860748626
is_reject = JS_IsException(res);
48608-
if (is_reject)
48627+
if (is_reject) {
4860948628
res = JS_GetException(ctx);
48629+
if (unlikely(JS_IsUncatchableError(ctx, res))) {
48630+
JS_Throw(ctx, res);
48631+
return JS_EXCEPTION;
48632+
}
48633+
}
4861048634
func = argv[is_reject];
4861148635
/* as an extension, we support undefined as value to avoid
4861248636
creating a dummy promise in the 'await' implementation of async

0 commit comments

Comments
 (0)