Skip to content

Commit 3e8c943

Browse files
author
Alexander Borisov
committed
Fixed resolve/reject callback for Promise.prototype.finally().
1 parent 573366b commit 3e8c943

File tree

3 files changed

+64
-21
lines changed

3 files changed

+64
-21
lines changed

src/njs_promise.c

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ typedef struct {
4545
njs_bool_t resolved;
4646
njs_bool_t *resolved_ref;
4747
njs_promise_capability_t *capability;
48+
njs_function_native_t handler;
4849
} njs_promise_context_t;
4950

5051

@@ -69,7 +70,9 @@ static njs_int_t njs_promise_perform_then(njs_vm_t *vm, njs_value_t *value,
6970
njs_promise_capability_t *capability);
7071
static njs_int_t njs_promise_then_finally_function(njs_vm_t *vm,
7172
njs_value_t *args, njs_uint_t nargs, njs_index_t unused);
72-
static njs_int_t njs_promise_catch_finally_function(njs_vm_t *vm,
73+
static njs_int_t njs_promise_then_finally_return(njs_vm_t *vm,
74+
njs_value_t *args, njs_uint_t nargs, njs_index_t unused);
75+
static njs_int_t njs_promise_catch_finally_return(njs_vm_t *vm,
7376
njs_value_t *args, njs_uint_t nargs, njs_index_t unused);
7477
static njs_int_t njs_promise_reaction_job(njs_vm_t *vm, njs_value_t *args,
7578
njs_uint_t nargs, njs_index_t unused);
@@ -207,7 +210,7 @@ njs_promise_constructor_call(njs_vm_t *vm, njs_function_t *function)
207210

208211

209212
static njs_function_t *
210-
njs_promise_create_function(njs_vm_t *vm)
213+
njs_promise_create_function(njs_vm_t *vm, size_t context_size)
211214
{
212215
njs_function_t *function;
213216
njs_promise_context_t *context;
@@ -217,10 +220,15 @@ njs_promise_create_function(njs_vm_t *vm)
217220
goto memory_error;
218221
}
219222

220-
context = njs_mp_zalloc(vm->mem_pool, sizeof(njs_promise_context_t));
221-
if (njs_slow_path(context == NULL)) {
222-
njs_mp_free(vm->mem_pool, function);
223-
goto memory_error;
223+
if (context_size > 0) {
224+
context = njs_mp_zalloc(vm->mem_pool, context_size);
225+
if (njs_slow_path(context == NULL)) {
226+
njs_mp_free(vm->mem_pool, function);
227+
goto memory_error;
228+
}
229+
230+
} else {
231+
context = NULL;
224232
}
225233

226234
function->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object;
@@ -253,7 +261,8 @@ njs_promise_create_resolving_functions(njs_vm_t *vm, njs_promise_t *promise,
253261

254262
/* Some compilers give at error an uninitialized context if using for. */
255263
do {
256-
function = njs_promise_create_function(vm);
264+
function = njs_promise_create_function(vm,
265+
sizeof(njs_promise_context_t));
257266
if (njs_slow_path(function == NULL)) {
258267
return NJS_ERROR;
259268
}
@@ -302,7 +311,7 @@ njs_promise_new_capability(njs_vm_t *vm, njs_value_t *constructor)
302311
return NULL;
303312
}
304313

305-
function = njs_promise_create_function(vm);
314+
function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
306315
if (njs_slow_path(function == NULL)) {
307316
return NULL;
308317
}
@@ -456,7 +465,8 @@ njs_promise_trigger_reactions(njs_vm_t *vm, njs_value_t *value,
456465
{
457466
reaction = njs_queue_link_data(link, njs_promise_reaction_t, link);
458467

459-
function = njs_promise_create_function(vm);
468+
function = njs_promise_create_function(vm,
469+
sizeof(njs_promise_context_t));
460470
function->u.native = njs_promise_reaction_job;
461471

462472
njs_set_data(&arguments[0], reaction, 0);
@@ -686,7 +696,7 @@ njs_promise_resolve_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
686696
arguments[1] = *resolution;
687697
arguments[2] = then;
688698

689-
function = njs_promise_create_function(vm);
699+
function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
690700
if (njs_slow_path(function == NULL)) {
691701
return NJS_ERROR;
692702
}
@@ -861,7 +871,7 @@ njs_promise_prototype_then(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
861871
goto failed;
862872
}
863873

864-
function = njs_promise_create_function(vm);
874+
function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
865875
function->u.native = njs_promise_constructor;
866876

867877
njs_set_function(&constructor, function);
@@ -941,7 +951,8 @@ njs_promise_perform_then(njs_vm_t *vm, njs_value_t *value,
941951
njs_queue_insert_tail(&data->reject_queue, &rejected_reaction->link);
942952

943953
} else {
944-
function = njs_promise_create_function(vm);
954+
function = njs_promise_create_function(vm,
955+
sizeof(njs_promise_context_t));
945956
function->u.native = njs_promise_reaction_job;
946957

947958
if (data->state == NJS_PROMISE_REJECTED) {
@@ -1009,7 +1020,7 @@ njs_promise_prototype_finally(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
10091020

10101021
finally = njs_arg(args, nargs, 1);
10111022

1012-
function = njs_promise_create_function(vm);
1023+
function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
10131024
function->u.native = njs_promise_constructor;
10141025

10151026
njs_set_function(&constructor, function);
@@ -1027,7 +1038,7 @@ njs_promise_prototype_finally(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
10271038
return njs_promise_invoke_then(vm, promise, arguments, 2);
10281039
}
10291040

1030-
function = njs_promise_create_function(vm);
1041+
function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
10311042
if (njs_slow_path(function == NULL)) {
10321043
return NJS_ERROR;
10331044
}
@@ -1038,21 +1049,23 @@ njs_promise_prototype_finally(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
10381049
context = function->context;
10391050
context->constructor = constructor;
10401051
context->finally = *finally;
1052+
context->handler = njs_promise_then_finally_return;
10411053

10421054
njs_set_function(&arguments[0], function);
10431055

1044-
function = njs_promise_create_function(vm);
1056+
function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
10451057
if (njs_slow_path(function == NULL)) {
10461058
njs_mp_free(vm->mem_pool, njs_function(&arguments[0]));
10471059
return NJS_ERROR;
10481060
}
10491061

1050-
function->u.native = njs_promise_catch_finally_function;
1062+
function->u.native = njs_promise_then_finally_function;
10511063
function->args_count = 1;
10521064

10531065
context = function->context;
10541066
context->constructor = constructor;
10551067
context->finally = *finally;
1068+
context->handler = njs_promise_catch_finally_return;
10561069

10571070
njs_set_function(&arguments[1], function);
10581071

@@ -1065,8 +1078,9 @@ njs_promise_then_finally_function(njs_vm_t *vm, njs_value_t *args,
10651078
njs_uint_t nargs, njs_index_t unused)
10661079
{
10671080
njs_int_t ret;
1068-
njs_value_t value, retval;
1081+
njs_value_t value, retval, argument;
10691082
njs_promise_t *promise;
1083+
njs_function_t *function;
10701084
njs_native_frame_t *frame;
10711085
njs_promise_context_t *context;
10721086

@@ -1086,18 +1100,35 @@ njs_promise_then_finally_function(njs_vm_t *vm, njs_value_t *args,
10861100

10871101
njs_set_promise(&value, promise);
10881102

1089-
return njs_promise_invoke_then(vm, &value, njs_arg(args, nargs, 1), 1);
1103+
function = njs_promise_create_function(vm, sizeof(njs_value_t));
1104+
if (njs_slow_path(function == NULL)) {
1105+
return NJS_ERROR;
1106+
}
1107+
1108+
function->u.native = context->handler;
1109+
1110+
*((njs_value_t *) function->context) = *njs_arg(args, nargs, 1);
1111+
1112+
njs_set_function(&argument, function);
1113+
1114+
return njs_promise_invoke_then(vm, &value, &argument, 1);
10901115
}
10911116

10921117

10931118
static njs_int_t
1094-
njs_promise_catch_finally_function(njs_vm_t *vm, njs_value_t *args,
1119+
njs_promise_then_finally_return(njs_vm_t *vm, njs_value_t *args,
10951120
njs_uint_t nargs, njs_index_t unused)
10961121
{
1097-
(void) njs_promise_then_finally_function(vm, args, nargs, unused);
1122+
njs_vm_retval_set(vm, vm->top_frame->function->context);
1123+
return NJS_OK;
1124+
}
10981125

1099-
njs_vm_retval_set(vm, njs_arg(args, nargs, 1));
11001126

1127+
static njs_int_t
1128+
njs_promise_catch_finally_return(njs_vm_t *vm, njs_value_t *args,
1129+
njs_uint_t nargs, njs_index_t unused)
1130+
{
1131+
njs_vm_retval_set(vm, vm->top_frame->function->context);
11011132
return NJS_ERROR;
11021133
}
11031134

test/js/promise_finally.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Promise.resolve('here')
2+
.finally(() => {'nope'})
3+
.then(v => {console.log(v)});
4+
5+
Promise.resolve('here')
6+
.finally(() => {throw 'nope'})
7+
.then(v => {console.log(v)});

test/njs_expect_test.exp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,11 @@ njs_run {"./test/js/promise_then_throw_catch.js"} \
10621062
njs_run {"./test/js/promise_catch_then_throw_catch.js"} \
10631063
"Done"
10641064

1065+
njs_run {"./test/js/promise_finally.js"} \
1066+
"here
1067+
Thrown:
1068+
Error: unhandled promise rejection: nope"
1069+
10651070
njs_run {"./test/js/promise_finally_throw.js"} \
10661071
"Error: unhandled promise rejection: ReferenceError: \"nonExsistingInFinally\" is not defined"
10671072

0 commit comments

Comments
 (0)