]> git.kaiwu.me - njs.git/commitdiff
Fixed execution of async function in synchronous context.
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 3 Dec 2021 13:55:22 +0000 (13:55 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Fri, 3 Dec 2021 13:55:22 +0000 (13:55 +0000)
The bug was introduced in 92d10cd761e2 (0.7.0).

src/njs_async.c
src/test/njs_unit_test.c
test/js/async_promise.t.js [new file with mode: 0644]

index d92d377a790cdcc705f30fb40d4f8003f1a5e82c..7bc6c37e79fd19aad2a4812079ad5b2ad7708593 100644 (file)
@@ -37,6 +37,9 @@ njs_async_function_frame_invoke(njs_vm_t *vm, njs_value_t *retval)
         ret = njs_function_call(vm, njs_function(&capability->resolve),
                                 &njs_value_undefined, retval, 1, &vm->retval);
 
+    } else if (ret == NJS_AGAIN) {
+        ret = NJS_OK;
+
     } else if (ret == NJS_ERROR) {
         if (njs_is_memory_error(vm, &vm->retval)) {
             return NJS_ERROR;
@@ -116,6 +119,9 @@ njs_await_fulfilled(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 
         njs_async_context_free(vm, ctx);
 
+    } else if (ret == NJS_AGAIN) {
+        ret = NJS_OK;
+
     } else if (ret == NJS_ERROR) {
         if (njs_is_memory_error(vm, &vm->retval)) {
             return NJS_ERROR;
index 45db986a13ba71cdd1a97633c7907a2830f376ca..c11b47ed9c5d9db47edb659a6ae89f12ba761366 100644 (file)
@@ -21024,6 +21024,22 @@ static njs_unit_test_t  njs_externals_test[] =
               "$r.subrequest('b')"
               ".then(select => cb($r, select))"),
       njs_str("2") },
+
+    { njs_str("function pr(x) { return new Promise(resolve => {resolve(x + ':pr')}); };"
+              "Promise.all(['a', 'b', 'c'].map(async (v) => {"
+              "    return await pr(v + ':async');"
+              "}))"
+              ".then(v => $r.retval(v))"),
+      njs_str("a:async:pr,b:async:pr,c:async:pr") },
+
+    { njs_str("function pr(x) { return new Promise(resolve => {resolve(x + ':pr')}); };"
+              "Promise.all(['a', 'b', 'c'].map(async (v) => {"
+              "    let r = await pr(v + ':async');"
+              "    let r2 = await pr(r + ':async2');"
+              "    return r2 + ':r';"
+              "}))"
+              ".then(v => $r.retval(v))"),
+      njs_str("a:async:pr:async2:pr:r,b:async:pr:async2:pr:r,c:async:pr:async2:pr:r") },
 };
 
 
diff --git a/test/js/async_promise.t.js b/test/js/async_promise.t.js
new file mode 100644 (file)
index 0000000..27ed2b4
--- /dev/null
@@ -0,0 +1,20 @@
+/*---
+includes: [compareArray.js]
+flags: [async]
+---*/
+
+let stages = [];
+
+function pr(x) { return new Promise(resolve => {resolve(x)}); }
+
+pr(10)
+.then(async (v) => {
+    stages.push("then before");
+    let y = await pr(22);
+    stages.push(`then ${v} ${y}`);
+    return v + y;
+})
+.then(v => stages.push(`then2 ${v}`))
+.catch(e => $DONOTEVALUATE())
+.then(v => assert.compareArray(stages, ['then before', 'then 10 22', 'then2 32']))
+.then($DONE, $DONE);