[njs] Fixed resolve/reject callback for Promise.prototype.finally().
Alexander Borisov
alexander.borisov at nginx.com
Wed Aug 11 18:49:53 UTC 2021
details: https://hg.nginx.org/njs/rev/3e00ce537115
branches:
changeset: 1685:3e00ce537115
user: Alexander Borisov <alexander.borisov at nginx.com>
date: Wed Aug 11 21:48:51 2021 +0300
description:
Fixed resolve/reject callback for Promise.prototype.finally().
diffstat:
src/njs_promise.c | 75 ++++++++++++++++++++++++++++++++-------------
test/js/promise_finally.js | 7 ++++
test/njs_expect_test.exp | 5 +++
3 files changed, 65 insertions(+), 22 deletions(-)
diffs (230 lines):
diff -r ca2f051a4fc9 -r 3e00ce537115 src/njs_promise.c
--- a/src/njs_promise.c Wed Aug 11 21:48:51 2021 +0300
+++ b/src/njs_promise.c Wed Aug 11 21:48:51 2021 +0300
@@ -45,6 +45,7 @@ typedef struct {
njs_bool_t resolved;
njs_bool_t *resolved_ref;
njs_promise_capability_t *capability;
+ njs_function_native_t handler;
} njs_promise_context_t;
@@ -69,7 +70,9 @@ static njs_int_t njs_promise_perform_the
njs_promise_capability_t *capability);
static njs_int_t njs_promise_then_finally_function(njs_vm_t *vm,
njs_value_t *args, njs_uint_t nargs, njs_index_t unused);
-static njs_int_t njs_promise_catch_finally_function(njs_vm_t *vm,
+static njs_int_t njs_promise_then_finally_return(njs_vm_t *vm,
+ njs_value_t *args, njs_uint_t nargs, njs_index_t unused);
+static njs_int_t njs_promise_catch_finally_return(njs_vm_t *vm,
njs_value_t *args, njs_uint_t nargs, njs_index_t unused);
static njs_int_t njs_promise_reaction_job(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused);
@@ -207,7 +210,7 @@ njs_promise_constructor_call(njs_vm_t *v
static njs_function_t *
-njs_promise_create_function(njs_vm_t *vm)
+njs_promise_create_function(njs_vm_t *vm, size_t context_size)
{
njs_function_t *function;
njs_promise_context_t *context;
@@ -217,10 +220,15 @@ njs_promise_create_function(njs_vm_t *vm
goto memory_error;
}
- context = njs_mp_zalloc(vm->mem_pool, sizeof(njs_promise_context_t));
- if (njs_slow_path(context == NULL)) {
- njs_mp_free(vm->mem_pool, function);
- goto memory_error;
+ if (context_size > 0) {
+ context = njs_mp_zalloc(vm->mem_pool, context_size);
+ if (njs_slow_path(context == NULL)) {
+ njs_mp_free(vm->mem_pool, function);
+ goto memory_error;
+ }
+
+ } else {
+ context = NULL;
}
function->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object;
@@ -253,7 +261,8 @@ njs_promise_create_resolving_functions(n
/* Some compilers give at error an uninitialized context if using for. */
do {
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm,
+ sizeof(njs_promise_context_t));
if (njs_slow_path(function == NULL)) {
return NJS_ERROR;
}
@@ -302,7 +311,7 @@ njs_promise_new_capability(njs_vm_t *vm,
return NULL;
}
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
if (njs_slow_path(function == NULL)) {
return NULL;
}
@@ -456,7 +465,8 @@ njs_promise_trigger_reactions(njs_vm_t *
{
reaction = njs_queue_link_data(link, njs_promise_reaction_t, link);
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm,
+ sizeof(njs_promise_context_t));
function->u.native = njs_promise_reaction_job;
njs_set_data(&arguments[0], reaction, 0);
@@ -686,7 +696,7 @@ njs_promise_resolve_function(njs_vm_t *v
arguments[1] = *resolution;
arguments[2] = then;
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
if (njs_slow_path(function == NULL)) {
return NJS_ERROR;
}
@@ -861,7 +871,7 @@ njs_promise_prototype_then(njs_vm_t *vm,
goto failed;
}
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
function->u.native = njs_promise_constructor;
njs_set_function(&constructor, function);
@@ -941,7 +951,8 @@ njs_promise_perform_then(njs_vm_t *vm, n
njs_queue_insert_tail(&data->reject_queue, &rejected_reaction->link);
} else {
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm,
+ sizeof(njs_promise_context_t));
function->u.native = njs_promise_reaction_job;
if (data->state == NJS_PROMISE_REJECTED) {
@@ -1009,7 +1020,7 @@ njs_promise_prototype_finally(njs_vm_t *
finally = njs_arg(args, nargs, 1);
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
function->u.native = njs_promise_constructor;
njs_set_function(&constructor, function);
@@ -1027,7 +1038,7 @@ njs_promise_prototype_finally(njs_vm_t *
return njs_promise_invoke_then(vm, promise, arguments, 2);
}
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
if (njs_slow_path(function == NULL)) {
return NJS_ERROR;
}
@@ -1038,21 +1049,23 @@ njs_promise_prototype_finally(njs_vm_t *
context = function->context;
context->constructor = constructor;
context->finally = *finally;
+ context->handler = njs_promise_then_finally_return;
njs_set_function(&arguments[0], function);
- function = njs_promise_create_function(vm);
+ function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
if (njs_slow_path(function == NULL)) {
njs_mp_free(vm->mem_pool, njs_function(&arguments[0]));
return NJS_ERROR;
}
- function->u.native = njs_promise_catch_finally_function;
+ function->u.native = njs_promise_then_finally_function;
function->args_count = 1;
context = function->context;
context->constructor = constructor;
context->finally = *finally;
+ context->handler = njs_promise_catch_finally_return;
njs_set_function(&arguments[1], function);
@@ -1065,8 +1078,9 @@ njs_promise_then_finally_function(njs_vm
njs_uint_t nargs, njs_index_t unused)
{
njs_int_t ret;
- njs_value_t value, retval;
+ njs_value_t value, retval, argument;
njs_promise_t *promise;
+ njs_function_t *function;
njs_native_frame_t *frame;
njs_promise_context_t *context;
@@ -1086,18 +1100,35 @@ njs_promise_then_finally_function(njs_vm
njs_set_promise(&value, promise);
- return njs_promise_invoke_then(vm, &value, njs_arg(args, nargs, 1), 1);
+ function = njs_promise_create_function(vm, sizeof(njs_value_t));
+ if (njs_slow_path(function == NULL)) {
+ return NJS_ERROR;
+ }
+
+ function->u.native = context->handler;
+
+ *((njs_value_t *) function->context) = *njs_arg(args, nargs, 1);
+
+ njs_set_function(&argument, function);
+
+ return njs_promise_invoke_then(vm, &value, &argument, 1);
}
static njs_int_t
-njs_promise_catch_finally_function(njs_vm_t *vm, njs_value_t *args,
+njs_promise_then_finally_return(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused)
{
- (void) njs_promise_then_finally_function(vm, args, nargs, unused);
+ njs_vm_retval_set(vm, vm->top_frame->function->context);
+ return NJS_OK;
+}
+
- njs_vm_retval_set(vm, njs_arg(args, nargs, 1));
-
+static njs_int_t
+njs_promise_catch_finally_return(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused)
+{
+ njs_vm_retval_set(vm, vm->top_frame->function->context);
return NJS_ERROR;
}
diff -r ca2f051a4fc9 -r 3e00ce537115 test/js/promise_finally.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/promise_finally.js Wed Aug 11 21:48:51 2021 +0300
@@ -0,0 +1,7 @@
+Promise.resolve('here')
+.finally(() => {'nope'})
+.then(v => {console.log(v)});
+
+Promise.resolve('here')
+.finally(() => {throw 'nope'})
+.then(v => {console.log(v)});
diff -r ca2f051a4fc9 -r 3e00ce537115 test/njs_expect_test.exp
--- a/test/njs_expect_test.exp Wed Aug 11 21:48:51 2021 +0300
+++ b/test/njs_expect_test.exp Wed Aug 11 21:48:51 2021 +0300
@@ -1062,6 +1062,11 @@ njs_run {"./test/js/promise_then_throw_c
njs_run {"./test/js/promise_catch_then_throw_catch.js"} \
"Done"
+njs_run {"./test/js/promise_finally.js"} \
+"here
+Thrown:
+Error: unhandled promise rejection: nope"
+
njs_run {"./test/js/promise_finally_throw.js"} \
"Error: unhandled promise rejection: ReferenceError: \"nonExsistingInFinally\" is not defined"
More information about the nginx-devel
mailing list