details: https://hg.nginx.org/njs/rev/ce3a943df9c4 branches: changeset: 683:ce3a943df9c4 user: Valentin Bartenev <vb...@nginx.com> date: Mon Dec 03 19:23:27 2018 +0300 description: Object.entries() method.
diffstat: njs/njs_object.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++- njs/njs_object.h | 1 + njs/test/njs_unit_test.c | 37 +++++++++++ 3 files changed, 188 insertions(+), 1 deletions(-) diffs (261 lines): diff -r 1af8f40573f2 -r ce3a943df9c4 njs/njs_object.c --- a/njs/njs_object.c Mon Dec 03 19:20:58 2018 +0300 +++ b/njs/njs_object.c Mon Dec 03 19:23:27 2018 +0300 @@ -914,6 +914,35 @@ njs_object_values(njs_vm_t *vm, njs_valu } +static njs_ret_t +njs_object_entries(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, + njs_index_t unused) + { + njs_array_t *array; + const njs_value_t *value; + + value = njs_arg(args, nargs, 1); + + if (njs_is_null_or_void(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); + + return NXT_ERROR; + } + + array = njs_object_enumerate(vm, value, NJS_ENUM_BOTH); + if (array == NULL) { + return NXT_ERROR; + } + + vm->retval.data.u.array = array; + vm->retval.type = NJS_ARRAY; + vm->retval.data.truth = 1; + + return NXT_OK; +} + + njs_array_t * njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, njs_object_enum_t kind) @@ -921,7 +950,7 @@ njs_object_enumerate(njs_vm_t *vm, const u_char *dst; uint32_t i, length, size, items_length, properties; njs_value_t *string, *item; - njs_array_t *items, *array; + njs_array_t *items, *array, *entry; nxt_lvlhsh_t *hash; const u_char *src, *end; njs_object_prop_t *prop; @@ -1013,6 +1042,29 @@ njs_object_enumerate(njs_vm_t *vm, const } break; + + case NJS_ENUM_BOTH: + for (i = 0; i < length; i++) { + if (njs_is_valid(&array->start[i])) { + entry = njs_array_alloc(vm, 2, 0); + if (nxt_slow_path(entry == NULL)) { + return NULL; + } + + njs_uint32_to_string(&entry->start[0], i); + + /* GC: retain. */ + entry->start[1] = array->start[i]; + + item->data.u.array = entry; + item->type = NJS_ARRAY; + item->data.truth = 1; + + item++; + } + } + + break; } } else if (length != 0) { @@ -1057,6 +1109,66 @@ njs_object_enumerate(njs_vm_t *vm, const } break; + + case NJS_ENUM_BOTH: + if (string_prop.size == (size_t) length) { + /* Byte or ASCII string. */ + + for (i = 0; i < length; i++) { + entry = njs_array_alloc(vm, 2, 0); + if (nxt_slow_path(entry == NULL)) { + return NULL; + } + + njs_uint32_to_string(&entry->start[0], i); + + string = &entry->start[1]; + + dst = njs_string_short_start(string); + dst[0] = string_prop.start[i]; + + njs_string_short_set(string, 1, 1); + + item->data.u.array = entry; + item->type = NJS_ARRAY; + item->data.truth = 1; + + item++; + } + + } else { + /* UTF-8 string. */ + + src = string_prop.start; + end = src + string_prop.size; + i = 0; + + do { + entry = njs_array_alloc(vm, 2, 0); + if (nxt_slow_path(entry == NULL)) { + return NULL; + } + + njs_uint32_to_string(&entry->start[0], i++); + + string = &entry->start[1]; + + dst = njs_string_short_start(string); + dst = nxt_utf8_copy(dst, &src, end); + size = dst - njs_string_short_start(value); + + njs_string_short_set(string, size, 1); + + item->data.u.array = entry; + item->type = NJS_ARRAY; + item->data.truth = 1; + + item++; + + } while (src != end); + } + + break; } } @@ -1095,6 +1207,35 @@ njs_object_enumerate(njs_vm_t *vm, const } break; + + case NJS_ENUM_BOTH: + for ( ;; ) { + prop = nxt_lvlhsh_each(hash, &lhe); + + if (prop == NULL) { + break; + } + + if (prop->type != NJS_WHITEOUT && prop->enumerable) { + entry = njs_array_alloc(vm, 2, 0); + if (nxt_slow_path(entry == NULL)) { + return NULL; + } + + njs_string_copy(&entry->start[0], &prop->name); + + /* GC: retain. */ + entry->start[1] = prop->value; + + item->data.u.array = entry; + item->type = NJS_ARRAY; + item->data.truth = 1; + + item++; + } + } + + break; } } @@ -1970,6 +2111,14 @@ static const njs_object_prop_t njs_obje NJS_SKIP_ARG, NJS_OBJECT_ARG), }, + /* ES8: Object.entries(). */ + { + .type = NJS_METHOD, + .name = njs_string("entries"), + .value = njs_native_function(njs_object_entries, 0, + NJS_SKIP_ARG, NJS_OBJECT_ARG), + }, + /* Object.defineProperty(). */ { .type = NJS_METHOD, diff -r 1af8f40573f2 -r ce3a943df9c4 njs/njs_object.h --- a/njs/njs_object.h Mon Dec 03 19:20:58 2018 +0300 +++ b/njs/njs_object.h Mon Dec 03 19:23:27 2018 +0300 @@ -20,6 +20,7 @@ typedef enum { typedef enum { NJS_ENUM_KEYS = 0, NJS_ENUM_VALUES, + NJS_ENUM_BOTH, } njs_object_enum_t; diff -r 1af8f40573f2 -r ce3a943df9c4 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon Dec 03 19:20:58 2018 +0300 +++ b/njs/test/njs_unit_test.c Mon Dec 03 19:23:27 2018 +0300 @@ -7445,6 +7445,29 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.values()"), nxt_string("TypeError: cannot convert undefined argument to object") }, + { nxt_string("Object.entries('abc')"), + nxt_string("0,a,1,b,2,c") }, + + { nxt_string("JSON.stringify(Object.entries('эюя'))"), + nxt_string("[[\"0\",\"э\"],[\"1\",\"ю\"],[\"2\",\"я\"]]") }, + + { nxt_string("var o = {a:\"а\", b:\"б\", c:\"ц\"};" + "JSON.stringify(Object.entries(o))"), + nxt_string("[[\"a\",\"а\"],[\"b\",\"б\"],[\"c\",\"ц\"]]") }, + + { nxt_string("JSON.stringify(Object.entries([0]))"), + nxt_string("[[\"0\",0]]") }, + + { nxt_string("var s = new String('αβ'); s.two = null; s[3] = true;" + "Object.entries(s)"), + nxt_string("0,α,1,β,two,,3,true") }, + + { nxt_string("Object.entries(true)"), + nxt_string("") }, + + { nxt_string("Object.entries()"), + nxt_string("TypeError: cannot convert undefined argument to object") }, + { nxt_string("var o = {}; Object.defineProperty(o, 'a', {}); o.a"), nxt_string("undefined") }, @@ -7482,6 +7505,20 @@ static njs_unit_test_t njs_test[] = "Object.values(o)"), nxt_string("1,3,2") }, + { nxt_string("var o = {a:1, c:2}; Object.defineProperty(o, 'b', {});" + "Object.entries(o)"), + nxt_string("a,1,c,2") }, + + { nxt_string("var o = {a:1, c:2};" + "Object.defineProperty(o, 'b', {enumerable:false, value:3});" + "Object.entries(o)"), + nxt_string("a,1,c,2") }, + + { nxt_string("var o = {a:1, c:3};" + "Object.defineProperty(o, 'b', {enumerable:true, value:2});" + "Object.entries(o)"), + nxt_string("a,1,c,3,b,2") }, + { nxt_string("var o = {}; Object.defineProperty(o, 'a', {}); o.a = 1"), nxt_string("TypeError: Cannot assign to read-only property 'a' of object") }, _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel