details: https://hg.nginx.org/njs/rev/ca2f051a4fc9 branches: changeset: 1684:ca2f051a4fc9 user: Alexander Borisov <alexander.bori...@nginx.com> date: Wed Aug 11 21:48:51 2021 +0300 description: Introduced AggregateError implementation.
diffstat: src/njs_builtin.c | 11 ++++ src/njs_error.c | 127 +++++++++++++++++++++++++++++++++++++++++++++- src/njs_error.h | 4 +- src/njs_fs.c | 2 +- src/njs_iterator.c | 45 ++++++++++++++++ src/njs_iterator.h | 2 + src/njs_object_hash.h | 29 ++++++++++ src/njs_vm.h | 1 + src/test/njs_unit_test.c | 20 +++++++ 9 files changed, 234 insertions(+), 7 deletions(-) diffs (407 lines): diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_builtin.c --- a/src/njs_builtin.c Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_builtin.c Wed Aug 11 21:48:51 2021 +0300 @@ -114,6 +114,7 @@ static const njs_object_type_init_t *con &njs_type_error_type_init, &njs_uri_error_type_init, &njs_memory_error_type_init, + &njs_aggregate_error_type_init, }; @@ -1676,6 +1677,16 @@ static const njs_object_prop_t njs_glob .writable = 1, .configurable = 1, }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("AggregateError"), + .value = njs_prop_handler2(njs_top_level_constructor, + NJS_OBJ_TYPE_AGGREGATE_ERROR, + NJS_AGGREGATE_ERROR_HASH), + .writable = 1, + .configurable = 1, + }, }; diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_error.c --- a/src/njs_error.c Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_error.c Wed Aug 11 21:48:51 2021 +0300 @@ -24,6 +24,7 @@ static njs_int_t njs_backtrace_to_string static const njs_value_t njs_error_message_string = njs_string("message"); static const njs_value_t njs_error_name_string = njs_string("name"); static const njs_value_t njs_error_stack_string = njs_string("stack"); +static const njs_value_t njs_error_errors_string = njs_string("errors"); void @@ -45,7 +46,7 @@ njs_error_new(njs_vm_t *vm, njs_value_t return; } - error = njs_error_alloc(vm, type, NULL, &string); + error = njs_error_alloc(vm, type, NULL, &string, NULL); if (njs_slow_path(error == NULL)) { return; } @@ -198,7 +199,7 @@ njs_error_stack(njs_vm_t *vm, njs_value_ njs_object_t * njs_error_alloc(njs_vm_t *vm, njs_object_type_t type, const njs_value_t *name, - const njs_value_t *message) + const njs_value_t *message, const njs_value_t *errors) { njs_int_t ret; njs_object_t *error; @@ -262,6 +263,26 @@ njs_error_alloc(njs_vm_t *vm, njs_object } } + if (errors != NULL) { + lhq.key = njs_str_value("errors"); + lhq.key_hash = NJS_ERRORS_HASH; + + prop = njs_object_prop_alloc(vm, &njs_error_errors_string, errors, 1); + if (njs_slow_path(prop == NULL)) { + goto memory_error; + } + + prop->enumerable = 0; + + lhq.value = prop; + + ret = njs_lvlhsh_insert(&error->hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NULL; + } + } + return error; memory_error: @@ -277,10 +298,32 @@ njs_error_constructor(njs_vm_t *vm, njs_ njs_index_t type) { njs_int_t ret; - njs_value_t *value; + njs_value_t *iterator, *value, list; + njs_array_t *array; njs_object_t *error; - value = njs_arg(args, nargs, 1); + if (type != NJS_OBJ_TYPE_AGGREGATE_ERROR) { + iterator = NULL; + value = njs_arg(args, nargs, 1); + + njs_set_undefined(&list); + + } else { + iterator = njs_arg(args, nargs, 1); + value = njs_arg(args, nargs, 2); + + if (njs_slow_path(iterator->type < NJS_STRING)) { + njs_type_error(vm, "first argument is not iterable"); + return NJS_ERROR; + } + + array = njs_iterator_to_array(vm, iterator); + if (njs_slow_path(array == NULL)) { + return NJS_ERROR; + } + + njs_set_array(&list, array); + } if (njs_slow_path(!njs_is_string(value))) { if (!njs_is_undefined(value)) { @@ -292,7 +335,8 @@ njs_error_constructor(njs_vm_t *vm, njs_ } error = njs_error_alloc(vm, type, NULL, - njs_is_defined(value) ? value : NULL); + njs_is_defined(value) ? value : NULL, + njs_is_defined(&list) ? &list : NULL); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } @@ -543,6 +587,36 @@ const njs_object_init_t njs_uri_error_c }; +static const njs_object_prop_t njs_aggregate_error_constructor_properties[] = +{ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("AggregateError"), + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("prototype"), + .value = njs_prop_handler(njs_object_prototype_create), + }, +}; + + +const njs_object_init_t njs_aggregate_error_constructor_init = { + njs_aggregate_error_constructor_properties, + njs_nitems(njs_aggregate_error_constructor_properties), +}; + + void njs_memory_error_set(njs_vm_t *vm, njs_value_t *value) { @@ -1164,6 +1238,49 @@ const njs_object_type_init_t njs_uri_er }; +static const njs_object_prop_t njs_aggregate_error_prototype_properties[] = +{ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("AggregateError"), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("message"), + .value = njs_string(""), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, + .configurable = 1, + }, +}; + + +const njs_object_init_t njs_aggregate_error_prototype_init = { + njs_aggregate_error_prototype_properties, + njs_nitems(njs_aggregate_error_prototype_properties), +}; + + +const njs_object_type_init_t njs_aggregate_error_type_init = { + .constructor = njs_native_ctor(njs_error_constructor, 1, + NJS_OBJ_TYPE_AGGREGATE_ERROR), + .constructor_props = &njs_aggregate_error_constructor_init, + .prototype_props = &njs_aggregate_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, +}; + + static njs_int_t njs_add_backtrace_entry(njs_vm_t *vm, njs_arr_t *stack, njs_native_frame_t *native_frame) diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_error.h --- a/src/njs_error.h Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_error.h Wed Aug 11 21:48:51 2021 +0300 @@ -41,7 +41,8 @@ void njs_memory_error(njs_vm_t *vm); void njs_memory_error_set(njs_vm_t *vm, njs_value_t *value); njs_object_t *njs_error_alloc(njs_vm_t *vm, njs_object_type_t type, - const njs_value_t *name, const njs_value_t *message); + const njs_value_t *name, const njs_value_t *message, + const njs_value_t *errors); njs_int_t njs_error_to_string(njs_vm_t *vm, njs_value_t *retval, const njs_value_t *error); njs_int_t njs_error_stack(njs_vm_t *vm, njs_value_t *value, njs_value_t *stack); @@ -57,6 +58,7 @@ extern const njs_object_type_init_t njs extern const njs_object_type_init_t njs_type_error_type_init; extern const njs_object_type_init_t njs_uri_error_type_init; extern const njs_object_type_init_t njs_memory_error_type_init; +extern const njs_object_type_init_t njs_aggregate_error_type_init; njs_inline njs_int_t diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_fs.c --- a/src/njs_fs.c Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_fs.c Wed Aug 11 21:48:51 2021 +0300 @@ -1491,7 +1491,7 @@ njs_fs_error(njs_vm_t *vm, const char *s return NJS_ERROR; } - error = njs_error_alloc(vm, NJS_OBJ_TYPE_ERROR, NULL, &value); + error = njs_error_alloc(vm, NJS_OBJ_TYPE_ERROR, NULL, &value, NULL); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_iterator.c --- a/src/njs_iterator.c Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_iterator.c Wed Aug 11 21:48:51 2021 +0300 @@ -26,6 +26,9 @@ static njs_int_t njs_iterator_object_han njs_iterator_handler_t handler, njs_iterator_args_t *args, njs_value_t *key, int64_t i); +static njs_int_t njs_iterator_to_array_handler(njs_vm_t *vm, + njs_iterator_args_t *args, njs_value_t *value, int64_t index); + njs_int_t njs_array_iterator_create(njs_vm_t *vm, const njs_value_t *target, @@ -676,3 +679,45 @@ njs_iterator_object_handler(njs_vm_t *vm return ret; } + + +njs_array_t * +njs_iterator_to_array(njs_vm_t *vm, njs_value_t *iterator) +{ + int64_t length; + njs_int_t ret; + njs_iterator_args_t args; + + njs_memzero(&args, sizeof(njs_iterator_args_t)); + + ret = njs_object_length(vm, iterator, &length); + if (njs_slow_path(ret != NJS_OK)) { + return NULL; + } + + args.array = njs_array_alloc(vm, 1, length, 0); + if (njs_slow_path(args.array == NULL)) { + return NULL; + } + + args.value = iterator; + args.to = length; + + ret = njs_object_iterate(vm, &args, njs_iterator_to_array_handler); + if (njs_slow_path(ret == NJS_ERROR)) { + njs_mp_free(vm->mem_pool, args.array); + return NULL; + } + + return args.array; +} + + +static njs_int_t +njs_iterator_to_array_handler(njs_vm_t *vm, njs_iterator_args_t *args, + njs_value_t *value, int64_t index) +{ + args->array->start[index] = *value; + + return NJS_OK; +} diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_iterator.h --- a/src/njs_iterator.h Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_iterator.h Wed Aug 11 21:48:51 2021 +0300 @@ -36,6 +36,8 @@ njs_int_t njs_object_iterate(njs_vm_t *v njs_int_t njs_object_iterate_reverse(njs_vm_t *vm, njs_iterator_args_t *args, njs_iterator_handler_t handler); +njs_array_t *njs_iterator_to_array(njs_vm_t *vm, njs_value_t *iterator); + extern const njs_object_type_init_t njs_iterator_type_init; extern const njs_object_type_init_t njs_array_iterator_type_init; diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_object_hash.h --- a/src/njs_object_hash.h Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_object_hash.h Wed Aug 11 21:48:51 2021 +0300 @@ -343,6 +343,25 @@ 'E'), 'r'), 'r'), 'o'), 'r') +#define NJS_AGGREGATE_ERROR_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'A'), 'g'), 'g'), 'r'), 'e'), 'g'), 'a'), 't'), 'e'), \ + 'E'), 'r'), 'r'), 'o'), 'r') + + #define NJS_MESSAGE_HASH \ njs_djb_hash_add( \ njs_djb_hash_add( \ @@ -354,6 +373,16 @@ 'm'), 'e'), 's'), 's'), 'a'), 'g'), 'e') +#define NJS_ERRORS_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'e'), 'r'), 'r'), 'o'), 'r'), 's') + + #define NJS_MODE_HASH \ njs_djb_hash_add( \ njs_djb_hash_add( \ diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/njs_vm.h --- a/src/njs_vm.h Wed Aug 11 21:48:50 2021 +0300 +++ b/src/njs_vm.h Wed Aug 11 21:48:51 2021 +0300 @@ -86,6 +86,7 @@ typedef enum { NJS_OBJ_TYPE_TYPE_ERROR, NJS_OBJ_TYPE_URI_ERROR, NJS_OBJ_TYPE_MEMORY_ERROR, + NJS_OBJ_TYPE_AGGREGATE_ERROR, NJS_OBJ_TYPE_MAX, } njs_object_type_t; diff -r eb6c1c9823f1 -r ca2f051a4fc9 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Aug 11 21:48:50 2021 +0300 +++ b/src/test/njs_unit_test.c Wed Aug 11 21:48:51 2021 +0300 @@ -11134,6 +11134,26 @@ static njs_unit_test_t njs_test[] = { njs_str("var e = RangeError('e'); Object.preventExtensions(e);e"), njs_str("RangeError: e") }, + /* AggregateError. */ + + { njs_str("AggregateError()"), + njs_str("TypeError: first argument is not iterable") }, + + { njs_str("AggregateError([1, 2, 3])"), + njs_str("AggregateError") }, + + { njs_str("let e = AggregateError([1, 2, 3], 'm'); e.message"), + njs_str("m") }, + + { njs_str("let e = AggregateError([1, 2, 3], 'm'); e.errors"), + njs_str("1,2,3") }, + + { njs_str("let e = AggregateError('abc'); e.errors"), + njs_str("a,b,c") }, + + { njs_str("let e = AggregateError([1, 2, 3], 'm'); e"), + njs_str("AggregateError: m") }, + /* Memory object is immutable. */ { njs_str("var e = MemoryError('e'); e.name = 'E'"), _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel