Created
April 8, 2019 16:19
-
-
Save lexborisov/52d270ffadcfbe4b9460031629a4ae2f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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