From cd85b6385037fa2db15c032ea7d02082fbebc023 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Fri, 3 Dec 2021 13:55:22 +0000 Subject: [PATCH] Fixed execution of async function in synchronous context. The bug was introduced in 92d10cd761e2 (0.7.0). --- src/njs_async.c | 6 ++++++ src/test/njs_unit_test.c | 16 ++++++++++++++++ test/js/async_promise.t.js | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 test/js/async_promise.t.js diff --git a/src/njs_async.c b/src/njs_async.c index d92d377a..7bc6c37e 100644 --- a/src/njs_async.c +++ b/src/njs_async.c @@ -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; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 45db986a..c11b47ed 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -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 index 00000000..27ed2b42 --- /dev/null +++ b/test/js/async_promise.t.js @@ -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); -- 2.47.3