details: http://hg.nginx.org/njs/rev/9dcf4f92e32a branches: changeset: 455:9dcf4f92e32a user: Dmitry Volyntsev <xei...@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") }, _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel