[njs] Handling the NJS_NATIVE_GETTER properties in a single place.
Dmitry Volyntsev
xeioex at nginx.com
Tue Mar 13 15:57:37 UTC 2018
details: http://hg.nginx.org/njs/rev/9dcf4f92e32a
branches:
changeset: 455:9dcf4f92e32a
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue Mar 13 18:55:24 2018 +0300
description:
Handling the NJS_NATIVE_GETTER properties in a single place.
diffstat:
njs/njs_array.c | 5 +-
njs/njs_error.c | 5 +-
njs/njs_function.c | 5 +-
njs/njs_function.h | 3 +-
njs/njs_object.c | 32 +++++++++++--------
njs/njs_object.h | 9 +++-
njs/njs_regexp.c | 25 +++++++++------
njs/njs_string.c | 5 +-
njs/njs_vm.c | 76 ++++++++++++++++++++++++-----------------------
njs/njs_vm.h | 3 +-
njs/test/njs_unit_test.c | 9 +++++
11 files changed, 103 insertions(+), 74 deletions(-)
diffs (472 lines):
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_array.c
--- a/njs/njs_array.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_array.c Tue Mar 13 18:55:24 2018 +0300
@@ -381,9 +381,10 @@ const njs_object_init_t njs_array_const
static njs_ret_t
-njs_array_prototype_length(njs_vm_t *vm, njs_value_t *array)
+njs_array_prototype_length(njs_vm_t *vm, njs_value_t *array,
+ njs_value_t *retval)
{
- njs_value_number_set(&vm->retval, array->data.u.array->length);
+ njs_value_number_set(retval, array->data.u.array->length);
njs_release(vm, array);
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_error.c
--- a/njs/njs_error.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_error.c Tue Mar 13 18:55:24 2018 +0300
@@ -533,7 +533,8 @@ njs_memory_error_constructor(njs_vm_t *v
static njs_ret_t
-njs_memory_error_prototype_create(njs_vm_t *vm, njs_value_t *value)
+njs_memory_error_prototype_create(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
int32_t index;
njs_value_t *proto;
@@ -550,7 +551,7 @@ njs_memory_error_prototype_create(njs_vm
proto = (njs_value_t *) &njs_value_void;
}
- vm->retval = *proto;
+ *retval = *proto;
return NXT_OK;
}
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_function.c
--- a/njs/njs_function.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_function.c Tue Mar 13 18:55:24 2018 +0300
@@ -411,14 +411,15 @@ njs_function_call(njs_vm_t *vm, njs_inde
*/
njs_ret_t
-njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value)
+njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
njs_value_t *proto;
proto = njs_function_property_prototype_create(vm, value);
if (nxt_fast_path(proto != NULL)) {
- vm->retval = *proto;
+ *retval = *proto;
return NXT_OK;
}
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_function.h
--- a/njs/njs_function.h Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_function.h Tue Mar 13 18:55:24 2018 +0300
@@ -146,7 +146,8 @@ struct njs_frame_s {
njs_function_t *njs_function_alloc(njs_vm_t *vm);
njs_function_t *njs_function_value_copy(njs_vm_t *vm, njs_value_t *value);
njs_native_frame_t *njs_function_frame_alloc(njs_vm_t *vm, size_t size);
-njs_ret_t njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value);
+njs_ret_t njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval);
njs_value_t *njs_function_property_prototype_create(njs_vm_t *vm,
njs_value_t *value);
njs_ret_t njs_function_constructor(njs_vm_t *vm, njs_value_t *args,
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_object.c
--- a/njs/njs_object.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_object.c Tue Mar 13 18:55:24 2018 +0300
@@ -745,7 +745,7 @@ njs_object_get_prototype_of(njs_vm_t *vm
njs_index_t unused)
{
if (nargs > 1 && njs_is_object(&args[1])) {
- njs_object_prototype_get_proto(vm, &args[1]);
+ njs_object_prototype_get_proto(vm, &args[1], &vm->retval);
return NXT_OK;
}
@@ -976,7 +976,8 @@ njs_object_is_extensible(njs_vm_t *vm, n
*/
njs_ret_t
-njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
+njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
nxt_uint_t index;
njs_object_t *proto;
@@ -993,9 +994,9 @@ njs_primitive_prototype_get_proto(njs_vm
proto = &vm->prototypes[index].object;
}
- vm->retval.data.u.object = proto;
- vm->retval.type = proto->type;
- vm->retval.data.truth = 1;
+ retval->data.u.object = proto;
+ retval->type = proto->type;
+ retval->data.truth = 1;
return NXT_OK;
}
@@ -1008,7 +1009,8 @@ njs_primitive_prototype_get_proto(njs_vm
*/
njs_ret_t
-njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value)
+njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
int32_t index;
njs_value_t *proto;
@@ -1027,7 +1029,7 @@ njs_object_prototype_create(njs_vm_t *vm
proto = (njs_value_t *) &njs_value_void;
}
- vm->retval = *proto;
+ *retval = *proto;
return NXT_OK;
}
@@ -1205,19 +1207,20 @@ const njs_object_init_t njs_object_cons
njs_ret_t
-njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
+njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
njs_object_t *proto;
proto = value->data.u.object->__proto__;
if (nxt_fast_path(proto != NULL)) {
- vm->retval.data.u.object = proto;
- vm->retval.type = proto->type;
- vm->retval.data.truth = 1;
+ retval->data.u.object = proto;
+ retval->type = proto->type;
+ retval->data.truth = 1;
} else {
- vm->retval = njs_value_null;
+ *retval = njs_value_null;
}
return NXT_OK;
@@ -1231,7 +1234,8 @@ njs_object_prototype_get_proto(njs_vm_t
*/
static njs_ret_t
-njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value)
+njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
int32_t index;
njs_value_t *cons;
@@ -1267,7 +1271,7 @@ found:
cons = njs_property_constructor_create(vm, &prototype->object.hash,
&vm->scopes[NJS_SCOPE_GLOBAL][index]);
if (nxt_fast_path(cons != NULL)) {
- vm->retval = *cons;
+ *retval = *cons;
return NXT_OK;
}
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_object.h
--- a/njs/njs_object.h Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_object.h Tue Mar 13 18:55:24 2018 +0300
@@ -51,11 +51,14 @@ njs_ret_t njs_object_constructor(njs_vm_
nxt_uint_t nargs, njs_index_t unused);
njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name,
const njs_value_t *value, uint8_t attributes);
-njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
-njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value);
+njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval);
+njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval);
njs_value_t *njs_property_prototype_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
njs_object_t *prototype);
-njs_ret_t njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
+njs_ret_t njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval);
njs_value_t *njs_property_constructor_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
njs_value_t *constructor);
njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_regexp.c
--- a/njs/njs_regexp.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_regexp.c Tue Mar 13 18:55:24 2018 +0300
@@ -474,7 +474,8 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regex
static njs_ret_t
-njs_regexp_prototype_last_index(njs_vm_t *vm, njs_value_t *value)
+njs_regexp_prototype_last_index(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
uint32_t index;
njs_regexp_t *regexp;
@@ -487,19 +488,20 @@ njs_regexp_prototype_last_index(njs_vm_t
(void) njs_string_prop(&string, ®exp->string);
index = njs_string_index(&string, regexp->last_index);
- njs_value_number_set(&vm->retval, index);
+ njs_value_number_set(retval, index);
return NXT_OK;
}
static njs_ret_t
-njs_regexp_prototype_global(njs_vm_t *vm, njs_value_t *value)
+njs_regexp_prototype_global(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
njs_regexp_pattern_t *pattern;
pattern = value->data.u.regexp->pattern;
- vm->retval = pattern->global ? njs_value_true : njs_value_false;
+ *retval = pattern->global ? njs_value_true : njs_value_false;
njs_release(vm, value);
return NXT_OK;
@@ -507,12 +509,13 @@ njs_regexp_prototype_global(njs_vm_t *vm
static njs_ret_t
-njs_regexp_prototype_ignore_case(njs_vm_t *vm, njs_value_t *value)
+njs_regexp_prototype_ignore_case(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
njs_regexp_pattern_t *pattern;
pattern = value->data.u.regexp->pattern;
- vm->retval = pattern->ignore_case ? njs_value_true : njs_value_false;
+ *retval = pattern->ignore_case ? njs_value_true : njs_value_false;
njs_release(vm, value);
return NXT_OK;
@@ -520,12 +523,13 @@ njs_regexp_prototype_ignore_case(njs_vm_
static njs_ret_t
-njs_regexp_prototype_multiline(njs_vm_t *vm, njs_value_t *value)
+njs_regexp_prototype_multiline(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
njs_regexp_pattern_t *pattern;
pattern = value->data.u.regexp->pattern;
- vm->retval = pattern->multiline ? njs_value_true : njs_value_false;
+ *retval = pattern->multiline ? njs_value_true : njs_value_false;
njs_release(vm, value);
return NXT_OK;
@@ -533,7 +537,8 @@ njs_regexp_prototype_multiline(njs_vm_t
static njs_ret_t
-njs_regexp_prototype_source(njs_vm_t *vm, njs_value_t *value)
+njs_regexp_prototype_source(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
u_char *source;
int32_t length;
@@ -547,7 +552,7 @@ njs_regexp_prototype_source(njs_vm_t *vm
size = strlen((char *) source) - pattern->flags;
length = nxt_utf8_length(source, size);
- return njs_regexp_string_create(vm, &vm->retval, source, size, length);
+ return njs_regexp_string_create(vm, retval, source, size, length);
}
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_string.c
--- a/njs/njs_string.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_string.c Tue Mar 13 18:55:24 2018 +0300
@@ -434,7 +434,8 @@ 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_prototype_length(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *retval)
{
size_t size;
uintptr_t length;
@@ -461,7 +462,7 @@ njs_string_prototype_length(njs_vm_t *vm
length = (length == 0) ? size : length;
}
- njs_value_number_set(&vm->retval, length);
+ njs_value_number_set(retval, length);
njs_release(vm, value);
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_vm.c
--- a/njs/njs_vm.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_vm.c Tue Mar 13 18:55:24 2018 +0300
@@ -53,6 +53,10 @@
typedef struct {
nxt_lvlhsh_query_t lhq;
+
+ /* scratch is used to get the value of an NJS_NATIVE_GETTER property. */
+ njs_object_prop_t scratch;
+
njs_value_t value;
njs_object_t *prototype;
uint8_t query;
@@ -561,15 +565,6 @@ njs_vmcode_property_get(njs_vm_t *vm, nj
retval = &prop->value;
break;
- case NJS_NATIVE_GETTER:
- ret = prop->value.data.u.getter(vm, object);
-
- if (nxt_fast_path(ret == NXT_OK)) {
- return sizeof(njs_vmcode_prop_get_t);
- }
-
- return ret;
-
default:
nxt_thread_log_alert("invalid property get type:%d", prop->type);
@@ -1168,6 +1163,7 @@ njs_object_property_query(njs_vm_t *vm,
if (prop->type != NJS_WHITEOUT) {
pq->shared = 0;
+
return ret;
}
@@ -1183,13 +1179,31 @@ njs_object_property_query(njs_vm_t *vm,
if (ret == NXT_OK) {
pq->shared = 1;
-
- if (pq->query == NJS_PROPERTY_QUERY_IN) {
+ prop = pq->lhq.value;
+
+ switch (pq->query) {
+ case NJS_PROPERTY_QUERY_GET:
+ if (prop->type == NJS_NATIVE_GETTER) {
+ pq->scratch = *prop;
+ prop = &pq->scratch;
+ ret = prop->value.data.u.getter(vm, value, &prop->value);
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+ prop->type = NJS_PROPERTY;
+ pq->lhq.value = prop;
+ }
+ }
+
+ break;
+
+ case NJS_PROPERTY_QUERY_IN:
prop = pq->lhq.value;
if (prop->type == NJS_WHITEOUT) {
return NXT_DECLINED;
}
+
+ break;
}
return ret;
@@ -1361,12 +1375,14 @@ njs_ret_t
njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
njs_value_t *constructor)
{
- nxt_int_t ret;
- njs_value_t *value;
- njs_object_t *prototype, *proto;
- njs_object_prop_t *prop;
- const njs_value_t *retval;
- nxt_lvlhsh_query_t lhq;
+ nxt_int_t ret;
+ njs_value_t *value;
+ njs_object_t *prototype, *proto;
+ njs_object_prop_t *prop;
+ const njs_value_t *retval;
+ njs_property_query_t pq;
+
+ static njs_value_t prototype_string = njs_string("prototype");
if (!njs_is_function(constructor)) {
njs_exception_type_error(vm, "right argument is not a function", NULL);
@@ -1376,28 +1392,14 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs
retval = &njs_value_false;
if (njs_is_object(object)) {
-
- lhq.key_hash = NJS_PROTOTYPE_HASH;
- lhq.key = nxt_string_value("prototype");
-
- prop = njs_object_property(vm, constructor->data.u.object, &lhq);
-
- if (prop != NULL) {
+ pq.query = NJS_PROPERTY_QUERY_GET;
+
+ ret = njs_property_query(vm, &pq, constructor, &prototype_string);
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+ prop = pq.lhq.value;
value = &prop->value;
- if (prop->type == NJS_NATIVE_GETTER) {
- /*
- * STUB: getter should be called by some njs_object_property()
- */
- ret = prop->value.data.u.getter(vm, constructor);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- return ret;
- }
-
- value = &vm->retval;
- }
-
/* TODO: test prop->value is object. */
prototype = value->data.u.object;
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/njs_vm.h
--- a/njs/njs_vm.h Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/njs_vm.h Tue Mar 13 18:55:24 2018 +0300
@@ -117,7 +117,8 @@ typedef enum {
typedef struct njs_parser_s njs_parser_t;
-typedef njs_ret_t (*njs_getter_t) (njs_vm_t *vm, njs_value_t *obj);
+typedef njs_ret_t (*njs_getter_t) (njs_vm_t *vm, njs_value_t *obj,
+ njs_value_t *retval);
typedef njs_ret_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t retval);
diff -r c86a0cc40ce5 -r 9dcf4f92e32a njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Wed Feb 28 19:16:25 2018 +0300
+++ b/njs/test/njs_unit_test.c Tue Mar 13 18:55:24 2018 +0300
@@ -5724,9 +5724,15 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("({}).constructor === Object"),
nxt_string("true") },
+ { nxt_string("({}).constructor()"),
+ nxt_string("[object Object]") },
+
{ nxt_string("var a = Object.__proto__; a()"),
nxt_string("undefined") },
+ { nxt_string("Object.__proto__()"),
+ nxt_string("undefined") },
+
{ nxt_string("var a = Array(3); a"),
nxt_string(",,") },
@@ -5793,6 +5799,9 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("[].constructor === Array"),
nxt_string("true") },
+ { nxt_string("([]).constructor()"),
+ nxt_string("") },
+
{ nxt_string("Boolean()"),
nxt_string("false") },
More information about the nginx-devel
mailing list