[njs] Fixed objects instance properties.
Dmitry Volyntsev
xeioex at nginx.com
Fri Apr 12 15:36:12 UTC 2019
details: https://hg.nginx.org/njs/rev/1213e0a2b485
branches:
changeset: 885:1213e0a2b485
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Fri Apr 12 18:36:02 2019 +0300
description:
Fixed objects instance properties.
Some properties like 'length' of Array, String or Function
objects should be instance properties not prototype properties.
diffstat:
njs/njs_array.c | 26 +++++++-
njs/njs_array.h | 1 +
njs/njs_builtin.c | 92 ++++++++++++++++--------------
njs/njs_extern.c | 2 +-
njs/njs_function.c | 58 +++++++++++++++++--
njs/njs_function.h | 4 +-
njs/njs_number.c | 88 ++++++++++++++++++++++++++--
njs/njs_object.c | 40 +++++--------
njs/njs_string.c | 141 +++++++++++++++++++++++++++++++++++++++++-----
njs/njs_string.h | 1 +
njs/njs_vm.h | 9 ++-
njs/test/njs_unit_test.c | 60 +++++++++++++++++++-
12 files changed, 411 insertions(+), 111 deletions(-)
diffs (truncated from 1033 to 1000 lines):
diff -r ff7760036c67 -r 1213e0a2b485 njs/njs_array.c
--- a/njs/njs_array.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_array.c Fri Apr 12 18:36:02 2019 +0300
@@ -149,7 +149,7 @@ njs_array_alloc(njs_vm_t *vm, uint32_t l
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_const
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_arra
{
.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_proto
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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_array.h
--- a/njs/njs_array.h Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_array.h Fri Apr 12 18:36:02 2019 +0300
@@ -26,6 +26,7 @@ njs_ret_t njs_array_constructor(njs_vm_t
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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_builtin.c
--- a/njs/njs_builtin.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_builtin.c Fri Apr 12 18:36:02 2019 +0300
@@ -138,22 +138,6 @@ const njs_function_init_t njs_native_fu
};
-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_protot
};
+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_create(vm, &vm->shared->arguments_object_hash,
- njs_arguments_object_properties,
- nxt_nitems(njs_arguments_object_properties));
+ ret = njs_object_hash_init(vm, &shared->function_instance_hash,
+ &njs_function_instance_init);
if (nxt_slow_path(ret != NXT_OK)) {
return NXT_ERROR;
}
- object = vm->shared->objects;
+ 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 = 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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_extern.c
--- a/njs/njs_extern.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_extern.c Fri Apr 12 18:36:02 2019 +0300
@@ -109,7 +109,7 @@ njs_vm_external_add(njs_vm_t *vm, nxt_lv
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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_function.c
--- a/njs/njs_function.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_function.c Fri Apr 12 18:36:02 2019 +0300
@@ -42,7 +42,7 @@ njs_function_alloc(njs_vm_t *vm, njs_fun
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_v
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
}
-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
}
+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_co
* 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
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_pr
};
+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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_function.h
--- a/njs/njs_function.h Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_function.h Fri Apr 12 18:36:02 2019 +0300
@@ -153,8 +153,6 @@ njs_ret_t njs_function_arguments_object_
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_f
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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_number.c
--- a/njs/njs_number.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_number.c Fri Apr 12 18:36:02 2019 +0300
@@ -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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_object.c
--- a/njs/njs_object.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_object.c Fri Apr 12 18:36:02 2019 +0300
@@ -294,7 +294,7 @@ njs_property_query(njs_vm_t *vm, njs_pro
}
}
- 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, nj
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
}
}
- exotic_length = all;
-
break;
case NJS_STRING:
@@ -997,19 +992,14 @@ njs_object_enumerate(njs_vm_t *vm, const
} 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
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
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
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
}
}
- 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
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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_string.c
--- a/njs/njs_string.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_string.c Fri Apr 12 18:36:02 2019 +0300
@@ -555,6 +555,8 @@ njs_string_constructor(njs_vm_t *vm, njs
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_cons
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
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_prot
};
+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_
}
+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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_string.h
--- a/njs/njs_string.h Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_string.h Fri Apr 12 18:36:02 2019 +0300
@@ -177,6 +177,7 @@ njs_index_t njs_value_index(njs_vm_t *vm
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 -r ff7760036c67 -r 1213e0a2b485 njs/njs_vm.h
--- a/njs/njs_vm.h Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/njs_vm.h Fri Apr 12 18:36:02 2019 +0300
@@ -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 -r ff7760036c67 -r 1213e0a2b485 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu Apr 11 21:24:16 2019 +0300
+++ b/njs/test/njs_unit_test.c Fri Apr 12 18:36:02 2019 +0300
@@ -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") },
More information about the nginx-devel
mailing list