[njs] Fixed execution of async function in synchronous context.

Dmitry Volyntsev xeioex at nginx.com
Fri Dec 3 13:57:20 UTC 2021


details:   https://hg.nginx.org/njs/rev/ed1756875eb5
branches:  
changeset: 1758:ed1756875eb5
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Dec 03 13:55:22 2021 +0000
description:
Fixed execution of async function in synchronous context.

The bug was introduced in 92d10cd761e2 (0.7.0).

diffstat:

 src/njs_async.c            |   6 ++++++
 src/test/njs_unit_test.c   |  16 ++++++++++++++++
 test/js/async_promise.t.js |  20 ++++++++++++++++++++
 3 files changed, 42 insertions(+), 0 deletions(-)

diffs (73 lines):

diff -r cd87a113829d -r ed1756875eb5 src/njs_async.c
--- a/src/njs_async.c	Fri Dec 03 13:55:12 2021 +0000
+++ b/src/njs_async.c	Fri Dec 03 13:55:22 2021 +0000
@@ -37,6 +37,9 @@ njs_async_function_frame_invoke(njs_vm_t
         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_va
 
         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;
diff -r cd87a113829d -r ed1756875eb5 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Fri Dec 03 13:55:12 2021 +0000
+++ b/src/test/njs_unit_test.c	Fri Dec 03 13:55:22 2021 +0000
@@ -21024,6 +21024,22 @@ static njs_unit_test_t  njs_externals_te
               "$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 -r cd87a113829d -r ed1756875eb5 test/js/async_promise.t.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/async_promise.t.js	Fri Dec 03 13:55:22 2021 +0000
@@ -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);


More information about the nginx-devel mailing list