]> git.kaiwu.me - njs.git/commitdiff
Fixed Object.values() and Object.entries() with external objects.
authorDmitry Volyntsev <xeioex@nginx.com>
Sat, 7 Jan 2023 00:50:46 +0000 (16:50 -0800)
committerDmitry Volyntsev <xeioex@nginx.com>
Sat, 7 Jan 2023 00:50:46 +0000 (16:50 -0800)
This closes #606 issue on Github.

src/njs_value.c
src/test/njs_unit_test.c

index 91758085a4aaf8f6e2f40884aa64ffaf94fff0a6..ff885fe3a16972def3c327d090fb4d92dced952f 100644 (file)
@@ -231,25 +231,80 @@ njs_array_t *
 njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value,
     njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all)
 {
-    njs_int_t           ret;
-    njs_value_t         keys;
+    njs_int_t           ret, len;
+    njs_array_t         *values, *entry;
+    njs_value_t         keys, *k, *dst, *end;
     njs_object_value_t  obj_val;
     njs_exotic_slots_t  *slots;
 
     if (njs_is_object(value)) {
-        if (kind == NJS_ENUM_KEYS && (type & NJS_ENUM_STRING)) {
-            slots = njs_object_slots(value);
-            if (slots != NULL && slots->keys != NULL) {
-                ret = slots->keys(vm, value, &keys);
+        slots = njs_object_slots(value);
+        if (slots == NULL || slots->keys == NULL) {
+            return njs_object_own_enumerate(vm, njs_object(value), kind, type,
+                                            all);
+        }
+
+        ret = slots->keys(vm, value, &keys);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NULL;
+        }
+
+        switch (kind) {
+        case NJS_ENUM_KEYS:
+            return njs_array(&keys);
+
+        case NJS_ENUM_VALUES:
+            len = njs_array_len(&keys);
+            k = njs_array(&keys)->start;
+            end = k + len;
+
+            values = njs_array_alloc(vm, 1, len, 0);
+            if (njs_slow_path(values == NULL)) {
+                return NULL;
+            }
+
+            dst = values->start;
+
+            while (k < end) {
+                ret = njs_value_property(vm, value, k++, dst++);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    return NULL;
+                }
+            }
+
+            return values;
+
+        case NJS_ENUM_BOTH:
+        default:
+            len = njs_array_len(&keys);
+            k = njs_array(&keys)->start;
+            end = k + len;
+
+            values = njs_array_alloc(vm, 1, len, 0);
+            if (njs_slow_path(values == NULL)) {
+                return NULL;
+            }
+
+            dst = values->start;
+
+            while (k < end) {
+                entry = njs_array_alloc(vm, 1, 2, 0);
+                if (njs_slow_path(entry == NULL)) {
+                    return NULL;
+                }
+
+                ret = njs_value_property(vm, value, k, &entry->start[1]);
                 if (njs_slow_path(ret != NJS_OK)) {
                     return NULL;
                 }
 
-                return njs_array(&keys);
+                njs_value_assign(&entry->start[0], k++);
+
+                njs_set_array(dst++, entry);
             }
-        }
 
-        return njs_object_own_enumerate(vm, njs_object(value), kind, type, all);
+            return values;
+        }
     }
 
     if (value->type != NJS_STRING) {
index 0888d59130dcf4359fcd380f03d1f9539394b001..cf7a5404542d7d7449d256fefed2ee2230a666e7 100644 (file)
@@ -21712,6 +21712,15 @@ static njs_unit_test_t  njs_externals_test[] =
     { njs_str("njs.dump($r).startsWith('External')"),
       njs_str("true") },
 
+    { njs_str("Object.keys($r.header)"),
+      njs_str("01,02,03") },
+
+    { njs_str("Object.values($r.header)"),
+      njs_str("01|АБВ,02|АБВ,03|АБВ") },
+
+    { njs_str("njs.dump(Object.entries($r.header))"),
+      njs_str("[['01','01|АБВ'],['02','02|АБВ'],['03','03|АБВ']]") },
+
     { njs_str("njs.dump($r.header)"),
       njs_str("Header {01:'01|АБВ',02:'02|АБВ',03:'03|АБВ'}") },