From 480d58508d159dc71b844f2b1ba9c421bfc2f67d Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Tue, 13 Sep 2016 16:19:26 +0300 Subject: [PATCH] Constructor function prototypes now have correct types and values. --- njs/njs_array.c | 3 +- njs/njs_array.h | 9 --- njs/njs_builtin.c | 49 ++++++++++--- njs/njs_date.c | 3 +- njs/njs_date.h | 6 -- njs/njs_function.c | 6 +- njs/njs_object.c | 52 ++++++++------ njs/njs_object.h | 6 -- njs/njs_regexp.c | 3 +- njs/njs_regexp.h | 16 ----- njs/njs_vm.c | 8 ++- njs/njs_vm.h | 150 ++++++++++++++++++++++++++------------- njs/test/njs_unit_test.c | 48 +++++++++++++ 13 files changed, 234 insertions(+), 125 deletions(-) diff --git a/njs/njs_array.c b/njs/njs_array.c index 70b0bcdf..de5d9e6c 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -133,7 +133,8 @@ njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare) array->start = array->data; nxt_lvlhsh_init(&array->object.hash); nxt_lvlhsh_init(&array->object.shared_hash); - array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY]; + array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY].object; + array->object.type = NJS_ARRAY; array->object.shared = 0; array->size = size; array->length = length; diff --git a/njs/njs_array.h b/njs/njs_array.h index f853f8a2..21539fcb 100644 --- a/njs/njs_array.h +++ b/njs/njs_array.h @@ -10,15 +10,6 @@ #define NJS_ARRAY_SPARE 8 -struct njs_array_s { - /* Must be aligned to njs_value_t. */ - njs_object_t object; - uint32_t size; - uint32_t length; - njs_value_t *start; - njs_value_t *data; -}; - njs_array_t *njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare); njs_ret_t njs_array_string_add(njs_vm_t *vm, njs_array_t *array, u_char *start, diff --git a/njs/njs_builtin.c b/njs/njs_builtin.c index ea1f3277..3d74d09e 100644 --- a/njs/njs_builtin.c +++ b/njs/njs_builtin.c @@ -37,10 +37,11 @@ typedef struct { nxt_int_t njs_builtin_objects_create(njs_vm_t *vm) { - nxt_int_t ret; - nxt_uint_t i; - njs_object_t *objects, *prototypes; - njs_function_t *functions, *constructors; + nxt_int_t ret; + nxt_uint_t i; + njs_object_t *objects; + njs_function_t *functions, *constructors; + njs_object_prototype_t *prototypes; static const njs_object_init_t *prototype_init[] = { &njs_object_prototype_init, @@ -53,6 +54,29 @@ njs_builtin_objects_create(njs_vm_t *vm) &njs_date_prototype_init, }; + static const njs_object_prototype_t prototype_values[] = { + { .object.type = NJS_OBJECT }, + { .object.type = NJS_ARRAY }, + + /* + * The .object.type field must be initialzed after the .value field, + * otherwise SunC 5.9 treats the .value as .object.value or so. + */ + { .object_value = { .value = njs_value(NJS_BOOLEAN, 0, 0.0), + .object.type = NJS_OBJECT_BOOLEAN } }, + + { .object_value = { .value = njs_value(NJS_NUMBER, 0, 0.0), + .object.type = NJS_OBJECT_NUMBER } }, + + { .object_value = { .value = njs_string(""), + .object.type = NJS_OBJECT_STRING } }, + + { .object.type = NJS_FUNCTION }, + { .object.type = NJS_REGEXP }, + + { .date = { .time = NJS_NAN, .object.type = NJS_DATE } }, + }; + static const njs_object_init_t *constructor_init[] = { &njs_object_constructor_init, &njs_array_constructor_init, @@ -172,7 +196,9 @@ njs_builtin_objects_create(njs_vm_t *vm) prototypes = vm->shared->prototypes; for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) { - ret = njs_object_hash_create(vm, &prototypes[i].shared_hash, + prototypes[i] = prototype_values[i]; + + ret = njs_object_hash_create(vm, &prototypes[i].object.shared_hash, prototype_init[i]->properties, prototype_init[i]->items); if (nxt_slow_path(ret != NXT_OK)) { @@ -180,6 +206,9 @@ njs_builtin_objects_create(njs_vm_t *vm) } } + prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern = + vm->empty_regexp.data.u.regexp->pattern; + constructors = vm->shared->constructors; for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) { @@ -249,22 +278,24 @@ njs_builtin_objects_clone(njs_vm_t *vm) size_t size; nxt_uint_t i; njs_value_t *values; - njs_object_t *function_prototype; + njs_object_t *object_prototype, *function_prototype; /* * Copy both prototypes and constructors arrays by one memcpy() * because they are stored together. */ - size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t) + size = NJS_PROTOTYPE_MAX * sizeof(njs_object_prototype_t) + NJS_CONSTRUCTOR_MAX * sizeof(njs_function_t); memcpy(vm->prototypes, vm->shared->prototypes, size); + object_prototype = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object; + for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) { - vm->prototypes[i].__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT]; + vm->prototypes[i].object.__proto__ = object_prototype; } - function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION]; + function_prototype = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION].object; values = vm->scopes[NJS_SCOPE_GLOBAL]; for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) { diff --git a/njs/njs_date.c b/njs/njs_date.c index 1ae2fee3..20ec407a 100644 --- a/njs/njs_date.c +++ b/njs/njs_date.c @@ -151,8 +151,9 @@ njs_date_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, nxt_lvlhsh_init(&date->object.hash); nxt_lvlhsh_init(&date->object.shared_hash); + date->object.type = NJS_DATE; date->object.shared = 0; - date->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_DATE]; + date->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_DATE].object; date->time = time; diff --git a/njs/njs_date.h b/njs/njs_date.h index b590e2c4..57f8ed92 100644 --- a/njs/njs_date.h +++ b/njs/njs_date.h @@ -8,12 +8,6 @@ #define _NJS_DATE_H_INCLUDED_ -struct njs_date_s { - njs_object_t object; - double time; -}; - - njs_ret_t njs_date_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); diff --git a/njs/njs_function.c b/njs/njs_function.c index ed97aecf..60304cc9 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -40,6 +40,7 @@ njs_function_alloc(njs_vm_t *vm) */ function->object.shared_hash = vm->shared->function_prototype_hash; + function->object.type = NJS_FUNCTION; function->object.shared = 1; function->args_offset = 1; @@ -69,7 +70,8 @@ njs_function_value_copy(njs_vm_t *vm, njs_value_t *value) if (nxt_fast_path(function != NULL)) { *function = *value->data.u.function; - function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION]; + function->object.__proto__ = + &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object; function->object.shared = 0; value->data.u.function = function; } @@ -527,7 +529,7 @@ njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, *function = *args[0].data.u.function; - function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION]; + function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object; function->object.shared = 0; if (nargs == 1) { diff --git a/njs/njs_object.c b/njs/njs_object.c index e1242e25..be0c6d0e 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -35,7 +35,8 @@ njs_object_alloc(njs_vm_t *vm) if (nxt_fast_path(object != NULL)) { nxt_lvlhsh_init(&object->hash); nxt_lvlhsh_init(&object->shared_hash); - object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT]; + object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object; + object->type = NJS_OBJECT; object->shared = 0; } @@ -58,7 +59,7 @@ njs_object_value_copy(njs_vm_t *vm, njs_value_t *value) if (nxt_fast_path(object != NULL)) { *object = *value->data.u.object; - object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT]; + object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object; object->shared = 0; value->data.u.object = object; } @@ -78,10 +79,11 @@ njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value, nxt_uint_t type) if (nxt_fast_path(ov != NULL)) { nxt_lvlhsh_init(&ov->object.hash); nxt_lvlhsh_init(&ov->object.shared_hash); + ov->object.type = njs_object_value_type(type); ov->object.shared = 0; index = njs_primitive_prototype_index(type); - ov->object.__proto__ = &vm->prototypes[index]; + ov->object.__proto__ = &vm->prototypes[index].object; ov->value = *value; } @@ -258,7 +260,7 @@ njs_object_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, return NXT_ERROR; } - type = NJS_OBJECT + value->type; + type = njs_object_value_type(value->type); } else { vm->exception = &njs_exception_type_error; @@ -324,6 +326,7 @@ njs_object_create(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value) { + nxt_uint_t index; njs_object_t *proto; /* @@ -331,14 +334,15 @@ njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value) * and have to return different results for primitive type and for objects. */ if (njs_is_object(value)) { - proto = value->data.u.object->__proto__; + proto = value->data.u.object->__proto__; } else { - proto = &vm->prototypes[njs_primitive_prototype_index(value->type)]; + index = njs_primitive_prototype_index(value->type); + proto = &vm->prototypes[index].object; } vm->retval.data.u.object = proto; - vm->retval.type = NJS_OBJECT; + vm->retval.type = proto->type; vm->retval.data.truth = 1; return NXT_OK; @@ -364,7 +368,7 @@ njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value) if (index >= 0 && index < NJS_PROTOTYPE_MAX) { proto = njs_property_prototype_create(vm, &function->object.hash, - &vm->prototypes[index]); + &vm->prototypes[index].object); } if (proto == NULL) { @@ -395,7 +399,7 @@ njs_property_prototype_create(njs_vm_t *vm, nxt_lvlhsh_t *hash, /* GC */ prop->value.data.u.object = prototype; - prop->value.type = NJS_OBJECT; + prop->value.type = prototype->type; prop->value.data.truth = 1; prop->enumerable = 0; @@ -469,7 +473,7 @@ njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value) if (nxt_fast_path(proto != NULL)) { vm->retval.data.u.object = proto; - vm->retval.type = NJS_OBJECT; + vm->retval.type = proto->type; vm->retval.data.truth = 1; } else { @@ -489,23 +493,25 @@ njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value) static njs_ret_t njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value) { - int32_t index; - njs_value_t *cons; - njs_object_t *prototype; + int32_t index; + njs_value_t *cons; + njs_object_t *object; + njs_object_prototype_t *prototype; if (njs_is_object(value)) { - prototype = value->data.u.object; + object = value->data.u.object; do { + prototype = (njs_object_prototype_t *) object; index = prototype - vm->prototypes; if (index >= 0 && index < NJS_PROTOTYPE_MAX) { goto found; } - prototype = prototype->__proto__; + object = object->__proto__; - } while (prototype != NULL); + } while (object != NULL); nxt_thread_log_alert("prototype not found"); @@ -518,7 +524,7 @@ njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value) found: - cons = njs_property_constructor_create(vm, &prototype->hash, + cons = njs_property_constructor_create(vm, &prototype->object.hash, &vm->scopes[NJS_SCOPE_GLOBAL][index]); if (nxt_fast_path(cons != NULL)) { vm->retval = *cons; @@ -604,8 +610,9 @@ njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - int32_t index; - njs_object_t *prototype; + int32_t index; + njs_object_t *object; + njs_object_prototype_t *prototype; static const njs_value_t *class_name[] = { /* Primitives. */ @@ -633,9 +640,10 @@ njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, index = args[0].type; if (njs_is_object(&args[0])) { - prototype = args[0].data.u.object; + object = args[0].data.u.object; do { + prototype = (njs_object_prototype_t *) object; index = prototype - vm->prototypes; if (index >= 0 && index < NJS_PROTOTYPE_MAX) { @@ -643,9 +651,9 @@ njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, goto found; } - prototype = prototype->__proto__; + object = object->__proto__; - } while (prototype != NULL); + } while (object != NULL); nxt_thread_log_alert("prototype not found"); diff --git a/njs/njs_object.h b/njs/njs_object.h index a7a81c08..c88fc8f4 100644 --- a/njs/njs_object.h +++ b/njs/njs_object.h @@ -8,12 +8,6 @@ #define _NJS_OBJECT_H_INCLUDED_ -struct njs_object_value_s { - njs_object_t object; - njs_value_t value; -}; - - typedef enum { NJS_PROPERTY = 0, NJS_GETTER, diff --git a/njs/njs_regexp.c b/njs/njs_regexp.c index 3a9d068f..157d454b 100644 --- a/njs/njs_regexp.c +++ b/njs/njs_regexp.c @@ -466,7 +466,8 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern) if (nxt_fast_path(regexp != NULL)) { nxt_lvlhsh_init(®exp->object.hash); nxt_lvlhsh_init(®exp->object.shared_hash); - regexp->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_REGEXP]; + regexp->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_REGEXP].object; + regexp->object.type = NJS_REGEXP; regexp->object.shared = 0; regexp->last_index = 0; regexp->pattern = pattern; diff --git a/njs/njs_regexp.h b/njs/njs_regexp.h index a9aaf73f..85d3e3e8 100644 --- a/njs/njs_regexp.h +++ b/njs/njs_regexp.h @@ -16,22 +16,6 @@ typedef enum { } njs_regexp_flags_t; -struct njs_regexp_s { - /* Must be aligned to njs_value_t. */ - njs_object_t object; - - uint32_t last_index; - - njs_regexp_pattern_t *pattern; - - /* - * This string value can be unaligned since - * it never used in nJSVM operations. - */ - njs_value_t string; -}; - - njs_ret_t njs_regexp_init(njs_vm_t *vm); njs_ret_t njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); diff --git a/njs/njs_vm.c b/njs/njs_vm.c index e7b61ec8..260e2be4 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -403,7 +403,8 @@ njs_vmcode_function(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2) function = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t)); if (nxt_fast_path(function != NULL)) { - function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION]; + function->object.__proto__ = + &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object; function->args_offset = 1; code = (njs_vmcode_function_t *) vm->current; @@ -929,7 +930,8 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, return NJS_PRIMITIVE_VALUE; } - obj = &vm->prototypes[njs_primitive_prototype_index(object->type)]; + index = njs_primitive_prototype_index(object->type); + obj = &vm->prototypes[index].object; break; case NJS_STRING: @@ -937,7 +939,7 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, return NXT_DECLINED; } - obj = &vm->prototypes[NJS_PROTOTYPE_STRING]; + obj = &vm->prototypes[NJS_PROTOTYPE_STRING].object; break; case NJS_ARRAY: diff --git a/njs/njs_vm.h b/njs/njs_vm.h index a9289e74..9aab8025 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -111,6 +111,7 @@ typedef njs_ret_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args, typedef struct njs_string_s njs_string_t; +typedef struct njs_object_s njs_object_t; typedef struct njs_object_init_s njs_object_init_t; typedef struct njs_object_value_s njs_object_value_t; typedef struct njs_array_s njs_array_t; @@ -123,53 +124,6 @@ typedef struct njs_native_frame_s njs_native_frame_t; typedef struct njs_property_next_s njs_property_next_t; -typedef struct njs_object_s njs_object_t; - -struct njs_object_s { - /* A private hash of njs_object_prop_t. */ - nxt_lvlhsh_t hash; - - /* A shared hash of njs_object_prop_t. */ - nxt_lvlhsh_t shared_hash; - - /* An object __proto__. */ - njs_object_t *__proto__; - - uint32_t shared; /* 1 bit */ -}; - - -#define NJS_ARGS_TYPES_MAX 5 - -struct njs_function_s { - njs_object_t object; - - uint8_t args_types[NJS_ARGS_TYPES_MAX]; - uint8_t args_offset; - - /* - * TODO Shared - * When function object is used as value: in assignments, - * as function argument, as property and as object to get properties. - */ - -#if (NXT_64BIT) - uint8_t native; - uint8_t continuation_size; -#else - uint8_t native; - uint8_t continuation_size; -#endif - - union { - njs_function_lambda_t *lambda; - njs_function_native_t native; - } u; - - njs_value_t *bound; -}; - - typedef struct njs_continuation_s njs_continuation_t; struct njs_continuation_s { @@ -246,6 +200,97 @@ union njs_value_s { }; +struct njs_object_s { + /* A private hash of njs_object_prop_t. */ + nxt_lvlhsh_t hash; + + /* A shared hash of njs_object_prop_t. */ + nxt_lvlhsh_t shared_hash; + + /* An object __proto__. */ + njs_object_t *__proto__; + + /* The type is used in constructor prototypes. */ + njs_value_type_t type:8; + uint8_t shared; /* 1 bit */ +}; + + +struct njs_object_value_s { + njs_object_t object; + /* The value can be unaligned since it never used in nJSVM operations. */ + njs_value_t value; +}; + + +struct njs_array_s { + njs_object_t object; + uint32_t size; + uint32_t length; + njs_value_t *start; + njs_value_t *data; +}; + + +#define NJS_ARGS_TYPES_MAX 5 + +struct njs_function_s { + njs_object_t object; + + uint8_t args_types[NJS_ARGS_TYPES_MAX]; + uint8_t args_offset; + + /* + * TODO Shared + * When function object is used as value: in assignments, + * as function argument, as property and as object to get properties. + */ + +#if (NXT_64BIT) + uint8_t native; + uint8_t continuation_size; +#else + uint8_t native; + uint8_t continuation_size; +#endif + + union { + njs_function_lambda_t *lambda; + njs_function_native_t native; + } u; + + njs_value_t *bound; +}; + + +struct njs_regexp_s { + njs_object_t object; + uint32_t last_index; + njs_regexp_pattern_t *pattern; + /* + * This string value can be unaligned since + * it never used in nJSVM operations. + */ + njs_value_t string; +}; + + +struct njs_date_s { + njs_object_t object; + double time; +}; + + +typedef union { + njs_object_t object; + njs_object_value_t object_value; + njs_array_t array; + njs_function_t function; + njs_regexp_t regexp; + njs_date_t date; +} njs_object_prototype_t; + + #define njs_value(_type, _truth, _number) { \ .data = { \ .type = _type, \ @@ -367,6 +412,10 @@ typedef njs_ret_t (*njs_vmcode_operation_t)(njs_vm_t *vm, njs_value_t *value1, (((value)->type & NJS_OBJECT) != 0) +#define njs_object_value_type(type) \ + (type + NJS_OBJECT) + + #define njs_is_array(value) \ ((value)->type == NJS_ARRAY) @@ -683,6 +732,9 @@ enum njs_prototypes_e { #define njs_primitive_prototype_index(type) \ (NJS_PROTOTYPE_BOOLEAN + ((type) - NJS_BOOLEAN)) +#define njs_prototype_type(index) \ + (index + NJS_OBJECT) + enum njs_constructor_e { NJS_CONSTRUCTOR_OBJECT = NJS_PROTOTYPE_OBJECT, @@ -788,7 +840,7 @@ struct njs_vm_s { * they are copied from njs_vm_shared_t by single memcpy() * in njs_builtin_objects_clone(). */ - njs_object_t prototypes[NJS_PROTOTYPE_MAX]; + njs_object_prototype_t prototypes[NJS_PROTOTYPE_MAX]; njs_function_t constructors[NJS_CONSTRUCTOR_MAX]; nxt_mem_cache_pool_t *mem_cache_pool; @@ -829,7 +881,7 @@ struct njs_vm_shared_s { * The prototypes and constructors arrays must be togther because they are * copied to njs_vm_t by single memcpy() in njs_builtin_objects_clone(). */ - njs_object_t prototypes[NJS_PROTOTYPE_MAX]; + njs_object_prototype_t prototypes[NJS_PROTOTYPE_MAX]; njs_function_t constructors[NJS_CONSTRUCTOR_MAX]; }; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 5714ebf0..0601e401 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -4097,6 +4097,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.prototype.__proto__ === null"), nxt_string("true") }, + { nxt_string("Object.prototype.toString.call(Object.prototype)"), + nxt_string("[object Object]") }, + + { nxt_string("Object.prototype"), + nxt_string("[object Object]") }, + { nxt_string("Object.constructor === Function"), nxt_string("true") }, @@ -4154,6 +4160,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("Array.prototype.__proto__ === Object.prototype"), nxt_string("true") }, + { nxt_string("Object.prototype.toString.call(Array.prototype)"), + nxt_string("[object Array]") }, + + { nxt_string("Array.prototype"), + nxt_string("") }, + { nxt_string("Array.constructor === Function"), nxt_string("true") }, @@ -4211,6 +4223,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("Boolean.prototype.__proto__ === Object.prototype"), nxt_string("true") }, + { nxt_string("Object.prototype.toString.call(Boolean.prototype)"), + nxt_string("[object Boolean]") }, + + { nxt_string("Boolean.prototype"), + nxt_string("false") }, + { nxt_string("Boolean.constructor === Function"), nxt_string("true") }, @@ -4264,6 +4282,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("Number.prototype.__proto__ === Object.prototype"), nxt_string("true") }, + { nxt_string("Object.prototype.toString.call(Number.prototype)"), + nxt_string("[object Number]") }, + + { nxt_string("Number.prototype"), + nxt_string("0") }, + { nxt_string("Number.constructor === Function"), nxt_string("true") }, @@ -4314,6 +4338,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("String.__proto__ === Function.prototype"), nxt_string("true") }, + { nxt_string("Object.prototype.toString.call(String.prototype)"), + nxt_string("[object String]") }, + + { nxt_string("String.prototype"), + nxt_string("") }, + { nxt_string("String.prototype.length"), nxt_string("0") }, @@ -4359,6 +4389,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("Function.prototype.__proto__ === Object.prototype"), nxt_string("true") }, + { nxt_string("Object.prototype.toString.call(Function.prototype)"), + nxt_string("[object Function]") }, + + { nxt_string("Function.prototype"), + nxt_string("[object Function]") }, + { nxt_string("Function.constructor === Function"), nxt_string("true") }, @@ -4389,6 +4425,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("RegExp.prototype.__proto__ === Object.prototype"), nxt_string("true") }, + { nxt_string("Object.prototype.toString.call(RegExp.prototype)"), + nxt_string("[object RegExp]") }, + + { nxt_string("RegExp.prototype"), + nxt_string("/(?:)/") }, + { nxt_string("RegExp.constructor === Function"), nxt_string("true") }, @@ -4801,6 +4843,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("Date.prototype.__proto__ === Object.prototype"), nxt_string("true") }, + { nxt_string("Date.prototype"), + nxt_string("Invalid Date") }, + + { nxt_string("Date.prototype.valueOf()"), + nxt_string("NaN") }, + { nxt_string("Date.constructor === Function"), nxt_string("true") }, -- 2.47.3