]> git.kaiwu.me - njs.git/commitdiff
Handling the NJS_NATIVE_GETTER properties in a single place.
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 13 Mar 2018 15:55:24 +0000 (18:55 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Tue, 13 Mar 2018 15:55:24 +0000 (18:55 +0300)
njs/njs_array.c
njs/njs_error.c
njs/njs_function.c
njs/njs_function.h
njs/njs_object.c
njs/njs_object.h
njs/njs_regexp.c
njs/njs_string.c
njs/njs_vm.c
njs/njs_vm.h
njs/test/njs_unit_test.c

index 8ba6897da671f66d552dbdb7c1059c701cd721ee..a1f81131ccbd1547959bc252f3970b3beaf711bf 100644 (file)
@@ -381,9 +381,10 @@ const njs_object_init_t  njs_array_constructor_init = {
 
 
 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);
 
index 6d1e285f84ba02ac2ed4108c57e4bb72e75e1c1b..32a94a5c0599337dedaa7290118eba05e6e6e303 100644 (file)
@@ -533,7 +533,8 @@ njs_memory_error_constructor(njs_vm_t *vm, njs_value_t *args,
 
 
 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_t *vm, njs_value_t *value)
         proto = (njs_value_t *) &njs_value_void;
     }
 
-    vm->retval = *proto;
+    *retval = *proto;
 
     return NXT_OK;
 }
index 6e8cce113904385e07e3c0be0a4da40e45e6c253..52486e8b6ec2de5ee03d22e1850d7d71464883c1 100644 (file)
@@ -411,14 +411,15 @@ njs_function_call(njs_vm_t *vm, njs_index_t retval, size_t advance)
  */
 
 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;
     }
 
index 6bcba89b5897578f2af79acdbda58322310e9366..13619289cf7b91110472be9ffd32405b9df1ff2e 100644 (file)
@@ -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,
index 57b63d3504fcbe5135d79019b074d6d12a975c53..7f51f4fb93443cd127747f5b2ec7d95c89537130 100644 (file)
@@ -745,7 +745,7 @@ njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     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, njs_value_t *args, nxt_uint_t nargs,
  */
 
 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_t *vm, njs_value_t *value)
         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_t *vm, njs_value_t *value)
  */
 
 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, njs_value_t *value)
         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_constructor_init = {
 
 
 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 *vm, njs_value_t *value)
  */
 
 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;
     }
 
index 14a57d502aa05abbe24e715410b155e0cbd1ab74..a0094a5b499decf84856d37d8ec4b02b28066bb0 100644 (file)
@@ -51,11 +51,14 @@ njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_value_t *args,
     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,
index bf8a6e5ee22081084b9678b738b1334886a57a0c..e28ac3cb036559d23d2756e4e04c6937b514ca2b 100644 (file)
@@ -474,7 +474,8 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern)
 
 
 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 *vm, njs_value_t *value)
     (void) njs_string_prop(&string, &regexp->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, njs_value_t *value)
 
 
 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_t *vm, njs_value_t *value)
 
 
 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 *vm, njs_value_t *value)
 
 
 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, njs_value_t *value)
     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);
 }
 
 
index 544a3548e6d4bba509873075091263a16ce4b11f..cafde07b3c992c7563d3838e1b71d3b14ee72094 100644 (file)
@@ -434,7 +434,8 @@ 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_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, njs_value_t *value)
         length = (length == 0) ? size : length;
     }
 
-    njs_value_number_set(&vm->retval, length);
+    njs_value_number_set(retval, length);
 
     njs_release(vm, value);
 
index 2c742bfd64f0d87e86a674d5c5585908ab5f2c1c..f8e39719e9c373a4034fd9f1b06632baa9024db1 100644 (file)
 
 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, njs_value_t *object,
             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, njs_property_query_t *pq,
 
             if (prop->type != NJS_WHITEOUT) {
                 pq->shared = 0;
+
                 return ret;
             }
 
@@ -1183,13 +1179,31 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq,
 
         if (ret == NXT_OK) {
             pq->shared = 1;
+            prop = pq->lhq.value;
 
-            if (pq->query == NJS_PROPERTY_QUERY_IN) {
+            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_value_t *object,
     retval = &njs_value_false;
 
     if (njs_is_object(object)) {
+        pq.query = NJS_PROPERTY_QUERY_GET;
 
-        lhq.key_hash = NJS_PROTOTYPE_HASH;
-        lhq.key = nxt_string_value("prototype");
+        ret = njs_property_query(vm, &pq, constructor, &prototype_string);
 
-        prop = njs_object_property(vm, constructor->data.u.object, &lhq);
-
-        if (prop != NULL) {
+        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;
index b87a9021f2d8ad0447045ff752f250051d866114..871aeaf551c3bf063a2d83083b4693182a885c11 100644 (file)
@@ -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);
 
index 1fd0f9e14bcf09fedb7cfa4a382090e7c0966939..69de8e3426e1b1380d59d29eb729b1e762768f87 100644 (file)
@@ -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") },