]> git.kaiwu.me - njs.git/commitdiff
Fixed njs_vmcode_interpreter() when await fails.
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 2 Jun 2022 23:32:38 +0000 (16:32 -0700)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 2 Jun 2022 23:32:38 +0000 (16:32 -0700)
Previously, while interpreting a user function, njs_vmcode_interpreter()
might return prematurely when an error happens in await instruction.
This is not correct because the current frame has to be unwound (or
exception caught) first.

The fix is to exit through only 5 appropriate exit points to ensure
proper unwinding.

The patch correctly fixes issue reported in 07ef6c1f04f1 (0.7.3).

This closes #506 issue on Github.

src/njs_vmcode.c
test/js/async_exception_in_await.t.js [new file with mode: 0644]

index 9833ada03073b7bad9e71c9cda4e8d45a1be5254..cc33d20b2a9be319336462fc1b58cec89cda5985 100644 (file)
@@ -856,9 +856,15 @@ next:
             case NJS_VMCODE_AWAIT:
                 await = (njs_vmcode_await_t *) pc;
 
+                ret = njs_vmcode_await(vm, await, promise_cap, async_ctx);
+
                 njs_vmcode_debug(vm, pc, "EXIT AWAIT");
 
-                return njs_vmcode_await(vm, await, promise_cap, async_ctx);
+                if (njs_slow_path(ret == NJS_ERROR)) {
+                    goto error;
+                }
+
+                return ret;
 
             case NJS_VMCODE_TRY_START:
                 ret = njs_vmcode_try_start(vm, value1, value2, pc);
@@ -1923,6 +1929,7 @@ njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
 
     value = njs_scope_valid_value(vm, await->retval);
     if (njs_slow_path(value == NULL)) {
+        njs_internal_error(vm, "await->retval is invalid");
         return NJS_ERROR;
     }
 
diff --git a/test/js/async_exception_in_await.t.js b/test/js/async_exception_in_await.t.js
new file mode 100644 (file)
index 0000000..cc9bc8a
--- /dev/null
@@ -0,0 +1,22 @@
+/*---
+includes: []
+flags: []
+---*/
+
+var p = new Promise(() => 0);
+Object.defineProperty(p, "constructor", {get: () => ({}).a.a});
+
+async function g() {
+    try {
+        await p;
+    } catch (e) {
+    }
+}
+
+function f() {
+    g();
+
+    return 42;
+}
+
+assert.sameValue(f(), 42);