[njs] Object.keys() method.
Dmitry Volyntsev
xeioex at nginx.com
Wed Jun 7 11:16:53 UTC 2017
details: http://hg.nginx.org/njs/rev/fb703c8f4292
branches:
changeset: 352:fb703c8f4292
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Wed Jun 07 14:12:23 2017 +0300
description:
Object.keys() method.
diffstat:
njs/njs_object.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++
njs/njs_vm.h | 13 ++++++
njs/test/njs_unit_test.c | 19 ++++++++
3 files changed, 133 insertions(+), 0 deletions(-)
diffs (178 lines):
diff -r 02a59fe82c7a -r fb703c8f4292 njs/njs_object.c
--- a/njs/njs_object.c Mon Jun 05 14:59:28 2017 +0300
+++ b/njs/njs_object.c Wed Jun 07 14:12:23 2017 +0300
@@ -19,7 +19,9 @@
#include <njs_string.h>
#include <njs_object.h>
#include <njs_object_hash.h>
+#include <njs_array.h>
#include <njs_function.h>
+#include <stdio.h>
#include <string.h>
@@ -318,6 +320,97 @@ njs_object_create(njs_vm_t *vm, njs_valu
}
+static njs_ret_t
+njs_object_keys(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ size_t size;
+ uint32_t i, n, keys_length, array_length;
+ njs_value_t *value;
+ njs_array_t *keys, *array;
+ nxt_lvlhsh_t *hash;
+ njs_object_prop_t *prop;
+ nxt_lvlhsh_each_t lhe;
+
+ if (nargs < 2 || !njs_is_object(&args[1])) {
+ vm->exception = &njs_exception_type_error;
+ return NXT_ERROR;
+ }
+
+ keys_length = 0;
+ array_length = 0;
+
+ if (njs_is_array(&args[1])) {
+ array = args[1].data.u.array;
+ array_length = array->length;
+
+ for (i = 0; i < array_length; i++) {
+ if (njs_is_valid(&array->start[i])) {
+ keys_length++;
+ }
+ }
+ }
+
+ memset(&lhe, 0, sizeof(nxt_lvlhsh_each_t));
+ lhe.proto = &njs_object_hash_proto;
+
+ hash = &args[1].data.u.object->hash;
+
+ for ( ;; ) {
+ prop = nxt_lvlhsh_each(hash, &lhe);
+
+ if (prop == NULL) {
+ break;
+ }
+
+ if (prop->enumerable) {
+ keys_length++;
+ }
+ }
+
+ keys = njs_array_alloc(vm, keys_length, NJS_ARRAY_SPARE);
+ if (nxt_slow_path(keys == NULL)) {
+ return NXT_ERROR;
+ }
+
+ n = 0;
+
+ for (i = 0; i < array_length; i++) {
+ if (njs_is_valid(&array->start[i])) {
+ value = &keys->start[n++];
+ /*
+ * The maximum array index is 4294967294, so
+ * it can be stored as a short string inside value.
+ */
+ size = snprintf((char *) njs_string_short_start(value),
+ NJS_STRING_SHORT, "%u", i);
+ njs_string_short_set(value, size, size);
+ }
+ }
+
+ memset(&lhe, 0, sizeof(nxt_lvlhsh_each_t));
+ lhe.proto = &njs_object_hash_proto;
+
+ for ( ;; ) {
+ prop = nxt_lvlhsh_each(hash, &lhe);
+
+ if (prop == NULL) {
+ break;
+ }
+
+ if (prop->enumerable) {
+ njs_string_copy(&keys->start[n++], &prop->name);
+ }
+ }
+
+ vm->retval.data.u.array = keys;
+ vm->retval.type = NJS_ARRAY;
+ vm->retval.data.truth = 1;
+
+ return NXT_OK;
+}
+
+
/*
* The __proto__ property of booleans, numbers and strings primitives,
* of objects created by Boolean(), Number(), and String() constructors,
@@ -456,6 +549,14 @@ static const njs_object_prop_t njs_obje
.name = njs_string("create"),
.value = njs_native_function(njs_object_create, 0, 0),
},
+
+ /* Object.keys(). */
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("keys"),
+ .value = njs_native_function(njs_object_keys, 0,
+ NJS_SKIP_ARG, NJS_OBJECT_ARG),
+ },
};
diff -r 02a59fe82c7a -r fb703c8f4292 njs/njs_vm.h
--- a/njs/njs_vm.h Mon Jun 05 14:59:28 2017 +0300
+++ b/njs/njs_vm.h Wed Jun 07 14:12:23 2017 +0300
@@ -408,6 +408,19 @@ typedef njs_ret_t (*njs_vmcode_operation
#define njs_string_truth(value, size)
+#define njs_string_short_start(value) \
+ (value)->short_string.start
+
+
+#define njs_string_short_set(value, _size, _length) \
+ do { \
+ (value)->type = NJS_STRING; \
+ njs_string_truth(value, _size); \
+ (value)->short_string.size = _size; \
+ (value)->short_string.length = _length; \
+ } while (0)
+
+
#define njs_is_primitive(value) \
((value)->type <= NJS_STRING)
diff -r 02a59fe82c7a -r fb703c8f4292 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Mon Jun 05 14:59:28 2017 +0300
+++ b/njs/test/njs_unit_test.c Wed Jun 07 14:12:23 2017 +0300
@@ -5843,6 +5843,25 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("var o = Object.create(null); '__proto__' in o"),
nxt_string("false") },
+ { nxt_string("var o = {a:1, b:2, c:3};"
+ "Object.keys(o)"),
+ nxt_string("a,b,c") },
+
+ { nxt_string("var a = []; a.one = 7; Object.keys(a)"),
+ nxt_string("one") },
+
+ { nxt_string("var a = [,,]; a.one = 7; Object.keys(a)"),
+ nxt_string("one") },
+
+ { nxt_string("var a = [,6,,3]; a.one = 7; Object.keys(a)"),
+ nxt_string("1,3,one") },
+
+ { nxt_string("Object.keys('a')"),
+ nxt_string("TypeError") },
+
+ { nxt_string("Object.keys(1)"),
+ nxt_string("TypeError") },
+
{ nxt_string("var d = new Date(''); d +' '+ d.getTime()"),
nxt_string("Invalid Date NaN") },
More information about the nginx-devel
mailing list