details: https://hg.nginx.org/njs/rev/80adcb502e40 branches: changeset: 1686:80adcb502e40 user: Alexander Borisov <alexander.bori...@nginx.com> date: Wed Aug 11 21:48:52 2021 +0300 description: Added remaining Promise constructor methods.
The following methods were added: Promise.all(), Promise.allSettled(), Promise.any(), Promise.race(). diffstat: src/njs_promise.c | 599 +++++++++++++++++++++++++++++++++++ test/js/promise_all.js | 9 + test/js/promise_allSettled.js | 20 + test/js/promise_allSettled_string.js | 10 + test/js/promise_all_throw.js | 9 + test/js/promise_any.js | 8 + test/js/promise_any_all_rejected.js | 7 + test/js/promise_race.js | 12 + test/js/promise_race_throw.js | 12 + test/njs_expect_test.exp | 24 + 10 files changed, 710 insertions(+), 0 deletions(-) diffs (793 lines): diff -r 3e00ce537115 -r 80adcb502e40 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:52 2021 +0300 @@ -1,5 +1,6 @@ /* + * Copyright (C) Alexander Borisov * Copyright (C) Nginx, Inc. */ @@ -17,6 +18,12 @@ typedef enum { NJS_PROMISE_REJECT } njs_promise_rejection_type_t; +typedef enum { + NJS_PROMISE_ALL = 0, + NJS_PROMISE_ALL_SETTLED, + NJS_PROMISE_ANY +} njs_promise_function_type_t; + typedef struct { njs_promise_type_t state; njs_value_t result; @@ -48,6 +55,22 @@ typedef struct { njs_function_native_t handler; } njs_promise_context_t; +typedef struct { + njs_bool_t already_called; + uint32_t index; + uint32_t *remaining_elements; + njs_array_t *values; + njs_promise_capability_t *capability; +} njs_promise_all_context_t; + +typedef struct { + njs_iterator_args_t args; + uint32_t *remaining; + njs_value_t *constructor; + njs_function_t *function; + njs_promise_capability_t *capability; +} njs_promise_iterator_args_t; + static njs_promise_t *njs_promise_constructor_call(njs_vm_t *vm, njs_function_t *function); @@ -78,6 +101,28 @@ static njs_int_t njs_promise_reaction_jo njs_uint_t nargs, njs_index_t unused); static njs_int_t njs_promise_resolve_thenable_job(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); +static njs_int_t njs_promise_perform_all(njs_vm_t *vm, njs_value_t *iterator, + njs_promise_iterator_args_t *pargs, njs_iterator_handler_t handler, + njs_value_t *retval); +static njs_int_t njs_promise_perform_all_handler(njs_vm_t *vm, + njs_iterator_args_t *args, njs_value_t *value, int64_t index); +static njs_int_t njs_promise_all_resolve_element_functions(njs_vm_t *vm, + njs_value_t *args, njs_uint_t nargs, njs_index_t unused); +static njs_int_t njs_promise_perform_all_settled_handler(njs_vm_t *vm, + njs_iterator_args_t *args, njs_value_t *value, int64_t index); +static njs_int_t njs_promise_all_settled_element_functions(njs_vm_t *vm, + njs_value_t *args, njs_uint_t nargs, njs_index_t rejected); +static njs_int_t njs_promise_perform_any_handler(njs_vm_t *vm, + njs_iterator_args_t *args, njs_value_t *value, int64_t index); +static njs_int_t njs_promise_any_reject_element_functions(njs_vm_t *vm, + njs_value_t *args, njs_uint_t nargs, njs_index_t unused); +static njs_int_t njs_promise_perform_race_handler(njs_vm_t *vm, + njs_iterator_args_t *args, njs_value_t *value, int64_t index); + + +static const njs_value_t string_resolve = njs_string("resolve"); +static const njs_value_t string_any_rejected = + njs_long_string("All promises were rejected"); static njs_promise_t * @@ -1229,6 +1274,527 @@ njs_promise_resolve_thenable_job(njs_vm_ static njs_int_t +njs_promise_all(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t function_type) +{ + njs_int_t ret; + njs_value_t *promise, resolve; + njs_iterator_handler_t handler; + njs_promise_iterator_args_t pargs; + + promise = njs_argument(args, 0); + + pargs.capability = njs_promise_new_capability(vm, promise); + if (njs_slow_path(pargs.capability == NULL)) { + return NJS_ERROR; + } + + ret = njs_value_property(vm, promise, njs_value_arg(&string_resolve), + &resolve); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_slow_path(!njs_is_function(&resolve))) { + njs_type_error(vm, "resolve is not callable"); + return NJS_ERROR; + } + + pargs.function = njs_function(&resolve); + pargs.constructor = promise; + + switch (function_type) { + case NJS_PROMISE_ALL_SETTLED: + handler = njs_promise_perform_all_settled_handler; + break; + + case NJS_PROMISE_ANY: + handler = njs_promise_perform_any_handler; + break; + + default: + handler = njs_promise_perform_all_handler; + break; + } + + return njs_promise_perform_all(vm, njs_arg(args, nargs, 1), &pargs, + handler, &vm->retval); +} + + +static njs_int_t +njs_promise_perform_all(njs_vm_t *vm, njs_value_t *iterator, + njs_promise_iterator_args_t *pargs, njs_iterator_handler_t handler, + njs_value_t *retval) +{ + int64_t length; + njs_int_t ret; + njs_value_t argument; + njs_object_t *error; + + if (njs_slow_path(!njs_is_object(pargs->constructor))) { + njs_type_error(vm, "constructor is not object"); + return NJS_ERROR; + } + + njs_memzero(&pargs->args, sizeof(njs_iterator_args_t)); + + ret = njs_object_length(vm, iterator, &length); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + pargs->args.array = njs_array_alloc(vm, 1, length, 0); + if (njs_slow_path(pargs->args.array == NULL)) { + return NJS_ERROR; + } + + pargs->remaining = njs_mp_alloc(vm->mem_pool, sizeof(uint32_t)); + if (njs_slow_path(pargs->remaining == NULL)) { + njs_memory_error(vm); + return NJS_ERROR; + } + + (*pargs->remaining) = 1; + + pargs->args.value = iterator; + pargs->args.to = length; + + ret = njs_object_iterate(vm, &pargs->args, handler); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (--(*pargs->remaining) == 0) { + njs_mp_free(vm->mem_pool, pargs->remaining); + + njs_set_array(&argument, pargs->args.array); + + if (handler == njs_promise_perform_any_handler) { + error = njs_error_alloc(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR, + NULL, &string_any_rejected, &argument); + if (njs_slow_path(error == NULL)) { + return NJS_ERROR; + } + + njs_set_object(&argument, error); + } + + ret = njs_function_call(vm, njs_function(&pargs->capability->resolve), + &njs_value_undefined, &argument, 1, retval); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + } + + *retval = pargs->capability->promise; + + return NJS_OK; +} + + +static njs_int_t +njs_promise_perform_all_handler(njs_vm_t *vm, njs_iterator_args_t *args, + njs_value_t *value, int64_t index) +{ + njs_int_t ret; + njs_value_t arguments[2], next; + njs_function_t *on_fulfilled; + njs_promise_capability_t *capability; + njs_promise_all_context_t *context; + njs_promise_iterator_args_t *pargs; + + pargs = (njs_promise_iterator_args_t *) args; + + capability = pargs->capability; + + njs_set_undefined(&pargs->args.array->start[index]); + + ret = njs_function_call(vm, pargs->function, pargs->constructor, value, + 1, &next); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + on_fulfilled = njs_promise_create_function(vm, + sizeof(njs_promise_all_context_t)); + if (njs_slow_path(on_fulfilled == NULL)) { + return NJS_ERROR; + } + + on_fulfilled->u.native = njs_promise_all_resolve_element_functions; + on_fulfilled->args_count = 1; + + context = on_fulfilled->context; + + context->already_called = 0; + context->index = (uint32_t) index; + context->values = pargs->args.array; + context->capability = capability; + context->remaining_elements = pargs->remaining; + + (*pargs->remaining)++; + + njs_set_function(&arguments[0], on_fulfilled); + arguments[1] = capability->reject; + + ret = njs_promise_invoke_then(vm, &next, arguments, 2); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + return NJS_OK; +} + + +static njs_int_t +njs_promise_all_resolve_element_functions(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused) +{ + njs_value_t arguments; + njs_promise_all_context_t *context; + + context = vm->top_frame->function->context; + + if (context->already_called) { + njs_vm_retval_set(vm, &njs_value_undefined); + return NJS_OK; + } + + context->already_called = 1; + context->values->start[context->index] = *njs_arg(args, nargs, 1); + + if (--(*context->remaining_elements) == 0) { + njs_mp_free(vm->mem_pool, context->remaining_elements); + + njs_set_array(&arguments, context->values); + + return njs_function_call(vm, + njs_function(&context->capability->resolve), + &njs_value_undefined, &arguments, 1, + &vm->retval); + } + + njs_vm_retval_set(vm, &njs_value_undefined); + + return NJS_OK; +} + + +static njs_int_t +njs_promise_perform_all_settled_handler(njs_vm_t *vm, njs_iterator_args_t *args, + njs_value_t *value, int64_t index) +{ + njs_int_t ret; + njs_value_t arguments[2], next; + njs_function_t *on_fulfilled, *on_rejected; + njs_promise_capability_t *capability; + njs_promise_all_context_t *context; + njs_promise_iterator_args_t *pargs; + + pargs = (njs_promise_iterator_args_t *) args; + + capability = pargs->capability; + + njs_set_undefined(&pargs->args.array->start[index]); + + ret = njs_function_call(vm, pargs->function, pargs->constructor, value, + 1, &next); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + on_fulfilled = njs_promise_create_function(vm, + sizeof(njs_promise_all_context_t)); + if (njs_slow_path(on_fulfilled == NULL)) { + return NJS_ERROR; + } + + context = on_fulfilled->context; + + context->already_called = 0; + context->index = (uint32_t) index; + context->values = pargs->args.array; + context->capability = capability; + context->remaining_elements = pargs->remaining; + + on_rejected = njs_promise_create_function(vm, 0); + if (njs_slow_path(on_rejected == NULL)) { + return NJS_ERROR; + } + + on_fulfilled->u.native = njs_promise_all_settled_element_functions; + on_rejected->u.native = njs_promise_all_settled_element_functions; + on_rejected->magic8 = 1; /* rejected. */ + + on_fulfilled->args_count = 1; + on_rejected->args_count = 1; + + on_rejected->context = context; + + (*pargs->remaining)++; + + njs_set_function(&arguments[0], on_fulfilled); + njs_set_function(&arguments[1], on_rejected); + + ret = njs_promise_invoke_then(vm, &next, arguments, 2); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + return NJS_OK; +} + + +static njs_int_t +njs_promise_all_settled_element_functions(njs_vm_t *vm, + njs_value_t *args, njs_uint_t nargs, njs_index_t rejected) +{ + njs_int_t ret; + njs_value_t arguments, *value; + njs_object_t *obj; + const njs_value_t *status, *set; + njs_promise_all_context_t *context; + + static const njs_value_t string_status = njs_string("status"); + static const njs_value_t string_fulfilled = njs_string("fulfilled"); + static const njs_value_t string_value = njs_string("value"); + static const njs_value_t string_rejected = njs_string("rejected"); + static const njs_value_t string_reason = njs_string("reason"); + + context = vm->top_frame->function->context; + + if (context->already_called) { + njs_vm_retval_set(vm, &njs_value_undefined); + return NJS_OK; + } + + context->already_called = 1; + + obj = njs_object_alloc(vm); + if (njs_slow_path(obj == NULL)) { + return NJS_ERROR; + } + + value = &context->values->start[context->index]; + + njs_set_object(value, obj); + + if (rejected) { + status = &string_rejected; + set = &string_reason; + + } else { + status = &string_fulfilled; + set = &string_value; + } + + ret = njs_value_property_set(vm, value, njs_value_arg(&string_status), + njs_value_arg(status)); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + ret = njs_value_property_set(vm, value, njs_value_arg(set), + njs_arg(args, nargs, 1)); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (--(*context->remaining_elements) == 0) { + njs_mp_free(vm->mem_pool, context->remaining_elements); + + njs_set_array(&arguments, context->values); + + return njs_function_call(vm, + njs_function(&context->capability->resolve), + &njs_value_undefined, &arguments, 1, + &vm->retval); + } + + njs_vm_retval_set(vm, &njs_value_undefined); + + return NJS_OK; +} + + +static njs_int_t +njs_promise_perform_any_handler(njs_vm_t *vm, njs_iterator_args_t *args, + njs_value_t *value, int64_t index) +{ + njs_int_t ret; + njs_value_t arguments[2], next; + njs_function_t *on_rejected; + njs_promise_capability_t *capability; + njs_promise_all_context_t *context; + njs_promise_iterator_args_t *pargs; + + pargs = (njs_promise_iterator_args_t *) args; + + capability = pargs->capability; + + njs_set_undefined(&pargs->args.array->start[index]); + + ret = njs_function_call(vm, pargs->function, pargs->constructor, value, 1, + &next); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + on_rejected = njs_promise_create_function(vm, + sizeof(njs_promise_all_context_t)); + if (njs_slow_path(on_rejected == NULL)) { + return NJS_ERROR; + } + + on_rejected->u.native = njs_promise_any_reject_element_functions; + on_rejected->args_count = 1; + + context = on_rejected->context; + + context->already_called = 0; + context->index = (uint32_t) index; + context->values = pargs->args.array; + context->capability = capability; + context->remaining_elements = pargs->remaining; + + (*pargs->remaining)++; + + arguments[0] = capability->resolve; + njs_set_function(&arguments[1], on_rejected); + + ret = njs_promise_invoke_then(vm, &next, arguments, 2); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + return NJS_OK; +} + + +static njs_int_t +njs_promise_any_reject_element_functions(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused) +{ + njs_value_t argument; + njs_object_t *error; + njs_promise_all_context_t *context; + + context = vm->top_frame->function->context; + + if (context->already_called) { + njs_vm_retval_set(vm, &njs_value_undefined); + return NJS_OK; + } + + context->already_called = 1; + context->values->start[context->index] = *njs_arg(args, nargs, 1); + + if (--(*context->remaining_elements) == 0) { + njs_mp_free(vm->mem_pool, context->remaining_elements); + + njs_set_array(&argument, context->values); + + error = njs_error_alloc(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR, + NULL, &string_any_rejected, &argument); + if (njs_slow_path(error == NULL)) { + return NJS_ERROR; + } + + njs_set_object(&argument, error); + + return njs_function_call(vm, njs_function(&context->capability->reject), + &njs_value_undefined, &argument, 1, + &vm->retval); + } + + njs_vm_retval_set(vm, &njs_value_undefined); + + return NJS_OK; +} + + +static njs_int_t +njs_promise_race(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + int64_t length; + njs_int_t ret; + njs_value_t *promise, *iterator, resolve; + njs_promise_iterator_args_t pargs; + + promise = njs_argument(args, 0); + iterator = njs_arg(args, nargs, 1); + + pargs.capability = njs_promise_new_capability(vm, promise); + if (njs_slow_path(pargs.capability == NULL)) { + return NJS_ERROR; + } + + ret = njs_value_property(vm, promise, njs_value_arg(&string_resolve), + &resolve); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_slow_path(!njs_is_function(&resolve))) { + njs_type_error(vm, "resolve is not callable"); + return NJS_ERROR; + } + + ret = njs_object_length(vm, iterator, &length); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + njs_memzero(&pargs.args, sizeof(njs_iterator_args_t)); + + pargs.function = njs_function(&resolve); + pargs.constructor = promise; + + pargs.args.value = iterator; + pargs.args.to = length; + + ret = njs_object_iterate(vm, &pargs.args, njs_promise_perform_race_handler); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + vm->retval = pargs.capability->promise; + + return NJS_OK; +} + + +static njs_int_t +njs_promise_perform_race_handler(njs_vm_t *vm, njs_iterator_args_t *args, + njs_value_t *value, int64_t index) +{ + njs_int_t ret; + njs_value_t arguments[2], next; + njs_promise_capability_t *capability; + njs_promise_iterator_args_t *pargs; + + pargs = (njs_promise_iterator_args_t *) args; + + ret = njs_function_call(vm, pargs->function, pargs->constructor, value, + 1, &next); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + capability = pargs->capability; + + arguments[0] = capability->resolve; + arguments[1] = capability->reject; + + (void) njs_promise_invoke_then(vm, &next, arguments, 2); + + return NJS_OK; +} + + +static njs_int_t njs_promise_species(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { @@ -1278,6 +1844,39 @@ static const njs_object_prop_t njs_prom { .type = NJS_PROPERTY, + .name = njs_string("all"), + .value = njs_native_function2(njs_promise_all, 1, NJS_PROMISE_ALL), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("allSettled"), + .value = njs_native_function2(njs_promise_all, 1, + NJS_PROMISE_ALL_SETTLED), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("any"), + .value = njs_native_function2(njs_promise_all, 1, NJS_PROMISE_ANY), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("race"), + .value = njs_native_function(njs_promise_race, 1), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, .name = njs_wellknown_symbol(NJS_SYMBOL_SPECIES), .value = njs_value(NJS_INVALID, 1, NAN), .getter = njs_native_function(njs_promise_species, 0), diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_all.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_all.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,9 @@ +function resolve(value) { + return new Promise(resolve => setTimeout(() => resolve(value), 0)); +} + +Promise.all([resolve(['one', 'two']), resolve(['three', 'four'])]) +.then( + (v) => {console.log(`resolved:${njs.dump(v)}`)}, + (v) => {console.log(`rejected:${njs.dump(v)}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_allSettled.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_allSettled.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,20 @@ +var p0 = Promise.resolve(2).then(v => v + 1); +var p1 = Promise.reject(21).catch(v => v * 2); +var p2 = Promise.resolve('nope').then(() => { throw 'foo' }); +var p3 = Promise.reject('yes').then(() => { throw 'nope'; }); +var p4 = Promise.resolve('here').finally(() => 'nope'); +var p5 = Promise.reject('here too').finally(() => 'nope'); +var p6 = Promise.resolve('nope').finally(() => { throw 'finally'; }); +var p7 = Promise.reject('nope').finally(() => { throw 'finally after rejected'; }); +var p8 = Promise.reject(1).then(() => 'nope', () => 0); + +function dump(v) { + var fulfilled = v.filter(v=>v.status == 'fulfilled').map(v=>v.value).sort(); + var rejected = v.filter(v=>v.status == 'rejected').map(v=>v.reason).sort(); + return `F:${fulfilled}|R:${rejected}` +} + +Promise.allSettled([p0, p1, p2, p3, p4, p5, p6, p7, p8]).then( + (v) => {console.log(`resolved:${dump(v)}`)}, + (v) => {console.log(`rejected:${dump(v)}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_allSettled_string.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_allSettled_string.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,10 @@ +function dump(v) { + var fulfilled = v.filter(v=>v.status == 'fulfilled').map(v=>v.value).sort(); + var rejected = v.filter(v=>v.status == 'rejected').map(v=>v.reason).sort(); + return `F:${fulfilled}|R:${rejected}`; +} + +Promise.allSettled("abc").then( + (v) => {console.log(`resolved:${dump(v)}`)}, + (v) => {console.log(`rejected:${dump(v)}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_all_throw.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_all_throw.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,9 @@ +var p0 = Promise.resolve(1).then(v => v + 1); +var p1 = Promise.reject(2).catch(v => v * 2); +var p2 = Promise.resolve().then(() => { throw 'foo' }); +var p3 = Promise.reject().then(() => { throw 'oof'; }); + +Promise.all([p0, p1, p2, p3]).then( + (v) => {console.log(`resolved:${v}`)}, + (v) => {console.log(`rejected:${v}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_any.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_any.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,8 @@ +var p0 = Promise.resolve().then(() => { throw 'foo' }); +var p1 = Promise.reject(2).catch(v => v * 2); +var p2 = Promise.resolve(1).then(v => v + 1); + +Promise.any([p0, p1, p2]).then( + (v) => {console.log(`resolved:${v}`)}, + (v) => {console.log(`rejected:${v}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_any_all_rejected.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_any_all_rejected.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,7 @@ +var p0 = Promise.reject(1); +var p1 = Promise.reject(2); + +Promise.any([p0, p1]).then( + (v) => {console.log(`resolve:${v}`)}, + (v) => {console.log(`reject:${v}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_race.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_race.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,12 @@ +var p1 = new Promise((resolve, reject) => { + setTimeout(resolve, 0, 'one'); +}); + +var p2 = new Promise((resolve, reject) => { + setTimeout(resolve, 0, 'two'); +}); + +Promise.race([p1, p2]).then( + (v) => {console.log(`resolved:${v}`)}, + (v) => {console.log(`rejected:${v}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 test/js/promise_race_throw.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/promise_race_throw.js Wed Aug 11 21:48:52 2021 +0300 @@ -0,0 +1,12 @@ +var p1 = new Promise((resolve, reject) => { + throw 'one'; +}); + +var p2 = new Promise((resolve, reject) => { + setTimeout(resolve, 0, 'two'); +}); + +Promise.race([p1, p2]).then( + (v) => {console.log(`resolved:${v}`)}, + (v) => {console.log(`rejected:${v}`)} +); diff -r 3e00ce537115 -r 80adcb502e40 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:52 2021 +0300 @@ -1084,3 +1084,27 @@ njs_run {"./test/js/promise_reject_catch njs_run {"./test/js/promise_reject_post_catch.js"} \ "Error: unhandled promise rejection: undefined" + +njs_run {"./test/js/promise_all.js"} \ +"resolved:\\\[\\\['one','two'],\\\['three','four']]" + +njs_run {"./test/js/promise_all_throw.js"} \ +"rejected:foo" + +njs_run {"./test/js/promise_allSettled.js"} \ +"resolved:resolved:F:0,3,42,here|R:finally,finally after rejected,foo,here too,yes" + +njs_run {"./test/js/promise_allSettled_string.js"} \ +"resolved:F:a,b,c|R:" + +njs_run {"./test/js/promise_any.js"} \ +"resolved:4" + +njs_run {"./test/js/promise_any_all_rejected.js"} \ +"reject:AggregateError: All promises were rejected" + +njs_run {"./test/js/promise_race.js"} \ +"resolved:one" + +njs_run {"./test/js/promise_race_throw.js"} \ +"rejected:one" _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel