[njs] Fixed Object.defineProperty() for shared descriptors.

Dmitry Volyntsev xeioex at nginx.com
Tue Jun 4 16:49:05 UTC 2019


details:   https://hg.nginx.org/njs/rev/8b27db801cd3
branches:  
changeset: 1000:8b27db801cd3
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Jun 04 19:38:50 2019 +0300
description:
Fixed Object.defineProperty() for shared descriptors.

This closes #172 issue on Github.

diffstat:

 njs/njs_object.c         |  33 ++++++++++++++++++++++++++-------
 njs/njs_object.h         |   2 +-
 njs/njs_vm.c             |   2 +-
 njs/test/njs_unit_test.c |  12 ++++++++++++
 4 files changed, 40 insertions(+), 9 deletions(-)

diffs (121 lines):

diff -r deef19f6498a -r 8b27db801cd3 njs/njs_object.c
--- a/njs/njs_object.c	Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/njs_object.c	Tue Jun 04 19:38:50 2019 +0300
@@ -708,7 +708,7 @@ njs_external_property_delete(njs_vm_t *v
 
 
 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, nj
     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, nj
         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_va
 
     /* 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 
 
     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;
diff -r deef19f6498a -r 8b27db801cd3 njs/njs_object.h
--- a/njs/njs_object.h	Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/njs_object.h	Tue Jun 04 19:38:50 2019 +0300
@@ -115,7 +115,7 @@ njs_value_t *njs_property_constructor_cr
 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;
diff -r deef19f6498a -r 8b27db801cd3 njs/njs_vm.c
--- a/njs/njs_vm.c	Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/njs_vm.c	Tue Jun 04 19:38:50 2019 +0300
@@ -3069,7 +3069,7 @@ njs_value_property(njs_vm_t *vm, const n
 
         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;
diff -r deef19f6498a -r 8b27db801cd3 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Tue Jun 04 16:07:14 2019 +0300
+++ b/njs/test/njs_unit_test.c	Tue Jun 04 19:38:50 2019 +0300
@@ -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") },
 


More information about the nginx-devel mailing list