]> git.kaiwu.me - njs.git/commitdiff
Fixed Object.defineProperty() for shared descriptors.
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 4 Jun 2019 16:38:50 +0000 (19:38 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Tue, 4 Jun 2019 16:38:50 +0000 (19:38 +0300)
This closes #172 issue on Github.

njs/njs_object.c
njs/njs_object.h
njs/njs_vm.c
njs/test/njs_unit_test.c

index cb3d1d4a8a97443e3300e1c6ff4380efdcc28dc0..fad293325053ebd235886321fb2b4016f6283b89 100644 (file)
@@ -708,7 +708,7 @@ njs_external_property_delete(njs_vm_t *vm, njs_value_t *value,
 
 
 njs_ret_t
-njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
+njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
 {
     nxt_int_t           ret;
     njs_function_t      *function;
@@ -727,6 +727,20 @@ njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
     shared = pq->lhq.value;
     *prop = *shared;
 
+    pq->lhq.replace = 0;
+    pq->lhq.value = prop;
+    pq->lhq.pool = vm->mem_pool;
+
+    ret = nxt_lvlhsh_insert(&pq->prototype->hash, &pq->lhq);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        njs_internal_error(vm, "lvlhsh insert failed");
+        return NXT_ERROR;
+    }
+
+    if (!njs_is_function(&prop->value)) {
+        return NXT_OK;
+    }
+
     function = njs_function_value_copy(vm, &prop->value);
     if (nxt_slow_path(function == NULL)) {
         return NXT_ERROR;
@@ -759,11 +773,7 @@ njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
         return NXT_ERROR;
     }
 
-    pq->lhq.replace = 0;
-    pq->lhq.value = prop;
-    pq->lhq.pool = vm->mem_pool;
-
-    return nxt_lvlhsh_insert(&pq->prototype->hash, &pq->lhq);
+    return NXT_OK;
 }
 
 
@@ -1900,10 +1910,19 @@ njs_define_property(njs_vm_t *vm, njs_value_t *object, const njs_value_t *name,
 
     /* Updating existing prop. */
 
+    if (nxt_slow_path(pq.shared)) {
+        ret = njs_prop_private_copy(vm, &pq);
+
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return ret;
+        }
+    }
+
     current = pq.lhq.value;
 
     switch (current->type) {
     case NJS_PROPERTY:
+    case NJS_METHOD:
         break;
 
     case NJS_PROPERTY_REF:
@@ -2043,7 +2062,7 @@ njs_object_property_descriptor(njs_vm_t *vm, njs_value_t *dest,
 
     case NJS_METHOD:
         if (pq.shared) {
-            ret = njs_method_private_copy(vm, &pq);
+            ret = njs_prop_private_copy(vm, &pq);
 
             if (nxt_slow_path(ret != NXT_OK)) {
                 return ret;
index ad7780fa12df8f962403056ff77f771f828fe77d..25e1d7374c6d61ed1db5b1ed0a59d84444796b79 100644 (file)
@@ -115,7 +115,7 @@ njs_value_t *njs_property_constructor_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
 njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
 
-njs_ret_t njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq);
+njs_ret_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq);
 const char * njs_prop_type_string(njs_object_property_type_t type);
 
 extern const njs_object_init_t  njs_object_constructor_init;
index f7ba55c98579afb8724e7daa0cfff501a8a40407..7488617867c4c8415387378ef21af027777650e8 100644 (file)
@@ -3069,7 +3069,7 @@ njs_value_property(njs_vm_t *vm, const njs_value_t *value,
 
         case NJS_METHOD:
             if (pq.shared) {
-                ret = njs_method_private_copy(vm, &pq);
+                ret = njs_prop_private_copy(vm, &pq);
 
                 if (nxt_slow_path(ret != NXT_OK)) {
                     return ret;
index e400ad52a0b62a618a556c428b1bdc181189549b..07c2ae7112643119c52738c9f981d188e53b2c58 100644 (file)
@@ -9320,6 +9320,18 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var o = {}; Object.defineProperty(o)"),
       nxt_string("TypeError: descriptor is not an object") },
 
+    { nxt_string("Object.defineProperty(Function.prototype, 'name', {value:'x'}).name"),
+      nxt_string("x") },
+
+    { nxt_string("Object.defineProperty(Function.prototype, 'xxx', {value:'x'}).xxx"),
+      nxt_string("x") },
+
+    { nxt_string("Object.defineProperty(Object, 'name', {value:'x'}).name"),
+      nxt_string("x") },
+
+    { nxt_string("Object.defineProperty(Object.prototype, 'toString', {value:1}).toString"),
+      nxt_string("1") },
+
     { nxt_string("var o = Object.defineProperties({}, {a:{value:1}}); o.a"),
       nxt_string("1") },