]> git.kaiwu.me - njs.git/commitdiff
Introduced njs_vm_value_enumerate() and njs_vm_value_own_enumerate().
authorDmitry Volyntsev <xeioex@nginx.com>
Sat, 16 Mar 2024 06:14:39 +0000 (23:14 -0700)
committerDmitry Volyntsev <xeioex@nginx.com>
Sat, 16 Mar 2024 06:14:39 +0000 (23:14 -0700)
src/njs.h
src/njs_value.h
src/njs_vm.c

index 4dfa2da65814504fd64aedf55b8e0de2812e1233..6e1e1a2dabc7f486f45f484bbe4658c8c9ce2bf7 100644 (file)
--- a/src/njs.h
+++ b/src/njs.h
@@ -128,6 +128,18 @@ typedef enum {
 } njs_wellknown_symbol_t;
 
 
+typedef enum {
+#define njs_object_enum_kind(flags) (flags & 7)
+    NJS_ENUM_KEYS = 1,
+    NJS_ENUM_VALUES = 2,
+    NJS_ENUM_BOTH = 4,
+#define njs_object_enum(flags) (flags & (NJS_ENUM_STRING | NJS_ENUM_SYMBOL))
+    NJS_ENUM_STRING = 8,
+    NJS_ENUM_SYMBOL = 16,
+    NJS_ENUM_ENUMERABLE_ONLY = 32,
+} njs_object_enum_t;
+
+
 typedef enum {
     /*
      * Extern property type.
@@ -497,6 +509,10 @@ NJS_EXPORT njs_int_t njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval,
     ...);
 NJS_EXPORT njs_value_t *njs_vm_object_keys(njs_vm_t *vm, njs_value_t *value,
     njs_value_t *retval);
+NJS_EXPORT njs_value_t *njs_vm_value_enumerate(njs_vm_t *vm, njs_value_t *value,
+    uint32_t flags, njs_value_t *retval);
+NJS_EXPORT njs_value_t *njs_vm_value_own_enumerate(njs_vm_t *vm,
+    njs_value_t *value, uint32_t flags, njs_value_t *retval);
 NJS_EXPORT njs_value_t *njs_vm_object_prop(njs_vm_t *vm,
     njs_value_t *value, const njs_str_t *key, njs_opaque_value_t *retval);
 NJS_EXPORT njs_int_t njs_vm_object_prop_set(njs_vm_t *vm, njs_value_t *value,
index 57f9790e1ea2763984654d0e884d273dabf67552..3751db7194f7dd0031d949b164df6da126614a6d 100644 (file)
@@ -312,18 +312,6 @@ struct njs_object_type_init_s {
 };
 
 
-typedef enum {
-#define njs_object_enum_kind(flags) (flags & 7)
-    NJS_ENUM_KEYS = 1,
-    NJS_ENUM_VALUES = 2,
-    NJS_ENUM_BOTH = 4,
-#define njs_object_enum(flags) (flags & (NJS_ENUM_STRING | NJS_ENUM_SYMBOL))
-    NJS_ENUM_STRING = 8,
-    NJS_ENUM_SYMBOL = 16,
-    NJS_ENUM_ENUMERABLE_ONLY = 32,
-} njs_object_enum_t;
-
-
 typedef enum {
     NJS_PROPERTY = 0,
     NJS_ACCESSOR,
index 9c8be4371889dfc60e04fd4feba7dd72e06bd89b..0db83704c510ff29915d9fa14480e5a73f1f1ed1 100644 (file)
@@ -1114,6 +1114,94 @@ njs_vm_exception_string(njs_vm_t *vm, njs_str_t *dst)
 }
 
 
+njs_value_t *
+njs_vm_value_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags,
+    njs_value_t *retval)
+{
+    ssize_t                  length;
+    njs_int_t                ret;
+    njs_value_t              *val;
+    njs_array_t              *keys;
+    njs_rbtree_t             *variables;
+    njs_rbtree_node_t        *rb_node;
+    njs_variable_node_t      *node;
+    const njs_lexer_entry_t  *lex_entry;
+
+    static const njs_str_t  njs_this_str = njs_str("this");
+
+    keys = njs_value_enumerate(vm, value, flags);
+    if (njs_slow_path(keys == NULL)) {
+        return NULL;
+    }
+
+    if (!njs_values_same(value, &vm->global_value)
+        || vm->global_scope == NULL)
+    {
+        goto done;
+    }
+
+    /* TODO: workaround for values in global object. */
+
+    variables = &vm->global_scope->variables;
+    rb_node = njs_rbtree_min(variables);
+
+    while (njs_rbtree_is_there_successor(variables, rb_node)) {
+        node = (njs_variable_node_t *) rb_node;
+
+        lex_entry = njs_lexer_entry(node->variable->unique_id);
+        if (njs_slow_path(lex_entry == NULL)) {
+            return NULL;
+        }
+
+        if (njs_strstr_eq(&lex_entry->name, &njs_this_str)) {
+            rb_node = njs_rbtree_node_successor(variables, rb_node);
+            continue;
+        }
+
+        length = njs_utf8_length(lex_entry->name.start, lex_entry->name.length);
+        if (njs_slow_path(length < 0)) {
+            return NULL;
+        }
+
+        val = njs_array_push(vm, keys);
+        if (njs_slow_path(value == NULL)) {
+            return NULL;
+        }
+
+        ret = njs_string_new(vm, val, lex_entry->name.start,
+                             lex_entry->name.length, length);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NULL;
+        }
+
+        rb_node = njs_rbtree_node_successor(variables, rb_node);
+    }
+
+done:
+
+     njs_set_array(retval, keys);
+
+     return retval;
+}
+
+
+njs_value_t *
+njs_vm_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags,
+    njs_value_t *retval)
+{
+    njs_array_t  *keys;
+
+    keys = njs_value_own_enumerate(vm, value, flags);
+    if (njs_slow_path(keys == NULL)) {
+        return NULL;
+    }
+
+    njs_set_array(retval, keys);
+
+    return retval;
+}
+
+
 njs_int_t
 njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval, ...)
 {