From: Artem S. Povalyukhin Date: Wed, 27 Mar 2019 17:49:03 +0000 (+0300) Subject: Added Object.getOwnPropertyDescriptors(). X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=32fdddfaf7a08caea59daf145ff3125aeec289a0;p=njs.git Added Object.getOwnPropertyDescriptors(). This closes #119 issue on Github. --- diff --git a/njs/njs_object.c b/njs/njs_object.c index 6d0fd3f3..d124f655 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -1782,6 +1782,75 @@ njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args, } +static njs_ret_t +njs_object_get_own_property_descriptors(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + njs_ret_t ret; + uint32_t i, length; + njs_array_t *names; + njs_value_t descriptor; + njs_object_t *descriptors; + const njs_value_t *value, *key; + njs_object_prop_t *pr; + nxt_lvlhsh_query_t lhq; + + value = njs_arg(args, nargs, 1); + + if (njs_is_null_or_undefined(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); + + return NXT_ERROR; + } + + names = njs_object_enumerate(vm, value, NJS_ENUM_KEYS, 1); + if (nxt_slow_path(names == NULL)) { + return NXT_ERROR; + } + + length = names->length; + + descriptors = njs_object_alloc(vm); + if (nxt_slow_path(descriptors == NULL)) { + return NXT_ERROR; + } + + lhq.replace = 0; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + + for (i = 0; i < length; i++) { + key = &names->start[i]; + ret = njs_object_property_descriptor(vm, &descriptor, value, key); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + pr = njs_object_prop_alloc(vm, key, &descriptor, 1); + if (nxt_slow_path(pr == NULL)) { + return NXT_ERROR; + } + + njs_string_get(key, &lhq.key); + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + lhq.value = pr; + + ret = nxt_lvlhsh_insert(&descriptors->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } + } + + vm->retval.data.u.object = descriptors; + vm->retval.type = NJS_OBJECT; + vm->retval.data.truth = 1; + + return NXT_OK; +} + + static njs_ret_t njs_object_get_own_property_names(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) @@ -2243,6 +2312,14 @@ static const njs_object_prop_t njs_object_constructor_properties[] = NJS_STRING_ARG), }, + /* Object.getOwnPropertyDescriptors(). */ + { + .type = NJS_METHOD, + .name = njs_long_string("getOwnPropertyDescriptors"), + .value = njs_native_function(njs_object_get_own_property_descriptors, 0, + NJS_SKIP_ARG, NJS_OBJECT_ARG), + }, + /* Object.getOwnPropertyNames(). */ { .type = NJS_METHOD, diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index d6f62cd2..533ba1a0 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -8672,6 +8672,22 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = {}; o[void 0] = 'a'; Object.getOwnPropertyDescriptor(o, undefined).value"), nxt_string("a") }, + { nxt_string("Object.getOwnPropertyDescriptors()"), + nxt_string("TypeError: cannot convert undefined argument to object") }, + + { nxt_string("typeof Object.getOwnPropertyDescriptors(1)"), + nxt_string("object") }, + + { nxt_string("Object.keys(Object.getOwnPropertyDescriptors([]))"), + nxt_string("length") }, + + { nxt_string("Object.getOwnPropertyDescriptors(function(a,b,c) {}).length.value"), + nxt_string("3") }, + + { nxt_string("Object.values(Object.getOwnPropertyDescriptors('abc'))" + ".reduce(function(a, x) { return a += x.value; }, '')"), + nxt_string("abc3") }, + { nxt_string("Object.getOwnPropertyNames()"), nxt_string("TypeError: cannot convert undefined argument to object") },