[njs] Improved object property attributes.

Dmitry Volyntsev xeioex at nginx.com
Wed Jun 5 15:44:41 UTC 2019


details:   https://hg.nginx.org/njs/rev/6d5c457a298d
branches:  
changeset: 1001:6d5c457a298d
user:      hongzhidao <hongzhidao at gmail.com>
date:      Wed Jun 05 22:13:47 2019 +0800
description:
Improved object property attributes.

diffstat:

 njs/njs_object.c         |  166 +++++++++++++++++++++++++---------------------
 njs/njs_object.h         |    8 +-
 njs/test/njs_unit_test.c |    6 +-
 3 files changed, 97 insertions(+), 83 deletions(-)

diffs (366 lines):

diff -r 8b27db801cd3 -r 6d5c457a298d njs/njs_object.c
--- a/njs/njs_object.c	Tue Jun 04 19:38:50 2019 +0300
+++ b/njs/njs_object.c	Wed Jun 05 22:13:47 2019 +0800
@@ -223,9 +223,10 @@ njs_object_prop_alloc(njs_vm_t *vm, cons
         prop->name = *name;
 
         prop->type = NJS_PROPERTY;
+        prop->writable = attributes;
         prop->enumerable = attributes;
-        prop->writable = attributes;
         prop->configurable = attributes;
+
         return prop;
     }
 
@@ -520,9 +521,9 @@ njs_array_property_query(njs_vm_t *vm, n
         prop->type = NJS_PROPERTY_REF;
     }
 
-    prop->configurable = 1;
+    prop->writable = 1;
     prop->enumerable = 1;
-    prop->writable = 1;
+    prop->configurable = 1;
 
     pq->lhq.value = prop;
 
@@ -550,10 +551,11 @@ njs_string_property_query(njs_vm_t *vm, 
          * so the function cannot fail.
          */
         (void) njs_string_slice(vm, &prop->value, &string, &slice);
+
         prop->type = NJS_PROPERTY;
+        prop->writable = 0;
+        prop->enumerable = 1;
         prop->configurable = 0;
-        prop->enumerable = 1;
-        prop->writable = 0;
 
         pq->lhq.value = prop;
 
@@ -583,9 +585,9 @@ njs_external_property_query(njs_vm_t *vm
     prop = &pq->scratch;
 
     prop->type = NJS_PROPERTY;
-    prop->configurable = 0;
+    prop->writable = 0;
     prop->enumerable = 1;
-    prop->writable = 0;
+    prop->configurable = 0;
 
     ext_proto = object->external.proto;
 
@@ -1798,54 +1800,49 @@ njs_object_define_properties(njs_vm_t *v
 }
 
 
-static uint8_t
-njs_descriptor_attribute(njs_vm_t *vm, const njs_object_t *descriptor,
-    nxt_lvlhsh_query_t *pq, nxt_bool_t unset)
-{
-    njs_object_prop_t  *prop;
-
-    prop = njs_object_property(vm, descriptor, pq);
-    if (prop != NULL) {
-        return prop->value.data.truth;
-    }
-
-    return unset ? NJS_ATTRIBUTE_UNSET : 0;
-}
-
-
 static njs_object_prop_t *
 njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name,
-    const njs_object_t *descriptor, nxt_bool_t unset)
+    const njs_object_t *descriptor)
 {
-    const njs_value_t   *value;
     njs_object_prop_t   *prop, *pr;
     nxt_lvlhsh_query_t  pq;
 
-    value = unset ? &njs_value_invalid : &njs_value_undefined;
-    prop = njs_object_prop_alloc(vm, name, value, 0);
+    prop = njs_object_prop_alloc(vm, name, &njs_value_invalid,
+                                 NJS_ATTRIBUTE_UNSET);
     if (nxt_slow_path(prop == NULL)) {
         return NULL;
     }
 
+    pq.key = nxt_string_value("value");
+    pq.key_hash = NJS_VALUE_HASH;
+
+    pr = njs_object_property(vm, descriptor, &pq);
+    if (pr != NULL) {
+        prop->value = pr->value;
+    }
+
+    pq.key = nxt_string_value("writable");
+    pq.key_hash = NJS_WRITABABLE_HASH;
+
+    pr = njs_object_property(vm, descriptor, &pq);
+    if (pr != NULL) {
+        prop->writable = pr->value.data.truth;
+    }
+
+    pq.key = nxt_string_value("enumerable");
+    pq.key_hash = NJS_ENUMERABLE_HASH;
+
+    pr = njs_object_property(vm, descriptor, &pq);
+    if (pr != NULL) {
+        prop->enumerable = pr->value.data.truth;
+    }
+
     pq.key = nxt_string_value("configurable");
     pq.key_hash = NJS_CONFIGURABLE_HASH;
-    prop->configurable = njs_descriptor_attribute(vm, descriptor, &pq, unset);
-
-    pq.key = nxt_string_value("enumerable");
-    pq.key_hash = NJS_ENUMERABLE_HASH;
-    prop->enumerable = njs_descriptor_attribute(vm, descriptor, &pq, unset);
-
-    pq.key = nxt_string_value("writable");
-    pq.key_hash = NJS_WRITABABLE_HASH;
-    prop->writable = njs_descriptor_attribute(vm, descriptor, &pq, unset);
-
-    pq.key = nxt_string_value("value");
-    pq.key_hash = NJS_VALUE_HASH;
-    pq.proto = &njs_object_hash_proto;
 
     pr = njs_object_property(vm, descriptor, &pq);
     if (pr != NULL) {
-        prop->value = pr->value;
+        prop->configurable = pr->value.data.truth;
     }
 
     return prop;
@@ -1862,7 +1859,6 @@ njs_define_property(njs_vm_t *vm, njs_va
     const njs_object_t *descriptor)
 {
     nxt_int_t             ret;
-    nxt_bool_t            unset;
     njs_object_prop_t     *desc, *current;
     njs_property_query_t  pq;
 
@@ -1878,13 +1874,29 @@ njs_define_property(njs_vm_t *vm, njs_va
         return ret;
     }
 
-    unset = (ret == NXT_OK);
-    desc = njs_descriptor_prop(vm, name, descriptor, unset);
+    desc = njs_descriptor_prop(vm, name, descriptor);
     if (nxt_slow_path(desc == NULL)) {
         return NXT_ERROR;
     }
 
     if (nxt_fast_path(ret == NXT_DECLINED)) {
+
+        if (!njs_is_valid(&desc->value)) {
+            desc->value = njs_value_undefined;
+        }
+
+        if (desc->writable == NJS_ATTRIBUTE_UNSET) {
+            desc->writable = 0;
+        }
+
+        if (desc->enumerable == NJS_ATTRIBUTE_UNSET) {
+            desc->enumerable = 0;
+        }
+
+        if (desc->configurable == NJS_ATTRIBUTE_UNSET) {
+            desc->configurable = 0;
+        }
+
         if (nxt_slow_path(pq.lhq.value != NULL)) {
             current = pq.lhq.value;
 
@@ -1955,12 +1967,10 @@ njs_define_property(njs_vm_t *vm, njs_va
     }
 
     if (!current->configurable) {
-        if (desc->configurable == NJS_ATTRIBUTE_TRUE) {
-            goto exception;
-        }
-
-        if (desc->enumerable != NJS_ATTRIBUTE_UNSET
-            && current->enumerable != desc->enumerable)
+
+        if (njs_is_valid(&desc->value)
+            && current->writable == NJS_ATTRIBUTE_FALSE
+            && !njs_values_strict_equal(&desc->value, &current->value))
         {
             goto exception;
         }
@@ -1971,28 +1981,31 @@ njs_define_property(njs_vm_t *vm, njs_va
             goto exception;
         }
 
-        if (njs_is_valid(&desc->value)
-            && current->writable == NJS_ATTRIBUTE_FALSE
-            && !njs_values_strict_equal(&desc->value, &current->value))
+        if (desc->enumerable != NJS_ATTRIBUTE_UNSET
+            && current->enumerable != desc->enumerable)
         {
             goto exception;
         }
+
+        if (desc->configurable == NJS_ATTRIBUTE_TRUE) {
+            goto exception;
+        }
     }
 
-    if (desc->configurable != NJS_ATTRIBUTE_UNSET) {
-        current->configurable = desc->configurable;
+    if (njs_is_valid(&desc->value)) {
+        current->value = desc->value;
+    }
+
+    if (desc->writable != NJS_ATTRIBUTE_UNSET) {
+        current->writable = desc->writable;
     }
 
     if (desc->enumerable != NJS_ATTRIBUTE_UNSET) {
         current->enumerable = desc->enumerable;
     }
 
-    if (desc->writable != NJS_ATTRIBUTE_UNSET) {
-        current->writable = desc->writable;
-    }
-
-    if (njs_is_valid(&desc->value)) {
-        current->value = desc->value;
+    if (desc->configurable != NJS_ATTRIBUTE_UNSET) {
+        current->configurable = desc->configurable;
     }
 
     return NXT_OK;
@@ -2006,12 +2019,12 @@ exception:
 
 
 static const njs_value_t  njs_object_value_string = njs_string("value");
+static const njs_value_t  njs_object_writable_string =
+                                                    njs_string("writable");
+static const njs_value_t  njs_object_enumerable_string =
+                                                    njs_string("enumerable");
 static const njs_value_t  njs_object_configurable_string =
                                                     njs_string("configurable");
-static const njs_value_t  njs_object_enumerable_string =
-                                                    njs_string("enumerable");
-static const njs_value_t  njs_object_writable_string =
-                                                    njs_string("writable");
 
 
 static njs_ret_t
@@ -2087,7 +2100,6 @@ njs_object_property_descriptor(njs_vm_t 
     lhq.proto = &njs_object_hash_proto;
     lhq.replace = 0;
     lhq.pool = vm->mem_pool;
-    lhq.proto = &njs_object_hash_proto;
 
     lhq.key = nxt_string_value("value");
     lhq.key_hash = NJS_VALUE_HASH;
@@ -2105,12 +2117,12 @@ njs_object_property_descriptor(njs_vm_t 
         return NXT_ERROR;
     }
 
-    lhq.key = nxt_string_value("configurable");
-    lhq.key_hash = NJS_CONFIGURABLE_HASH;
-
-    setval = (prop->configurable == 1) ? &njs_value_true : &njs_value_false;
-
-    pr = njs_object_prop_alloc(vm, &njs_object_configurable_string, setval, 1);
+    lhq.key = nxt_string_value("writable");
+    lhq.key_hash = NJS_WRITABABLE_HASH;
+
+    setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false;
+
+    pr = njs_object_prop_alloc(vm, &njs_object_writable_string, setval, 1);
     if (nxt_slow_path(pr == NULL)) {
         return NXT_ERROR;
     }
@@ -2141,12 +2153,12 @@ njs_object_property_descriptor(njs_vm_t 
         return NXT_ERROR;
     }
 
-    lhq.key = nxt_string_value("writable");
-    lhq.key_hash = NJS_WRITABABLE_HASH;
-
-    setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false;
-
-    pr = njs_object_prop_alloc(vm, &njs_object_writable_string, setval, 1);
+    lhq.key = nxt_string_value("configurable");
+    lhq.key_hash = NJS_CONFIGURABLE_HASH;
+
+    setval = (prop->configurable == 1) ? &njs_value_true : &njs_value_false;
+
+    pr = njs_object_prop_alloc(vm, &njs_object_configurable_string, setval, 1);
     if (nxt_slow_path(pr == NULL)) {
         return NXT_ERROR;
     }
diff -r 8b27db801cd3 -r 6d5c457a298d njs/njs_object.h
--- a/njs/njs_object.h	Tue Jun 04 19:38:50 2019 +0300
+++ b/njs/njs_object.h	Wed Jun 05 22:13:47 2019 +0800
@@ -27,6 +27,7 @@ typedef enum {
     NJS_ATTRIBUTE_UNSET,
 } njs_object_attribute_t;
 
+
 typedef struct {
     /* Must be aligned to njs_value_t. */
     njs_value_t                 value;
@@ -34,8 +35,8 @@ typedef struct {
 
     njs_object_property_type_t  type:8;          /* 3 bits */
 
+    njs_object_attribute_t      writable:8;      /* 2 bits */
     njs_object_attribute_t      enumerable:8;    /* 2 bits */
-    njs_object_attribute_t      writable:8;      /* 2 bits */
     njs_object_attribute_t      configurable:8;  /* 2 bits */
 } njs_object_prop_t;
 
@@ -99,7 +100,7 @@ nxt_int_t njs_object_hash_create(njs_vm_
 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);
+    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_value_t *setval, njs_value_t *retval);
 njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value,
@@ -116,9 +117,10 @@ njs_ret_t njs_object_prototype_to_string
     nxt_uint_t nargs, njs_index_t unused);
 
 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);
+const char *njs_prop_type_string(njs_object_property_type_t type);
 
 extern const njs_object_init_t  njs_object_constructor_init;
 extern const njs_object_init_t  njs_object_prototype_init;
 
+
 #endif /* _NJS_OBJECT_H_INCLUDED_ */
diff -r 8b27db801cd3 -r 6d5c457a298d njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Tue Jun 04 19:38:50 2019 +0300
+++ b/njs/test/njs_unit_test.c	Wed Jun 05 22:13:47 2019 +0800
@@ -9598,7 +9598,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("undefined") },
 
     { nxt_string("JSON.stringify(Object.getOwnPropertyDescriptor([3,4], 'length'))"),
-      nxt_string("{\"value\":2,\"configurable\":false,\"enumerable\":false,\"writable\":true}") },
+      nxt_string("{\"value\":2,\"writable\":true,\"enumerable\":false,\"configurable\":false}") },
 
     { nxt_string("Object.getOwnPropertyDescriptor(Array.of, 'length').value"),
       nxt_string("0") },
@@ -9614,10 +9614,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("1") },
 
     { nxt_string("JSON.stringify(Object.getOwnPropertyDescriptor('αβγδ', '2'))"),
-      nxt_string("{\"value\":\"γ\",\"configurable\":false,\"enumerable\":true,\"writable\":false}") },
+      nxt_string("{\"value\":\"γ\",\"writable\":false,\"enumerable\":true,\"configurable\":false}") },
 
     { nxt_string("JSON.stringify(Object.getOwnPropertyDescriptor(new String('abc'), 'length'))"),
-      nxt_string("{\"value\":3,\"configurable\":false,\"enumerable\":false,\"writable\":false}") },
+      nxt_string("{\"value\":3,\"writable\":false,\"enumerable\":false,\"configurable\":false}") },
 
     { nxt_string("Object.getOwnPropertyDescriptor(1, '0')"),
       nxt_string("undefined") },


More information about the nginx-devel mailing list