From 7eb71ee59257c398a5d11af310ca0cc3daa41def Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Thu, 24 Oct 2019 16:17:16 +0300 Subject: [PATCH] Refactoring Error value types. Eliminating special value types (njs_value_type_t) for error instance objects. According to the spec error instance objects are ordinary objects which have an [[ErrorData]] internal slot. --- src/njs_builtin.c | 16 ++++++++-------- src/njs_error.c | 38 ++++++++++++++++++++------------------ src/njs_error.h | 22 +++++++++++----------- src/njs_fs.c | 4 ++-- src/njs_generator.c | 3 ++- src/njs_json.c | 11 ++--------- src/njs_module.c | 1 + src/njs_object.c | 15 ++++++--------- src/njs_parser.c | 6 +++--- src/njs_parser.h | 9 +++++---- src/njs_value.c | 32 -------------------------------- src/njs_value.h | 29 ++++++++++++++--------------- src/njs_vm.c | 10 +++++++--- src/njs_vm.h | 6 +++--- src/njs_vmcode.c | 10 +--------- src/test/njs_unit_test.c | 12 ++++++++++++ 16 files changed, 97 insertions(+), 127 deletions(-) diff --git a/src/njs_builtin.c b/src/njs_builtin.c index 6d3438c6..acdf8fec 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -152,14 +152,14 @@ const njs_object_prototype_t njs_prototype_values[] = { { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0), .object = { .type = NJS_OBJECT } } }, - { .object = { .type = NJS_OBJECT_ERROR } }, - { .object = { .type = NJS_OBJECT_EVAL_ERROR } }, - { .object = { .type = NJS_OBJECT_INTERNAL_ERROR } }, - { .object = { .type = NJS_OBJECT_RANGE_ERROR } }, - { .object = { .type = NJS_OBJECT_REF_ERROR } }, - { .object = { .type = NJS_OBJECT_SYNTAX_ERROR } }, - { .object = { .type = NJS_OBJECT_TYPE_ERROR } }, - { .object = { .type = NJS_OBJECT_URI_ERROR } }, + { .object = { .type = NJS_OBJECT } }, + { .object = { .type = NJS_OBJECT } }, + { .object = { .type = NJS_OBJECT } }, + { .object = { .type = NJS_OBJECT } }, + { .object = { .type = NJS_OBJECT } }, + { .object = { .type = NJS_OBJECT } }, + { .object = { .type = NJS_OBJECT } }, + { .object = { .type = NJS_OBJECT } }, }; diff --git a/src/njs_error.c b/src/njs_error.c index 682be041..9baa9b83 100644 --- a/src/njs_error.c +++ b/src/njs_error.c @@ -13,7 +13,7 @@ static const njs_value_t njs_error_name_string = njs_string("name"); void -njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, +njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_prototype_t type, u_char *start, size_t size) { ssize_t length; @@ -36,12 +36,12 @@ njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, return; } - njs_set_type_object(dst, error, type); + njs_set_object(dst, error); } void -njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, +njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_prototype_t type, const char *fmt, ...) { va_list args; @@ -60,7 +60,7 @@ njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, njs_object_t * -njs_error_alloc(njs_vm_t *vm, njs_value_type_t type, const njs_value_t *name, +njs_error_alloc(njs_vm_t *vm, njs_prototype_t type, const njs_value_t *name, const njs_value_t *message) { njs_int_t ret; @@ -75,10 +75,11 @@ njs_error_alloc(njs_vm_t *vm, njs_value_type_t type, const njs_value_t *name, njs_lvlhsh_init(&error->hash); njs_lvlhsh_init(&error->shared_hash); - error->type = type; + error->type = NJS_OBJECT; error->shared = 0; error->extensible = 1; - error->__proto__ = &vm->prototypes[njs_error_prototype_index(type)].object; + error->error_data = 1; + error->__proto__ = &vm->prototypes[type].object; lhq.replace = 0; lhq.pool = vm->mem_pool; @@ -135,7 +136,7 @@ memory_error: static njs_int_t njs_error_create(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_value_type_t type) + njs_prototype_t type) { njs_int_t ret; njs_value_t *value; @@ -158,7 +159,7 @@ njs_error_create(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - njs_set_type_object(&vm->retval, error, type); + njs_set_object(&vm->retval, error); return NJS_OK; } @@ -168,7 +169,7 @@ njs_int_t njs_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_ERROR); } @@ -210,7 +211,7 @@ njs_int_t njs_eval_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_EVAL_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_EVAL_ERROR); } @@ -252,7 +253,7 @@ njs_int_t njs_internal_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_INTERNAL_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_INTERNAL_ERROR); } @@ -294,7 +295,7 @@ njs_int_t njs_range_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_RANGE_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_RANGE_ERROR); } @@ -336,7 +337,7 @@ njs_int_t njs_reference_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_REF_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_REF_ERROR); } @@ -378,7 +379,7 @@ njs_int_t njs_syntax_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_SYNTAX_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_SYNTAX_ERROR); } @@ -420,7 +421,7 @@ njs_int_t njs_type_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_TYPE_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_TYPE_ERROR); } @@ -462,7 +463,7 @@ njs_int_t njs_uri_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_error_create(vm, args, nargs, NJS_OBJECT_URI_ERROR); + return njs_error_create(vm, args, nargs, NJS_PROTOTYPE_URI_ERROR); } @@ -512,7 +513,7 @@ njs_memory_error_set(njs_vm_t *vm, njs_value_t *value) njs_lvlhsh_init(&object->hash); njs_lvlhsh_init(&object->shared_hash); object->__proto__ = &prototypes[NJS_PROTOTYPE_INTERNAL_ERROR].object; - object->type = NJS_OBJECT_INTERNAL_ERROR; + object->type = NJS_OBJECT; object->shared = 1; /* @@ -520,8 +521,9 @@ njs_memory_error_set(njs_vm_t *vm, njs_value_t *value) * it from ordinary internal errors. */ object->extensible = 0; + object->error_data = 1; - njs_set_type_object(value, object, NJS_OBJECT_INTERNAL_ERROR); + njs_set_object(value, object); } diff --git a/src/njs_error.h b/src/njs_error.h index ac94d8d0..efc580c0 100644 --- a/src/njs_error.h +++ b/src/njs_error.h @@ -9,38 +9,38 @@ #define njs_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_ERROR, fmt, ##__VA_ARGS__) #define njs_eval_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_EVAL_ERROR, fmt, \ + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_EVAL_ERROR, fmt, \ ##__VA_ARGS__) #define njs_internal_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_INTERNAL_ERROR, fmt, \ + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_INTERNAL_ERROR, fmt, \ ##__VA_ARGS__) #define njs_range_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_RANGE_ERROR, fmt, \ + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_RANGE_ERROR, fmt, \ ##__VA_ARGS__) #define njs_reference_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_REF_ERROR, fmt, \ + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_REF_ERROR, fmt, \ ##__VA_ARGS__) #define njs_syntax_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_SYNTAX_ERROR, fmt, \ + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_SYNTAX_ERROR, fmt, \ ##__VA_ARGS__) #define njs_type_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_TYPE_ERROR, fmt, \ + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_TYPE_ERROR, fmt, \ ##__VA_ARGS__) #define njs_uri_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_URI_ERROR, fmt, \ + njs_error_fmt_new(vm, &vm->retval, NJS_PROTOTYPE_URI_ERROR, fmt, \ ##__VA_ARGS__) -void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, +void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_prototype_t type, u_char *start, size_t size); void njs_noinline njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, - njs_value_type_t type, const char *fmt, ...); + njs_prototype_t type, const char *fmt, ...); 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_value_type_t type, +njs_object_t *njs_error_alloc(njs_vm_t *vm, njs_prototype_t type, const njs_value_t *name, const njs_value_t *message); njs_int_t njs_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); diff --git a/src/njs_fs.c b/src/njs_fs.c index 9d89df32..f2a053b8 100644 --- a/src/njs_fs.c +++ b/src/njs_fs.c @@ -1028,7 +1028,7 @@ njs_fs_error(njs_vm_t *vm, const char *syscall, const char *description, return NJS_ERROR; } - error = njs_error_alloc(vm, NJS_OBJECT_ERROR, NULL, &string); + error = njs_error_alloc(vm, NJS_PROTOTYPE_ERROR, NULL, &string); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } @@ -1101,7 +1101,7 @@ njs_fs_error(njs_vm_t *vm, const char *syscall, const char *description, } } - njs_set_type_object(retval, error, NJS_OBJECT_ERROR); + njs_set_object(retval, error); return NJS_ERROR; } diff --git a/src/njs_generator.c b/src/njs_generator.c index a4b43ce4..41a19c56 100644 --- a/src/njs_generator.c +++ b/src/njs_generator.c @@ -249,7 +249,8 @@ static njs_int_t njs_generate_function_debug(njs_vm_t *vm, #define njs_generate_syntax_error(vm, node, fmt, ...) \ - njs_parser_node_error(vm, node, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) + njs_parser_node_error(vm, node, NJS_PROTOTYPE_SYNTAX_ERROR, fmt, \ + ##__VA_ARGS__) static const njs_str_t no_label = njs_str(""); diff --git a/src/njs_json.c b/src/njs_json.c index 9dff7148..7867ffc6 100644 --- a/src/njs_json.c +++ b/src/njs_json.c @@ -2312,16 +2312,9 @@ njs_dump_value(njs_json_stringify_t *stringify, const njs_value_t *value, /* Fall through. */ + case NJS_OBJECT: case NJS_REGEXP: case NJS_DATE: - case NJS_OBJECT_ERROR: - case NJS_OBJECT_EVAL_ERROR: - case NJS_OBJECT_INTERNAL_ERROR: - case NJS_OBJECT_RANGE_ERROR: - case NJS_OBJECT_REF_ERROR: - case NJS_OBJECT_SYNTAX_ERROR: - case NJS_OBJECT_TYPE_ERROR: - case NJS_OBJECT_URI_ERROR: switch (value->type) { case NJS_NUMBER: @@ -2366,7 +2359,7 @@ memory_error: #define njs_dump_is_object(value) \ - (((value)->type == NJS_OBJECT) \ + (((value)->type == NJS_OBJECT && !njs_object(value)->error_data) \ || ((value)->type == NJS_ARRAY) \ || ((value)->type == NJS_OBJECT_VALUE) \ || ((value)->type == NJS_EXTERNAL \ diff --git a/src/njs_module.c b/src/njs_module.c index 1f3d508c..ecad60f9 100644 --- a/src/njs_module.c +++ b/src/njs_module.c @@ -539,6 +539,7 @@ njs_module_require(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, *object = module->object; object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object; object->shared = 0; + object->error_data = 0; njs_set_object(&vm->retval, object); diff --git a/src/njs_object.c b/src/njs_object.c index cb17691e..fb9d747a 100644 --- a/src/njs_object.c +++ b/src/njs_object.c @@ -43,6 +43,7 @@ njs_object_alloc(njs_vm_t *vm) object->type = NJS_OBJECT; object->shared = 0; object->extensible = 1; + object->error_data = 0; return object; } @@ -2057,7 +2058,7 @@ njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, { const njs_value_t *name; - static const njs_value_t *class_name[NJS_TYPE_MAX] = { + static const njs_value_t *class_name[NJS_VALUE_TYPE_MAX] = { /* Primitives. */ &njs_object_null_string, &njs_object_undefined_string, @@ -2086,19 +2087,15 @@ njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, &njs_object_function_string, &njs_object_regexp_string, &njs_object_date_string, - &njs_object_error_string, - &njs_object_error_string, - &njs_object_error_string, - &njs_object_error_string, - &njs_object_error_string, - &njs_object_error_string, - &njs_object_error_string, - &njs_object_error_string, &njs_object_object_string, }; name = class_name[args[0].type]; + if (njs_is_error(&args[0])) { + name = &njs_object_error_string; + } + if (njs_fast_path(name != NULL)) { vm->retval = *name; diff --git a/src/njs_parser.c b/src/njs_parser.c index c1620b7d..01a0f646 100644 --- a/src/njs_parser.c +++ b/src/njs_parser.c @@ -2300,7 +2300,7 @@ njs_parser_trace_handler(njs_trace_t *trace, njs_trace_data_t *td, static void njs_parser_scope_error(njs_vm_t *vm, njs_parser_scope_t *scope, - njs_value_type_t type, uint32_t line, const char *fmt, va_list args) + njs_prototype_t type, uint32_t line, const char *fmt, va_list args) { size_t width; u_char msg[NJS_MAX_ERROR_STR]; @@ -2333,7 +2333,7 @@ njs_parser_scope_error(njs_vm_t *vm, njs_parser_scope_t *scope, void njs_parser_lexer_error(njs_vm_t *vm, njs_parser_t *parser, - njs_value_type_t type, const char *fmt, ...) + njs_prototype_t type, const char *fmt, ...) { va_list args; @@ -2350,7 +2350,7 @@ njs_parser_lexer_error(njs_vm_t *vm, njs_parser_t *parser, void njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, - njs_value_type_t type, const char *fmt, ...) + njs_prototype_t type, const char *fmt, ...) { va_list args; diff --git a/src/njs_parser.h b/src/njs_parser.h index 066f96ad..7d0d46e3 100644 --- a/src/njs_parser.h +++ b/src/njs_parser.h @@ -109,9 +109,9 @@ njs_token_t njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser, u_char *njs_parser_trace_handler(njs_trace_t *trace, njs_trace_data_t *td, u_char *start); void njs_parser_lexer_error(njs_vm_t *vm, njs_parser_t *parser, - njs_value_type_t type, const char *fmt, ...); + njs_prototype_t type, const char *fmt, ...); void njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, - njs_value_type_t type, const char *fmt, ...); + njs_prototype_t type, const char *fmt, ...); #define njs_parser_enter(vm, parser) \ @@ -155,12 +155,13 @@ void njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, #define njs_parser_syntax_error(vm, parser, fmt, ...) \ - njs_parser_lexer_error(vm, parser, NJS_OBJECT_SYNTAX_ERROR, fmt, \ + njs_parser_lexer_error(vm, parser, NJS_PROTOTYPE_SYNTAX_ERROR, fmt, \ ##__VA_ARGS__) #define njs_parser_ref_error(vm, parser, fmt, ...) \ - njs_parser_lexer_error(vm, parser, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) + njs_parser_lexer_error(vm, parser, NJS_PROTOTYPE_REF_ERROR, fmt, \ + ##__VA_ARGS__) njs_inline njs_token_t diff --git a/src/njs_value.c b/src/njs_value.c index 4d0cf7e8..95713486 100644 --- a/src/njs_value.c +++ b/src/njs_value.c @@ -342,30 +342,6 @@ njs_type_string(njs_value_type_t type) case NJS_DATE: return "date"; - case NJS_OBJECT_ERROR: - return "error"; - - case NJS_OBJECT_EVAL_ERROR: - return "eval error"; - - case NJS_OBJECT_INTERNAL_ERROR: - return "internal error"; - - case NJS_OBJECT_RANGE_ERROR: - return "range error"; - - case NJS_OBJECT_REF_ERROR: - return "reference error"; - - case NJS_OBJECT_SYNTAX_ERROR: - return "syntax error"; - - case NJS_OBJECT_TYPE_ERROR: - return "type error"; - - case NJS_OBJECT_URI_ERROR: - return "uri error"; - default: return NULL; } @@ -558,14 +534,6 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *value, case NJS_OBJECT_STRING: case NJS_REGEXP: case NJS_DATE: - case NJS_OBJECT_ERROR: - case NJS_OBJECT_EVAL_ERROR: - case NJS_OBJECT_INTERNAL_ERROR: - case NJS_OBJECT_RANGE_ERROR: - case NJS_OBJECT_REF_ERROR: - case NJS_OBJECT_SYNTAX_ERROR: - case NJS_OBJECT_TYPE_ERROR: - case NJS_OBJECT_URI_ERROR: case NJS_OBJECT_VALUE: obj = njs_object(value); break; diff --git a/src/njs_value.h b/src/njs_value.h index 2a713618..08046fdc 100644 --- a/src/njs_value.h +++ b/src/njs_value.h @@ -64,16 +64,8 @@ typedef enum { NJS_FUNCTION = 0x15, NJS_REGEXP = 0x16, NJS_DATE = 0x17, - NJS_OBJECT_ERROR = 0x18, - NJS_OBJECT_EVAL_ERROR = 0x19, - NJS_OBJECT_INTERNAL_ERROR = 0x1a, - NJS_OBJECT_RANGE_ERROR = 0x1b, - NJS_OBJECT_REF_ERROR = 0x1c, - NJS_OBJECT_SYNTAX_ERROR = 0x1d, - NJS_OBJECT_TYPE_ERROR = 0x1e, - NJS_OBJECT_URI_ERROR = 0x1f, - NJS_OBJECT_VALUE = 0x20, -#define NJS_TYPE_MAX (NJS_OBJECT_VALUE + 1) + NJS_OBJECT_VALUE = 0x18, +#define NJS_VALUE_TYPE_MAX (NJS_OBJECT_VALUE + 1) } njs_value_type_t; @@ -205,7 +197,9 @@ struct njs_object_s { /* The type is used in constructor prototypes. */ njs_value_type_t type:8; uint8_t shared; /* 1 bit */ - uint8_t extensible; /* 1 bit */ + + uint8_t extensible:1; + uint8_t error_data:1; }; @@ -459,10 +453,6 @@ typedef struct { #define njs_is_string(value) \ ((value)->type == NJS_STRING) -#define njs_is_error(value) \ - ((value)->type >= NJS_OBJECT_ERROR \ - && (value)->type <= NJS_OBJECT_URI_ERROR) - /* * The truth field coincides with short_string.size and short_string.length @@ -520,6 +510,11 @@ typedef struct { ((value)->type >= NJS_OBJECT) +#define njs_has_prototype(vm, value, proto) \ + (((njs_object_prototype_t *) \ + njs_object(value)->__proto__ - (vm)->prototypes) == proto) + + #define njs_is_object_value(value) \ ((value)->type == NJS_OBJECT_VALUE) @@ -552,6 +547,10 @@ typedef struct { ((value)->type == NJS_DATE) +#define njs_is_error(value) \ + ((value)->type == NJS_OBJECT && njs_object(value)->error_data) + + #define njs_is_external(value) \ ((value)->type == NJS_EXTERNAL) diff --git a/src/njs_vm.c b/src/njs_vm.c index 8564e2f3..422847d1 100644 --- a/src/njs_vm.c +++ b/src/njs_vm.c @@ -675,7 +675,7 @@ njs_vm_value_error_set(njs_vm_t *vm, njs_value_t *value, const char *fmt, ...) va_end(args); } - njs_error_new(vm, value, NJS_OBJECT_ERROR, buf, p - buf); + njs_error_new(vm, value, NJS_PROTOTYPE_ERROR, buf, p - buf); } @@ -1015,9 +1015,13 @@ njs_vm_value_to_string(njs_vm_t *vm, njs_str_t *dst, const njs_value_t *src) return NJS_ERROR; } - if (njs_slow_path(src->type == NJS_OBJECT_INTERNAL_ERROR)) { + if (njs_slow_path(njs_is_error(src))) { + /* MemoryError is a nonextensible internal error. */ - if (!njs_object(src)->extensible) { + + if (njs_has_prototype(vm, src, NJS_PROTOTYPE_INTERNAL_ERROR) + && !njs_object(src)->extensible) + { njs_string_get(&njs_string_memory_error, dst); return NJS_OK; } diff --git a/src/njs_vm.h b/src/njs_vm.h index a0e09838..86f9758b 100644 --- a/src/njs_vm.h +++ b/src/njs_vm.h @@ -81,7 +81,7 @@ typedef enum { (((index) & NJS_SCOPE_CALLEE_ARGUMENTS) == NJS_SCOPE_CALLEE_ARGUMENTS) -enum njs_prototypes_e { +typedef enum { NJS_PROTOTYPE_OBJECT = 0, NJS_PROTOTYPE_ARRAY, NJS_PROTOTYPE_BOOLEAN, @@ -101,7 +101,7 @@ enum njs_prototypes_e { NJS_PROTOTYPE_TYPE_ERROR, NJS_PROTOTYPE_URI_ERROR, #define NJS_PROTOTYPE_MAX (NJS_PROTOTYPE_URI_ERROR + 1) -}; +} njs_prototype_t; #define njs_primitive_prototype_index(type) \ @@ -266,7 +266,7 @@ struct njs_vm_s { /* * MemoryError is statically allocated immutable Error object - * with the generic type NJS_OBJECT_INTERNAL_ERROR. + * with the InternalError prototype. */ njs_object_t memory_error_object; diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c index 68d5a372..0527a9cd 100644 --- a/src/njs_vmcode.c +++ b/src/njs_vmcode.c @@ -1384,7 +1384,7 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld) { /* ECMAScript 5.1: null, array and regexp are objects. */ - static const njs_value_t *types[NJS_TYPE_MAX] = { + static const njs_value_t *types[NJS_VALUE_TYPE_MAX] = { &njs_string_object, &njs_string_undefined, &njs_string_boolean, @@ -1411,14 +1411,6 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld) &njs_string_object, &njs_string_object, &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, - &njs_string_object, }; vm->retval = *types[value->type]; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 67d35032..9e29ee4f 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -8670,6 +8670,9 @@ static njs_unit_test_t njs_test[] = { njs_str("RangeError('e')"), njs_str("RangeError: e") }, + { njs_str("var e = RangeError('e'); Object.preventExtensions(e);e"), + njs_str("RangeError: e") }, + { njs_str("ReferenceError('e')"), njs_str("ReferenceError: e") }, @@ -9532,6 +9535,9 @@ static njs_unit_test_t njs_test[] = { njs_str("Object.prototype.toString.call(new URIError)"), njs_str("[object Error]") }, + { njs_str("Object.prototype.toString.call(URIError.prototype)"), + njs_str("[object Object]") }, + { njs_str("Object.prototype"), njs_str("[object Object]") }, @@ -10264,6 +10270,9 @@ static njs_unit_test_t njs_test[] = { njs_str("var fn = (function() { return new Function('return this'); }).call({}), o = {}; fn.call(o) == o && fn.bind(o).call(this) == o"), njs_str("true") }, + { njs_str("this.NN = {}; var f = Function('eval = 42;'); f()"), + njs_str("SyntaxError: Identifier \"eval\" is forbidden as left-hand in assignment in runtime:1") }, + { njs_str("RegExp()"), njs_str("/(?:)/") }, @@ -14029,6 +14038,9 @@ static njs_unit_test_t njs_test[] = { njs_str("njs.dump({a:1, b:[1,,2,{c:new Boolean(1)}]})"), njs_str("{a:1,b:[1,,2,{c:[Boolean: true]}]}") }, + { njs_str("njs.dump([InternalError(),TypeError('msg'), new RegExp(), /^undef$/m, new Date(0)])"), + njs_str("[InternalError,TypeError: msg,/(?:)/,/^undef$/m,1970-01-01T00:00:00.000Z]") }, + { njs_str("njs.dump(Array.prototype.slice.call({'1':'b', length:2}))"), njs_str("[,'b']") }, -- 2.47.3