]> git.kaiwu.me - njs.git/commitdiff
Fixed catching of exception thrown in try block of async function.
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 30 Nov 2021 14:55:57 +0000 (14:55 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Tue, 30 Nov 2021 14:55:57 +0000 (14:55 +0000)
The bug was introduced in 92d10cd761e2 (0.7.0).

src/njs_async.c
src/njs_async.h
src/njs_function.c
src/njs_function.h
src/njs_vmcode.c
test/js/async_throw_in_try_after_await.t.js [new file with mode: 0644]

index 6a93cfd01815b6b2ec7fa417f6504717140ed8a5..d92d377a790cdcc705f30fb40d4f8003f1a5e82c 100644 (file)
@@ -59,7 +59,7 @@ njs_await_fulfilled(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 {
     njs_int_t           ret;
     njs_value_t         **cur_local, **cur_closures, **cur_temp, *value;
-    njs_frame_t         *frame;
+    njs_frame_t         *frame, *async_frame;
     njs_function_t      *function;
     njs_async_ctx_t     *ctx;
     njs_native_frame_t  *top, *async;
@@ -71,7 +71,8 @@ njs_await_fulfilled(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
         goto failed;
     }
 
-    async = ctx->await;
+    async_frame = ctx->await;
+    async = &async_frame->native;
     async->previous = vm->top_frame;
 
     function = async->function;
@@ -87,7 +88,7 @@ njs_await_fulfilled(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     vm->levels[NJS_LEVEL_TEMP] = async->temp;
 
     vm->top_frame = async;
-    vm->active_frame = (njs_frame_t *) async;
+    vm->active_frame = async_frame;
 
     *njs_scope_value(vm, ctx->index) = *value;
     vm->retval = *value;
@@ -149,7 +150,7 @@ njs_await_rejected(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 
     value = njs_arg(args, nargs, 1);
 
-    if (ctx->await->pc == ctx->pc) {
+    if (ctx->await->native.pc == ctx->pc) {
         (void) njs_function_call(vm, njs_function(&ctx->capability->reject),
                                  &njs_value_undefined, value, 1, &vm->retval);
 
@@ -158,7 +159,7 @@ njs_await_rejected(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
         return NJS_ERROR;
     }
 
-    ctx->pc = ctx->await->pc;
+    ctx->pc = ctx->await->native.pc;
 
     return njs_await_fulfilled(vm, args, nargs, unused);
 }
index 598abfbc7c054eae035c53d7e12a18e5e94087cf..28533cbdcc92887b1443396159b0c87146e34df3 100644 (file)
@@ -10,7 +10,7 @@
 
 typedef struct {
     njs_promise_capability_t  *capability;
-    njs_native_frame_t        *await;
+    njs_frame_t               *await;
     uintptr_t                 index;
     u_char                    *pc;
 } njs_async_ctx_t;
index b166ef202d97f7c0205c7c14a68b4a1aea972ddf..e889c19de851b64279cc8720276e56d9c9b7ca17 100644 (file)
@@ -800,12 +800,17 @@ njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *native)
 
 
 njs_int_t
-njs_function_frame_save(njs_vm_t *vm, njs_native_frame_t *native, u_char *pc)
+njs_function_frame_save(njs_vm_t *vm, njs_frame_t *frame, u_char *pc)
 {
     size_t              value_count, n;
     njs_value_t         *start, *end, *p, **new, *value, **local;
     njs_function_t      *function;
-    njs_native_frame_t  *active;
+    njs_native_frame_t  *active, *native;
+
+    *frame = *vm->active_frame;
+    frame->previous_active_frame = NULL;
+
+    native = &frame->native;
 
     active = &vm->active_frame->native;
     value_count = njs_function_frame_value_count(active);
@@ -816,7 +821,6 @@ njs_function_frame_save(njs_vm_t *vm, njs_native_frame_t *native, u_char *pc)
     value = (njs_value_t *) (new + value_count
                              + function->u.lambda->temp);
 
-    *native = *active;
 
     native->arguments = value;
     native->arguments_offset = value + (function->args_offset - 1);
index f936547c4244a57f457166b8665fdfec66f36b1b..b47e7dc6af1f90cdc79b1c2b8b01c98959f3bd9b 100644 (file)
@@ -116,7 +116,7 @@ njs_int_t njs_function_lambda_call(njs_vm_t *vm);
 njs_int_t njs_function_native_call(njs_vm_t *vm);
 njs_native_frame_t *njs_function_frame_alloc(njs_vm_t *vm, size_t size);
 void njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *frame);
-njs_int_t njs_function_frame_save(njs_vm_t *vm, njs_native_frame_t *native,
+njs_int_t njs_function_frame_save(njs_vm_t *vm, njs_frame_t *native,
     u_char *pc);
 njs_object_type_t njs_function_object_type(njs_vm_t *vm,
     njs_function_t *function);
index 6f7639dd07c5a1564fa91635cc8e7fc53487fb6f..5facef586ac7c4befe0d8ed718f767575752f232 100644 (file)
@@ -1875,10 +1875,10 @@ njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await)
     frame = (njs_frame_t *) active;
 
     if (frame->exception.catch != NULL) {
-        ctx->await->pc = frame->exception.catch;
+        ctx->await->native.pc = frame->exception.catch;
 
     } else {
-        ctx->await->pc = ctx->pc;
+        ctx->await->native.pc = ctx->pc;
     }
 
     fulfilled->context = ctx;
diff --git a/test/js/async_throw_in_try_after_await.t.js b/test/js/async_throw_in_try_after_await.t.js
new file mode 100644 (file)
index 0000000..a00b2e9
--- /dev/null
@@ -0,0 +1,25 @@
+/*---
+includes: []
+flags: [async]
+---*/
+
+function pr(x) {
+    return new Promise(resolve => {resolve(x)});
+}
+
+async function add(x) {
+    try {
+        const a = await pr(x);
+        throw 'Oops';
+        return a + b;
+
+    } catch (e) {
+        return `catch: ${e.toString()}`;
+    }
+}
+
+add(50)
+.then(
+    v => assert.sameValue(v, 'catch: Oops'),
+    v => $DONOTEVALUATE(),
+).then($DONE, $DONE);