From: Dmitry Volyntsev Date: Fri, 12 Apr 2019 15:36:02 +0000 (+0300) Subject: Fixed objects instance properties. X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=06076082eaa52e78a14b48db204456963c2390c9;p=njs.git Fixed objects instance properties. Some properties like 'length' of Array, String or Function objects should be instance properties not prototype properties. --- diff --git a/njs/njs_array.c b/njs/njs_array.c index f605428a..635561b4 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -149,7 +149,7 @@ 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.shared_hash = vm->shared->array_instance_hash; array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY].object; array->object.type = NJS_ARRAY; array->object.shared = 0; @@ -401,8 +401,8 @@ const njs_object_init_t njs_array_constructor_init = { static njs_ret_t -njs_array_prototype_length(njs_vm_t *vm, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval) +njs_array_length(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { double num; int64_t size; @@ -2214,7 +2214,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY_HANDLER, .name = njs_string("length"), - .value = njs_prop_handler(njs_array_prototype_length), + .value = njs_prop_handler(njs_array_length), .writable = 1 }, @@ -2395,3 +2395,21 @@ const njs_object_init_t njs_array_prototype_init = { njs_array_prototype_properties, nxt_nitems(njs_array_prototype_properties), }; + + +const njs_object_prop_t njs_array_instance_properties[] = +{ + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("length"), + .value = njs_prop_handler(njs_array_length), + .writable = 1 + }, +}; + + +const njs_object_init_t njs_array_instance_init = { + nxt_string("Array instance"), + njs_array_instance_properties, + nxt_nitems(njs_array_instance_properties), +}; diff --git a/njs/njs_array.h b/njs/njs_array.h index d2c06f7a..5d13a8b3 100644 --- a/njs/njs_array.h +++ b/njs/njs_array.h @@ -26,6 +26,7 @@ njs_ret_t njs_array_constructor(njs_vm_t *vm, njs_value_t *args, extern const njs_object_init_t njs_array_constructor_init; extern const njs_object_init_t njs_array_prototype_init; +extern const njs_object_init_t njs_array_instance_init; #endif /* _NJS_ARRAY_H_INCLUDED_ */ diff --git a/njs/njs_builtin.c b/njs/njs_builtin.c index 82ecd6ee..56edb726 100644 --- a/njs/njs_builtin.c +++ b/njs/njs_builtin.c @@ -138,22 +138,6 @@ const njs_function_init_t njs_native_functions[] = { }; -const njs_object_prop_t njs_arguments_object_properties[] = -{ - { - .type = NJS_PROPERTY_HANDLER, - .name = njs_string("caller"), - .value = njs_prop_handler(njs_function_arguments_thrower), - }, - - { - .type = NJS_PROPERTY_HANDLER, - .name = njs_string("callee"), - .value = njs_prop_handler(njs_function_arguments_thrower), - }, -}; - - const njs_function_init_t njs_native_constructors[] = { /* SunC does not allow empty array initialization. */ { njs_object_constructor, { 0 } }, @@ -230,48 +214,61 @@ const njs_object_prototype_t njs_prototype_values[] = { }; +nxt_inline nxt_int_t +njs_object_hash_init(njs_vm_t *vm, nxt_lvlhsh_t *hash, + const njs_object_init_t *init) +{ + return njs_object_hash_create(vm, hash, init->properties, init->items); +} + nxt_int_t njs_builtin_objects_create(njs_vm_t *vm) { nxt_int_t ret; njs_module_t *module; - njs_object_t *object; + njs_object_t *object, *string_object; njs_function_t *func; nxt_lvlhsh_query_t lhq; + njs_vm_shared_t *shared; njs_object_prototype_t *prototype; const njs_object_init_t *obj, **p; const njs_function_init_t *f; - static const njs_object_prop_t function_prototype_property = { - .type = NJS_PROPERTY_HANDLER, - .name = njs_string("prototype"), - .value = njs_prop_handler(njs_function_prototype_create), - }; - static const nxt_str_t sandbox_key = nxt_string("sandbox"); - ret = njs_object_hash_create(vm, &vm->shared->function_prototype_hash, - &function_prototype_property, 1); + shared = vm->shared; + + ret = njs_object_hash_init(vm, &shared->array_instance_hash, + &njs_array_instance_init); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + ret = njs_object_hash_init(vm, &shared->string_instance_hash, + &njs_string_instance_init); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + ret = njs_object_hash_init(vm, &shared->function_instance_hash, + &njs_function_instance_init); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } - ret = njs_object_hash_create(vm, &vm->shared->arguments_object_hash, - njs_arguments_object_properties, - nxt_nitems(njs_arguments_object_properties)); + ret = njs_object_hash_init(vm, &shared->arguments_object_instance_hash, + &njs_arguments_object_instance_init); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } - object = vm->shared->objects; + object = shared->objects; for (p = njs_object_init; *p != NULL; p++) { obj = *p; - ret = njs_object_hash_create(vm, &object->shared_hash, - obj->properties, obj->items); - + ret = njs_object_hash_init(vm, &object->shared_hash, obj); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -295,8 +292,7 @@ njs_builtin_objects_create(njs_vm_t *vm) module->function.native = 1; - ret = njs_object_hash_create(vm, &module->object.shared_hash, - obj->properties, obj->items); + ret = njs_object_hash_init(vm, &module->object.shared_hash, obj); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -327,13 +323,12 @@ njs_builtin_objects_create(njs_vm_t *vm) } f = njs_native_functions; - func = vm->shared->functions; + func = shared->functions; for (p = njs_function_init; *p != NULL; p++) { obj = *p; - ret = njs_object_hash_create(vm, &func->object.shared_hash, - obj->properties, obj->items); + ret = njs_object_hash_init(vm, &func->object.shared_hash, obj); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -350,14 +345,13 @@ njs_builtin_objects_create(njs_vm_t *vm) func++; } - prototype = vm->shared->prototypes; + prototype = shared->prototypes; memcpy(prototype, njs_prototype_values, sizeof(njs_prototype_values)); for (p = njs_prototype_init; *p != NULL; p++) { obj = *p; - ret = njs_object_hash_create(vm, &prototype->object.shared_hash, - obj->properties, obj->items); + ret = njs_object_hash_init(vm, &prototype->object.shared_hash, obj); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -367,11 +361,19 @@ njs_builtin_objects_create(njs_vm_t *vm) prototype++; } - vm->shared->prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern = + shared->prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern = vm->shared->empty_regexp_pattern; + string_object = &shared->string_object; + nxt_lvlhsh_init(&string_object->hash); + string_object->shared_hash = vm->shared->string_instance_hash; + string_object->type = NJS_OBJECT_STRING; + string_object->shared = 1; + string_object->extensible = 0; + string_object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_STRING].object; + f = njs_native_constructors; - func = vm->shared->constructors; + func = shared->constructors; for (p = njs_constructor_init; *p != NULL; p++) { obj = *p; @@ -386,8 +388,7 @@ njs_builtin_objects_create(njs_vm_t *vm) memcpy(func->args_types, f->args_types, NJS_ARGS_TYPES_MAX); - ret = njs_object_hash_create(vm, &func->object.shared_hash, - obj->properties, obj->items); + ret = njs_object_hash_init(vm, &func->object.shared_hash, obj); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -523,6 +524,9 @@ njs_builtin_objects_clone(njs_vm_t *vm) vm->constructors[i].object.__proto__ = function_prototype; } + vm->string_object = vm->shared->string_object; + vm->string_object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_STRING].object; + return NXT_OK; } diff --git a/njs/njs_extern.c b/njs/njs_extern.c index c4600314..66cf27d3 100644 --- a/njs/njs_extern.c +++ b/njs/njs_extern.c @@ -109,7 +109,7 @@ njs_vm_external_add(njs_vm_t *vm, nxt_lvlhsh_t *hash, njs_external_t *external, function->object.__proto__ = &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION].object; - function->object.shared_hash = vm->shared->function_prototype_hash; + function->object.shared_hash = vm->shared->function_instance_hash; function->object.type = NJS_FUNCTION; function->object.shared = 1; function->object.extensible = 1; diff --git a/njs/njs_function.c b/njs/njs_function.c index a3435d68..03e65a06 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -42,7 +42,7 @@ njs_function_alloc(njs_vm_t *vm, njs_function_lambda_t *lambda, function->args_offset = 1; function->u.lambda = lambda; - function->object.shared_hash = vm->shared->function_prototype_hash; + function->object.shared_hash = vm->shared->function_instance_hash; function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object; function->object.type = NJS_FUNCTION; function->object.shared = shared; @@ -162,7 +162,7 @@ njs_function_arguments_object_init(njs_vm_t *vm, njs_native_frame_t *frame) return NXT_ERROR; } - arguments->shared_hash = vm->shared->arguments_object_hash; + arguments->shared_hash = vm->shared->arguments_object_instance_hash; nargs = frame->nargs; @@ -250,7 +250,7 @@ njs_function_rest_parameters_init(njs_vm_t *vm, njs_native_frame_t *frame) } -njs_ret_t +static njs_ret_t njs_function_arguments_thrower(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { @@ -259,6 +259,29 @@ njs_function_arguments_thrower(njs_vm_t *vm, njs_value_t *value, } +const njs_object_prop_t njs_arguments_object_instance_properties[] = +{ + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("caller"), + .value = njs_prop_handler(njs_function_arguments_thrower), + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("callee"), + .value = njs_prop_handler(njs_function_arguments_thrower), + }, +}; + + +const njs_object_init_t njs_arguments_object_instance_init = { + nxt_string("Argument object instance"), + njs_arguments_object_instance_properties, + nxt_nitems(njs_arguments_object_instance_properties), +}; + + njs_ret_t njs_function_native_frame(njs_vm_t *vm, njs_function_t *function, const njs_value_t *this, const njs_value_t *args, nxt_uint_t nargs, @@ -861,7 +884,7 @@ const njs_object_init_t njs_function_constructor_init = { * the typical number of arguments expected by the function. */ static njs_ret_t -njs_function_prototype_length(njs_vm_t *vm, njs_value_t *value, +njs_function_instance_length(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { nxt_uint_t n; @@ -1117,9 +1140,9 @@ njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, static const njs_object_prop_t njs_function_prototype_properties[] = { { - .type = NJS_PROPERTY_HANDLER, + .type = NJS_PROPERTY, .name = njs_string("length"), - .value = njs_prop_handler(njs_function_prototype_length), + .value = njs_value(NJS_NUMBER, 0, 0.0), }, { @@ -1149,6 +1172,29 @@ const njs_object_init_t njs_function_prototype_init = { }; +const njs_object_prop_t njs_function_instance_properties[] = +{ + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("length"), + .value = njs_prop_handler(njs_function_instance_length), + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("prototype"), + .value = njs_prop_handler(njs_function_prototype_create), + }, +}; + + +const njs_object_init_t njs_function_instance_init = { + nxt_string("Function instance"), + njs_function_instance_properties, + nxt_nitems(njs_function_instance_properties), +}; + + njs_ret_t njs_eval_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) diff --git a/njs/njs_function.h b/njs/njs_function.h index 6d54b838..05b54531 100644 --- a/njs/njs_function.h +++ b/njs/njs_function.h @@ -153,8 +153,6 @@ njs_ret_t njs_function_arguments_object_init(njs_vm_t *vm, njs_native_frame_t *frame); njs_ret_t njs_function_rest_parameters_init(njs_vm_t *vm, njs_native_frame_t *frame); -njs_ret_t njs_function_arguments_thrower(njs_vm_t *vm, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval); njs_ret_t njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); njs_value_t *njs_function_property_prototype_create(njs_vm_t *vm, @@ -219,6 +217,8 @@ njs_function_previous_frame(njs_native_frame_t *frame) extern const njs_object_init_t njs_function_constructor_init; extern const njs_object_init_t njs_function_prototype_init; +extern const njs_object_init_t njs_function_instance_init; +extern const njs_object_init_t njs_arguments_object_instance_init; njs_ret_t njs_eval_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); diff --git a/njs/njs_number.c b/njs/njs_number.c index 3f8c1165..3a89c4db 100644 --- a/njs/njs_number.c +++ b/njs/njs_number.c @@ -820,29 +820,101 @@ njs_number_to_integer(double num) } +static const njs_object_prop_t njs_is_nan_function_properties[] = +{ + /* isNaN.name == "isNaN". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("isNaN"), + }, + + /* isNaN.length == 1. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + }, +}; + + const njs_object_init_t njs_is_nan_function_init = { nxt_string("isNaN"), - NULL, - 0, + njs_is_nan_function_properties, + nxt_nitems(njs_is_nan_function_properties), +}; + + +static const njs_object_prop_t njs_is_finite_function_properties[] = +{ + /* isFinite.name == "isFinite". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("isFinite"), + }, + + /* isFinite.length == 1. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + }, }; const njs_object_init_t njs_is_finite_function_init = { nxt_string("isFinite"), - NULL, - 0, + njs_is_finite_function_properties, + nxt_nitems(njs_is_finite_function_properties), +}; + + +static const njs_object_prop_t njs_parse_int_function_properties[] = +{ + /* parseInt.name == "parseInt". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("parseInt"), + }, + + /* parseInt.length == 2. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 2.0), + }, }; const njs_object_init_t njs_parse_int_function_init = { nxt_string("parseInt"), - NULL, - 0, + njs_parse_int_function_properties, + nxt_nitems(njs_parse_int_function_properties), +}; + + +static const njs_object_prop_t njs_parse_float_function_properties[] = +{ + /* parseFloat.name == "parseFloat". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("parseFloat"), + }, + + /* parseFloat.length == 1. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + }, }; const njs_object_init_t njs_parse_float_function_init = { nxt_string("parseFloat"), - NULL, - 0, + njs_parse_float_function_properties, + nxt_nitems(njs_parse_float_function_properties), }; diff --git a/njs/njs_object.c b/njs/njs_object.c index f2a0f38e..8c2126f9 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -294,7 +294,7 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, } } - obj = &vm->prototypes[NJS_PROTOTYPE_STRING].object; + obj = &vm->string_object; break; case NJS_OBJECT_STRING: @@ -764,6 +764,8 @@ njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq) return NXT_ERROR; } + function->object.shared_hash = vm->shared->function_instance_hash; + pq->lhq.replace = 0; pq->lhq.value = prop; pq->lhq.pool = vm->mem_pool; @@ -954,25 +956,20 @@ njs_array_t * njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, njs_object_enum_t kind, nxt_bool_t all) { - nxt_bool_t exotic_length; u_char *dst; uint32_t i, length, size, items_length, properties; njs_value_t *string, *item; njs_array_t *items, *array, *entry; nxt_lvlhsh_t *hash; const u_char *src, *end; + njs_object_t *object; njs_object_prop_t *prop; njs_string_prop_t string_prop; nxt_lvlhsh_each_t lhe; - static const njs_value_t njs_string_length = njs_string("length"); - - /* TODO: "length" is in a shared_hash. */ - - exotic_length = 0; - array = NULL; length = 0; + object = NULL; items_length = 0; switch (value->type) { @@ -986,8 +983,6 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, } } - exotic_length = all; - break; case NJS_STRING: @@ -997,19 +992,14 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, } else { string = (njs_value_t *) value; + object = &vm->string_object; } length = njs_string_prop(&string_prop, string); items_length += length; - exotic_length = all; break; - case NJS_FUNCTION: - exotic_length = all && (value->data.u.function->native == 0); - - /* Fall through. */ - default: break; } @@ -1019,8 +1009,12 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, properties = 0; if (nxt_fast_path(njs_is_object(value))) { + object = value->data.u.object; + } + + if (object != NULL) { nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &value->data.u.object->hash; + hash = &object->hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); @@ -1036,7 +1030,7 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, if (nxt_slow_path(all)) { nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &value->data.u.object->shared_hash; + hash = &object->shared_hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); @@ -1052,7 +1046,7 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, items_length += properties; } - items = njs_array_alloc(vm, items_length + exotic_length, NJS_ARRAY_SPARE); + items = njs_array_alloc(vm, items_length, NJS_ARRAY_SPARE); if (nxt_slow_path(items == NULL)) { return NULL; } @@ -1210,14 +1204,10 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, } } - if (nxt_slow_path(exotic_length != 0)) { - *item++ = njs_string_length; - } - if (nxt_fast_path(properties != 0)) { nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &value->data.u.object->hash; + hash = &object->hash; switch (kind) { @@ -1236,7 +1226,7 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, if (nxt_slow_path(all)) { nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &value->data.u.object->shared_hash; + hash = &object->shared_hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); diff --git a/njs/njs_string.c b/njs/njs_string.c index 4ccd3aa9..36e95dac 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -555,6 +555,8 @@ njs_string_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, return NXT_ERROR; } + object->shared_hash = vm->shared->string_instance_hash; + vm->retval.data.u.object = object; vm->retval.type = NJS_OBJECT_STRING; vm->retval.data.truth = 1; @@ -623,7 +625,7 @@ const njs_object_init_t njs_string_constructor_init = { static njs_ret_t -njs_string_prototype_length(njs_vm_t *vm, njs_value_t *value, +njs_string_instance_length(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { size_t size; @@ -3752,15 +3754,15 @@ njs_string_to_c_string(njs_vm_t *vm, njs_value_t *value) static const njs_object_prop_t njs_string_prototype_properties[] = { { - .type = NJS_PROPERTY_HANDLER, - .name = njs_string("__proto__"), - .value = njs_prop_handler(njs_primitive_prototype_get_proto), + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 0, 0.0), }, { .type = NJS_PROPERTY_HANDLER, - .name = njs_string("length"), - .value = njs_prop_handler(njs_string_prototype_length), + .name = njs_string("__proto__"), + .value = njs_prop_handler(njs_primitive_prototype_get_proto), }, { @@ -3973,6 +3975,23 @@ const njs_object_init_t njs_string_prototype_init = { }; +const njs_object_prop_t njs_string_instance_properties[] = +{ + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("length"), + .value = njs_prop_handler(njs_string_instance_length), + }, +}; + + +const njs_object_init_t njs_string_instance_init = { + nxt_string("String instance"), + njs_string_instance_properties, + nxt_nitems(njs_string_instance_properties), +}; + + /* * encodeURI(string) */ @@ -4448,36 +4467,126 @@ njs_value_index(njs_vm_t *vm, const njs_value_t *src, nxt_uint_t runtime) } +static const njs_object_prop_t njs_to_string_function_properties[] = +{ + /* toString.name == "toString". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("toString"), + }, + + /* toString.length == 0. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 0, 0.0), + }, +}; + + const njs_object_init_t njs_to_string_function_init = { nxt_string("toString"), - NULL, - 0, + njs_to_string_function_properties, + nxt_nitems(njs_to_string_function_properties), +}; + + +static const njs_object_prop_t njs_encode_uri_function_properties[] = +{ + /* encodeURI.name == "encodeURI". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("encodeURI"), + }, + + /* encodeURI.length == 1. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + }, }; const njs_object_init_t njs_encode_uri_function_init = { nxt_string("encodeURI"), - NULL, - 0, + njs_encode_uri_function_properties, + nxt_nitems(njs_encode_uri_function_properties), +}; + + +static const njs_object_prop_t njs_encode_uri_component_function_properties[] = +{ + /* encodeURIComponent.name == "encodeURIComponent". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_long_string("encodeURIComponent"), + }, + + /* encodeURIComponent.length == 1. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + }, }; const njs_object_init_t njs_encode_uri_component_function_init = { nxt_string("encodeURIComponent"), - NULL, - 0, + njs_encode_uri_component_function_properties, + nxt_nitems(njs_encode_uri_component_function_properties), +}; + + +static const njs_object_prop_t njs_decode_uri_function_properties[] = +{ + /* decodeURI.name == "decodeURI". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string("decodeURI"), + }, + + /* decodeURI.length == 1. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + }, }; const njs_object_init_t njs_decode_uri_function_init = { nxt_string("decodeURI"), - NULL, - 0, + njs_decode_uri_function_properties, + nxt_nitems(njs_decode_uri_function_properties), +}; + + +static const njs_object_prop_t njs_decode_uri_component_function_properties[] = +{ + /* decodeURIComponent.name == "decodeURIComponent". */ + { + .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_long_string("decodeURIComponent"), + }, + + /* decodeURIComponent.length == 1. */ + { + .type = NJS_PROPERTY, + .name = njs_string("length"), + .value = njs_value(NJS_NUMBER, 1, 1.0), + }, }; const njs_object_init_t njs_decode_uri_component_function_init = { nxt_string("decodeURIComponent"), - NULL, - 0, + njs_decode_uri_component_function_properties, + nxt_nitems(njs_decode_uri_component_function_properties), }; diff --git a/njs/njs_string.h b/njs/njs_string.h index 314f76f3..d70a7dc0 100644 --- a/njs/njs_string.h +++ b/njs/njs_string.h @@ -177,6 +177,7 @@ njs_index_t njs_value_index(njs_vm_t *vm, const njs_value_t *src, extern const njs_object_init_t njs_string_constructor_init; extern const njs_object_init_t njs_string_prototype_init; +extern const njs_object_init_t njs_string_instance_init; extern const njs_object_init_t njs_to_string_function_init; extern const njs_object_init_t njs_encode_uri_function_init; diff --git a/njs/njs_vm.h b/njs/njs_vm.h index 8f3c9975..565620e4 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -1078,6 +1078,8 @@ struct njs_vm_s { */ njs_object_t memory_error_object; + njs_object_t string_object; + nxt_array_t *code; /* of njs_vm_code_t */ nxt_trace_t trace; @@ -1108,9 +1110,12 @@ typedef struct { struct njs_vm_shared_s { nxt_lvlhsh_t keywords_hash; nxt_lvlhsh_t values_hash; - nxt_lvlhsh_t function_prototype_hash; - nxt_lvlhsh_t arguments_object_hash; + nxt_lvlhsh_t array_instance_hash; + nxt_lvlhsh_t string_instance_hash; + nxt_lvlhsh_t function_instance_hash; + nxt_lvlhsh_t arguments_object_instance_hash; + njs_object_t string_object; njs_object_t objects[NJS_OBJECT_MAX]; njs_function_t functions[NJS_FUNCTION_MAX]; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index ede03192..6e1d9d86 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -3134,7 +3134,7 @@ static njs_unit_test_t njs_test[] = nxt_string("true") }, { nxt_string("var a = [1,2]; delete a.length"), - nxt_string("false") }, + nxt_string("TypeError: Cannot delete property \"length\" of array") }, { nxt_string("var a = [1,2,3]; a.x = 10; delete a[1]"), nxt_string("true") }, @@ -5638,6 +5638,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("String.bytesFrom('QUJDRA#', 'base64url')"), nxt_string("ABCD") }, + { nxt_string("encodeURI.name"), + nxt_string("encodeURI")}, + + { nxt_string("encodeURI.length"), + nxt_string("1")}, + { nxt_string("encodeURI()"), nxt_string("undefined")}, @@ -5647,9 +5653,21 @@ static njs_unit_test_t njs_test[] = { nxt_string("encodeURI('~}|{`_^]\\\\[@?>=<;:/.-,+*)(\\\'&%$#\"! ')"), nxt_string("~%7D%7C%7B%60_%5E%5D%5C%5B@?%3E=%3C;:/.-,+*)('&%25$#%22!%20")}, + { nxt_string("encodeURIComponent.name"), + nxt_string("encodeURIComponent")}, + + { nxt_string("encodeURIComponent.length"), + nxt_string("1")}, + { nxt_string("encodeURIComponent('~}|{`_^]\\\\[@?>=<;:/.-,+*)(\\\'&%$#\"! ')"), nxt_string("~%7D%7C%7B%60_%5E%5D%5C%5B%40%3F%3E%3D%3C%3B%3A%2F.-%2C%2B*)('%26%25%24%23%22!%20")}, + { nxt_string("decodeURI.name"), + nxt_string("decodeURI")}, + + { nxt_string("decodeURI.length"), + nxt_string("1")}, + { nxt_string("decodeURI()"), nxt_string("undefined")}, @@ -5671,6 +5689,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("decodeURI('%7e%7d%7c%7b%60%5f%5e%5d%5c%5b%40%3f%3e%3d%3c%3b%3a%2f%2e%2c%2b%2a%29%28%27%26%25%24%23%22%21%20')"), nxt_string("~}|{`_^]\\[%40%3f>%3d<%3b%3a%2f.%2c%2b*)('%26%%24%23\"! ")}, + { nxt_string("decodeURIComponent.name"), + nxt_string("decodeURIComponent")}, + + { nxt_string("decodeURIComponent.length"), + nxt_string("1")}, + { nxt_string("decodeURIComponent('%7e%7d%7c%7b%60%5f%5e%5d%5c%5b%40%3f%3e%3d%3c%3b%3a%2f%2e%2c%2b%2a%29%28%27%26%25%24%23%22%21%20')"), nxt_string("~}|{`_^]\\[@?>=<;:/.,+*)('&%$#\"! ")}, @@ -7700,6 +7724,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Array.prototype"), nxt_string("") }, + { nxt_string("Array.prototype.length"), + nxt_string("0") }, + { nxt_string("Array.constructor === Function"), nxt_string("true") }, @@ -8132,6 +8159,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Function.prototype"), nxt_string("[object Function]") }, + { nxt_string("Function.prototype.length"), + nxt_string("0") }, + { nxt_string("Function.constructor === Function"), nxt_string("true") }, @@ -8801,10 +8831,10 @@ static njs_unit_test_t njs_test[] = nxt_string("a,b") }, { nxt_string("Object.getOwnPropertyNames(Object.defineProperty([], 'b', {}))"), - nxt_string("length,b") }, + nxt_string("b,length") }, { nxt_string("Object.getOwnPropertyNames(Object.defineProperty(new String(), 'b', {}))"), - nxt_string("length,b") }, + nxt_string("b,length") }, { nxt_string("Object.getOwnPropertyNames([1,2,3])"), nxt_string("0,1,2,length") }, @@ -10483,6 +10513,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("isNaN"), nxt_string("[object Function]") }, + { nxt_string("isNaN.name"), + nxt_string("isNaN") }, + + { nxt_string("isNaN.length"), + nxt_string("1") }, + { nxt_string("isNaN()"), nxt_string("true") }, @@ -10501,6 +10537,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("isFinite"), nxt_string("[object Function]") }, + { nxt_string("isFinite.name"), + nxt_string("isFinite") }, + + { nxt_string("isFinite.length"), + nxt_string("1") }, + { nxt_string("isFinite()"), nxt_string("false") }, @@ -10516,6 +10558,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("isFinite('abc')"), nxt_string("false") }, + { nxt_string("parseInt.name"), + nxt_string("parseInt") }, + + { nxt_string("parseInt.length"), + nxt_string("2") }, + { nxt_string("parseInt('12345abc')"), nxt_string("12345") }, @@ -10567,6 +10615,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("parseInt('0', 37)"), nxt_string("NaN") }, + { nxt_string("parseFloat.name"), + nxt_string("parseFloat") }, + + { nxt_string("parseFloat.length"), + nxt_string("1") }, + { nxt_string("parseFloat('12345abc')"), nxt_string("12345") },