[njs] Fixed Object.values() and Object.entries() with shared properties.

noreply at nginx.com noreply at nginx.com
Tue Jul 2 02:32:02 UTC 2024


details:   https://github.com/nginx/njs/commit/69072164673d6dbe069ef05a4b38ef0a7a9d0908
branches:  master
commit:    69072164673d6dbe069ef05a4b38ef0a7a9d0908
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Wed, 26 Jun 2024 16:39:59 -0700
description:
Fixed Object.values() and Object.entries() with shared properties.

Previously, the functions directly copied a shared object from
a shared_hash. The copying is nessessary for lazy instantiation
of shared properties.

This fixes #743 issue on Github.

---
 src/njs_object.c         | 111 ++++++++++-------------------------------------
 src/test/njs_unit_test.c |   6 +++
 2 files changed, 30 insertions(+), 87 deletions(-)

diff --git a/src/njs_object.c b/src/njs_object.c
index 1b92437c..5a5970c9 100644
--- a/src/njs_object.c
+++ b/src/njs_object.c
@@ -1076,82 +1076,14 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object,
 }
 
 
-static njs_int_t
-njs_add_obj_prop_kind(njs_vm_t *vm, const njs_object_t *object,
-    const njs_lvlhsh_t *hash, njs_lvlhsh_query_t *lhq,
-    uint32_t flags, njs_array_t *items)
-{
-    njs_int_t          ret;
-    njs_value_t        value, *v, value1;
-    njs_array_t        *entry;
-    njs_object_prop_t  *prop;
-
-    ret = njs_lvlhsh_find(hash, lhq);
-    if (ret != NJS_OK) {
-        return NJS_DECLINED;
-    }
-
-    prop = (njs_object_prop_t *) (lhq->value);
-
-    if (prop->type != NJS_ACCESSOR) {
-        v = njs_prop_value(prop);
-
-    } else {
-        if (njs_is_data_descriptor(prop)) {
-            v = njs_prop_value(prop);
-            goto add;
-        }
-
-        if (njs_prop_getter(prop) == NULL) {
-            v =  njs_value_arg(&njs_value_undefined);
-            goto add;
-        }
-
-        v = &value1;
-
-        njs_set_object(&value, (njs_object_t *) object);
-        ret = njs_function_apply(vm, njs_prop_getter(prop), &value, 1, v);
-        if (ret != NJS_OK) {
-            return NJS_ERROR;
-        }
-    }
-
-add:
-    if (njs_object_enum_kind(flags) != NJS_ENUM_VALUES) {
-        entry = njs_array_alloc(vm, 0, 2, 0);
-        if (njs_slow_path(entry == NULL)) {
-            return NJS_ERROR;
-        }
-
-        njs_string_copy(&entry->start[0], &prop->name);
-        njs_value_assign(&entry->start[1], v);
-
-        njs_set_array(&value, entry);
-        v = &value;
-    }
-
-    ret = njs_array_add(vm, items, v);
-    if (njs_slow_path(ret != NJS_OK)) {
-        return NJS_ERROR;
-    }
-
-    return NJS_OK;
-}
-
-
 static njs_int_t
 njs_object_own_enumerate_object(njs_vm_t *vm, const njs_object_t *object,
     const njs_object_t *parent, njs_array_t *items, uint32_t flags)
 {
-    njs_int_t           ret;
-    uint32_t            i;
-    njs_array_t         *items_sorted;
-    njs_lvlhsh_each_t   lhe;
-    njs_lvlhsh_query_t  lhq;
-
-    lhq.proto = &njs_object_hash_proto;
-
-    njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
+    uint32_t     i;
+    njs_int_t    ret;
+    njs_array_t  *items_sorted, *entry;
+    njs_value_t  value, retval;
 
     switch (njs_object_enum_kind(flags)) {
     case NJS_ENUM_KEYS:
@@ -1174,26 +1106,31 @@ njs_object_own_enumerate_object(njs_vm_t *vm, const njs_object_t *object,
             return NJS_ERROR;
         }
 
-        for (i = 0; i< items_sorted->length; i++) {
+        njs_set_object(&value, (njs_object_t *) object);
 
-            lhe.key_hash = 0;
-            njs_object_property_key_set(&lhq, &items_sorted->start[i],
-                                        lhe.key_hash);
+        for (i = 0; i< items_sorted->length; i++) {
+            ret = njs_value_property(vm, &value, &items_sorted->start[i],
+                                     &retval);
+            if (njs_slow_path(ret != NJS_OK)) {
+                njs_array_destroy(vm, items_sorted);
+                return NJS_ERROR;
+            }
 
-            ret = njs_add_obj_prop_kind(vm, object, &object->hash, &lhq, flags,
-                                        items);
-            if (ret != NJS_DECLINED) {
-                if (ret != NJS_OK) {
+            if (njs_object_enum_kind(flags) != NJS_ENUM_VALUES) {
+                entry = njs_array_alloc(vm, 0, 2, 0);
+                if (njs_slow_path(entry == NULL)) {
                     return NJS_ERROR;
                 }
 
-            } else {
-                ret = njs_add_obj_prop_kind(vm, object, &object->shared_hash,
-                                            &lhq, flags, items);
-                njs_assert(ret != NJS_DECLINED);
-                if (ret != NJS_OK) {
-                    return NJS_ERROR;
-                }
+                njs_string_copy(&entry->start[0], &items_sorted->start[i]);
+                njs_value_assign(&entry->start[1], &retval);
+
+                njs_set_array(&retval, entry);
+            }
+
+            ret = njs_array_add(vm, items, &retval);
+            if (njs_slow_path(ret != NJS_OK)) {
+                return NJS_ERROR;
             }
         }
 
diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c
index d78c5b71..e63b0336 100644
--- a/src/test/njs_unit_test.c
+++ b/src/test/njs_unit_test.c
@@ -22693,6 +22693,12 @@ static njs_unit_test_t  njs_shared_test[] =
     { njs_str("var v = Math.round(Math.random() * 1000); ExternalNull.set(v);"
               "ExternalNull.get() == v"),
       njs_str("true") },
+
+#if (NJS_HAVE_OPENSSL)
+    { njs_str("var cr = Object.entries(global).filter((v) => v[0] == 'crypto')[0][1];"
+              "cr.abc = 1; cr.abc"),
+      njs_str("1") },
+#endif
 };
 
 


More information about the nginx-devel mailing list