[njs] Introduced AggregateError implementation.
Alexander Borisov
alexander.borisov at nginx.com
Wed Aug 11 18:49:51 UTC 2021
details: https://hg.nginx.org/njs/rev/ca2f051a4fc9
branches:
changeset: 1684:ca2f051a4fc9
user: Alexander Borisov <alexander.borisov at 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'"),
More information about the nginx-devel
mailing list