Skip to content

Instantly share code, notes, and snippets.

@lexborisov
Created April 8, 2019 16:19
Show Gist options
  • Save lexborisov/52d270ffadcfbe4b9460031629a4ae2f to your computer and use it in GitHub Desktop.
Save lexborisov/52d270ffadcfbe4b9460031629a4ae2f to your computer and use it in GitHub Desktop.
# HG changeset patch
# User Alexander Borisov <alexander.borisov@nginx.com>
# Date 1554739316 -10800
# Mon Apr 08 19:01:56 2019 +0300
# Node ID 7e69673975b0aa7d3ea3555211f8ff85f626d044
# Parent 84cb61f23b7e3075dd21ff0ead228157bc0dd0e9
Saving hash key to result for each() function in level hash.
diff -r 84cb61f23b7e -r 7e69673975b0 nxt/nxt_lvlhsh.c
--- a/nxt/nxt_lvlhsh.c Sun Apr 07 00:09:09 2019 +0800
+++ b/nxt/nxt_lvlhsh.c Mon Apr 08 19:01:56 2019 +0300
@@ -842,6 +842,7 @@
} while (nxt_lvlhsh_free_entry(bucket));
value = nxt_lvlhsh_entry_value(bucket);
+ lhe->key_hash = nxt_lvlhsh_entry_key(bucket);
lhe->entries--;
diff -r 84cb61f23b7e -r 7e69673975b0 nxt/nxt_lvlhsh.h
--- a/nxt/nxt_lvlhsh.h Sun Apr 07 00:09:09 2019 +0800
+++ b/nxt/nxt_lvlhsh.h Mon Apr 08 19:01:56 2019 +0300
@@ -171,6 +171,7 @@
uint32_t current;
uint32_t entry;
uint32_t entries;
+ uint32_t key_hash;
} nxt_lvlhsh_each_t;
# HG changeset patch
# User Alexander Borisov <alexander.borisov@nginx.com>
# Date 1554738667 -10800
# Mon Apr 08 18:51:07 2019 +0300
# Node ID 86763acc76d76ec238605034aeb893a6f4e461d6
# Parent 7e69673975b0aa7d3ea3555211f8ff85f626d044
Added function njs_object_property_proto_range().
The function searches for a value in the object with a depth limit of
the prototype.
diff -r 7e69673975b0 -r 86763acc76d7 njs/njs_object.c
--- a/njs/njs_object.c Mon Apr 08 19:01:56 2019 +0300
+++ b/njs/njs_object.c Mon Apr 08 18:51:07 2019 +0300
@@ -240,6 +240,34 @@
}
+nxt_noinline njs_object_prop_t *
+njs_object_property_proto_range(njs_vm_t *vm, const njs_object_t *begin,
+ const njs_object_t *end, nxt_lvlhsh_query_t *lhq)
+{
+ nxt_int_t ret;
+
+ lhq->proto = &njs_object_hash_proto;
+
+ while (begin != end) {
+ ret = nxt_lvlhsh_find(&begin->hash, lhq);
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+ return lhq->value;
+ }
+
+ ret = nxt_lvlhsh_find(&begin->shared_hash, lhq);
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+ return lhq->value;
+ }
+
+ begin = begin->__proto__;
+ }
+
+ return NULL;
+}
+
+
/*
* ES5.1, 8.12.1: [[GetOwnProperty]], [[GetProperty]].
* The njs_property_query() returns values
diff -r 7e69673975b0 -r 86763acc76d7 njs/njs_object.h
--- a/njs/njs_object.h Mon Apr 08 19:01:56 2019 +0300
+++ b/njs/njs_object.h Mon Apr 08 18:51:07 2019 +0300
@@ -92,6 +92,9 @@
const njs_value_t *property, njs_value_t *retval);
njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj,
nxt_lvlhsh_query_t *lhq);
+njs_object_prop_t *njs_object_property_proto_range(njs_vm_t *vm,
+ const njs_object_t *begin, const njs_object_t *end,
+ nxt_lvlhsh_query_t *lhq);
njs_ret_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq,
njs_value_t *object, const njs_value_t *property);
nxt_int_t njs_object_hash_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
# HG changeset patch
# User Alexander Borisov <alexander.borisov@nginx.com>
# Date 1554724440 -10800
# Mon Apr 08 14:54:00 2019 +0300
# Node ID 5caac4f9e23a823c181b04c74c22221087d43eeb
# Parent 86763acc76d76ec238605034aeb893a6f4e461d6
Walking over prototypes chain during iteration over an object.
This closes #33 issue on Github.
diff -r 86763acc76d7 -r 5caac4f9e23a njs/njs_vm.c
--- a/njs/njs_vm.c Mon Apr 08 18:51:07 2019 +0300
+++ b/njs/njs_vm.c Mon Apr 08 14:54:00 2019 +0300
@@ -10,8 +10,9 @@
struct njs_property_next_s {
- int32_t index;
- nxt_lvlhsh_each_t lhe;
+ int32_t index;
+ nxt_lvlhsh_each_t lhe;
+ njs_object_t *object;
};
@@ -757,7 +758,9 @@
vm->retval.data.u.next = next;
nxt_lvlhsh_each_init(&next->lhe, &njs_object_hash_proto);
+
next->index = -1;
+ next->object = object->data.u.object;
if (njs_is_array(object) && object->data.u.array->length != 0) {
next->index = 0;
@@ -790,7 +793,8 @@
nxt_uint_t n;
njs_value_t *retval;
njs_array_t *array;
- njs_object_prop_t *prop;
+ njs_object_prop_t *prop, *f_prop;
+ nxt_lvlhsh_query_t query;
njs_property_next_t *next;
const njs_extern_t *ext_proto;
njs_vmcode_prop_next_t *code;
@@ -818,12 +822,20 @@
}
for ( ;; ) {
- prop = nxt_lvlhsh_each(&object->data.u.object->hash, &next->lhe);
-
+ prop = nxt_lvlhsh_each(&next->object->hash, &next->lhe);
if (prop == NULL) {
break;
}
+ njs_string_get(&prop->name, &query.key);
+ query.key_hash = next->lhe.key_hash;
+
+ f_prop = njs_object_property_proto_range(vm, object->data.u.object,
+ next->object, &query);
+ if (f_prop != NULL) {
+ return 0;
+ }
+
if (prop->type != NJS_WHITEOUT && prop->enumerable) {
*retval = prop->name;
@@ -831,6 +843,14 @@
}
}
+ if (next->object->__proto__ != NULL) {
+ next->object = next->object->__proto__;
+
+ nxt_lvlhsh_each_init(&next->lhe, &njs_object_hash_proto);
+
+ return 0;
+ }
+
nxt_mp_free(vm->mem_pool, next);
} else if (njs_is_external(object)) {
diff -r 86763acc76d7 -r 5caac4f9e23a njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Mon Apr 08 18:51:07 2019 +0300
+++ b/njs/test/njs_unit_test.c Mon Apr 08 14:54:00 2019 +0300
@@ -7577,6 +7577,35 @@
{ nxt_string("Object.prototype.__proto__.f()"),
nxt_string("TypeError: cannot get property \"f\" of undefined") },
+ { nxt_string("var o1 = Object.create(null); o1.one = 1;"
+ "var o2 = Object.create(o1); o2.two = 2;"
+ "var o3 = Object.create(o2); o3.three = 3;"
+ "var res = [];"
+ "for (var val in o3) res.push(val); res"),
+ nxt_string("three,two,one") },
+
+ { nxt_string("var o1 = Object.create(null); o1.one = 1;"
+ "var o2 = Object.create(o1);"
+ "var o3 = Object.create(o2); o3.three = 3;"
+ "var res = [];"
+ "for (var val in o3) res.push(val); res"),
+ nxt_string("three,one") },
+
+ { nxt_string("var o1 = Object.create(null); o1.one = 1;"
+ "var o2 = Object.create(o1);"
+ "var o3 = Object.create(o2);"
+ "var res = [];"
+ "for (var val in o3) res.push(val); res"),
+ nxt_string("one") },
+
+ { nxt_string("var o1 = Object.create(null); o1.one = 1;"
+ "var o2 = Object.create(o1); o2.two = 2;"
+ "var o3 = Object.create(o2); o3.three = 3;"
+ "o3.two = -2; o3.one = -1;"
+ "var res = [];"
+ "for (var val in o3) res.push(val); res"),
+ nxt_string("three,two,one") },
+
{ nxt_string("Object.prototype.toString.call(Object.prototype)"),
nxt_string("[object Object]") },
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment