[njs] Fixed catching of exception thrown in try block of async function.

Dmitry Volyntsev xeioex at nginx.com
Tue Nov 30 16:36:14 UTC 2021


details:   https://hg.nginx.org/njs/rev/748eca39acb3
branches:  
changeset: 1755:748eca39acb3
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Nov 30 14:55:57 2021 +0000
description:
Fixed catching of exception thrown in try block of async function.

The bug was introduced in 92d10cd761e2 (0.7.0).

diffstat:

 src/njs_async.c                             |  11 ++++++-----
 src/njs_async.h                             |   2 +-
 src/njs_function.c                          |  10 +++++++---
 src/njs_function.h                          |   2 +-
 src/njs_vmcode.c                            |   4 ++--
 test/js/async_throw_in_try_after_await.t.js |  25 +++++++++++++++++++++++++
 6 files changed, 42 insertions(+), 12 deletions(-)

diffs (149 lines):

diff -r 6aaf1c14c1e7 -r 748eca39acb3 src/njs_async.c
--- a/src/njs_async.c	Mon Nov 29 18:14:25 2021 +0000
+++ b/src/njs_async.c	Tue Nov 30 14:55:57 2021 +0000
@@ -59,7 +59,7 @@ njs_await_fulfilled(njs_vm_t *vm, njs_va
 {
     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_va
         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_va
     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_val
 
     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_val
         return NJS_ERROR;
     }
 
-    ctx->pc = ctx->await->pc;
+    ctx->pc = ctx->await->native.pc;
 
     return njs_await_fulfilled(vm, args, nargs, unused);
 }
diff -r 6aaf1c14c1e7 -r 748eca39acb3 src/njs_async.h
--- a/src/njs_async.h	Mon Nov 29 18:14:25 2021 +0000
+++ b/src/njs_async.h	Tue Nov 30 14:55:57 2021 +0000
@@ -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;
diff -r 6aaf1c14c1e7 -r 748eca39acb3 src/njs_function.c
--- a/src/njs_function.c	Mon Nov 29 18:14:25 2021 +0000
+++ b/src/njs_function.c	Tue Nov 30 14:55:57 2021 +0000
@@ -800,12 +800,17 @@ njs_function_frame_free(njs_vm_t *vm, nj
 
 
 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, nj
     value = (njs_value_t *) (new + value_count
                              + function->u.lambda->temp);
 
-    *native = *active;
 
     native->arguments = value;
     native->arguments_offset = value + (function->args_offset - 1);
diff -r 6aaf1c14c1e7 -r 748eca39acb3 src/njs_function.h
--- a/src/njs_function.h	Mon Nov 29 18:14:25 2021 +0000
+++ b/src/njs_function.h	Tue Nov 30 14:55:57 2021 +0000
@@ -116,7 +116,7 @@ njs_int_t njs_function_lambda_call(njs_v
 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);
diff -r 6aaf1c14c1e7 -r 748eca39acb3 src/njs_vmcode.c
--- a/src/njs_vmcode.c	Mon Nov 29 18:14:25 2021 +0000
+++ b/src/njs_vmcode.c	Tue Nov 30 14:55:57 2021 +0000
@@ -1875,10 +1875,10 @@ njs_vmcode_await(njs_vm_t *vm, njs_vmcod
     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 -r 6aaf1c14c1e7 -r 748eca39acb3 test/js/async_throw_in_try_after_await.t.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/async_throw_in_try_after_await.t.js	Tue Nov 30 14:55:57 2021 +0000
@@ -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);


More information about the nginx-devel mailing list