From: Valentin Bartenev Date: Mon, 3 Dec 2018 16:23:27 +0000 (+0300) Subject: Object.entries() method. X-Git-Tag: 0.2.7~10 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=486c98f21e1c2b5e77c38ed7e673785c521ccfd1;p=njs.git Object.entries() method. --- diff --git a/njs/njs_object.c b/njs/njs_object.c index 6248bbee..c6414d20 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -914,6 +914,35 @@ njs_object_values(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, } +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 njs_value_t *value, 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; @@ -1012,6 +1041,29 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, } } + 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; } @@ -1056,6 +1108,66 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, } while (src != end); } + 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; } } @@ -1094,6 +1206,35 @@ njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, } } + 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_object_constructor_properties[] = 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 --git a/njs/njs_object.h b/njs/njs_object.h index ab7b1380..6c1c5239 100644 --- a/njs/njs_object.h +++ b/njs/njs_object.h @@ -20,6 +20,7 @@ typedef enum { typedef enum { NJS_ENUM_KEYS = 0, NJS_ENUM_VALUES, + NJS_ENUM_BOTH, } njs_object_enum_t; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index e0548916..3f84c3b5 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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") },