[njs] Introduced initial iterator support.
Dmitry Volyntsev
xeioex at nginx.com
Fri Nov 6 13:48:51 UTC 2020
details: https://hg.nginx.org/njs/rev/1c2313826b2b
branches:
changeset: 1561:1c2313826b2b
user: Artem S. Povalyukhin <artem.povaluhin at gmail.com>
date: Sun Oct 25 18:29:15 2020 +0300
description:
Introduced initial iterator support.
diffstat:
auto/sources | 1 +
src/njs_array.c | 54 ++++++++
src/njs_builtin.c | 9 +
src/njs_iterator.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++
src/njs_iterator.h | 21 +++
src/njs_main.h | 1 +
src/njs_string.c | 27 ++++
src/njs_typed_array.c | 59 +++++++++
src/njs_value.h | 1 +
src/njs_vm.h | 4 +-
src/test/njs_unit_test.c | 132 ++++++++++++++++++++
11 files changed, 607 insertions(+), 1 deletions(-)
diffs (769 lines):
diff -r 3e7f9e326219 -r 1c2313826b2b auto/sources
--- a/auto/sources Fri Nov 06 11:41:32 2020 +0000
+++ b/auto/sources Sun Oct 25 18:29:15 2020 +0300
@@ -58,6 +58,7 @@ NJS_LIB_SRCS=" \
src/njs_query_string.c \
src/njs_encoding.c \
src/njs_buffer.c \
+ src/njs_iterator.c \
"
NJS_LIB_TEST_SRCS=" \
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_array.c
--- a/src/njs_array.c Fri Nov 06 11:41:32 2020 +0000
+++ b/src/njs_array.c Sun Oct 25 18:29:15 2020 +0300
@@ -3351,6 +3351,24 @@ njs_array_prototype_copy_within(njs_vm_t
}
+static njs_int_t
+njs_array_prototype_iterator_obj(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t kind)
+{
+ njs_int_t ret;
+ njs_value_t *this;
+
+ this = njs_argument(args, 0);
+
+ ret = njs_value_to_object(vm, this);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_array_iterator_create(vm, this, &vm->retval, kind);
+}
+
+
static const njs_object_prop_t njs_array_prototype_properties[] =
{
{
@@ -3386,6 +3404,15 @@ static const njs_object_prop_t njs_arra
{
.type = NJS_PROPERTY,
+ .name = njs_string("entries"),
+ .value = njs_native_function2(njs_array_prototype_iterator_obj, 0,
+ NJS_ENUM_BOTH),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
.name = njs_string("every"),
.value = njs_native_function2(njs_array_prototype_iterator, 1,
njs_array_func(NJS_ARRAY_EVERY)),
@@ -3465,6 +3492,15 @@ static const njs_object_prop_t njs_arra
{
.type = NJS_PROPERTY,
+ .name = njs_string("keys"),
+ .value = njs_native_function2(njs_array_prototype_iterator_obj, 0,
+ NJS_ENUM_KEYS),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
.name = njs_string("lastIndexOf"),
.value = njs_native_function2(njs_array_prototype_reverse_iterator, 1,
NJS_ARRAY_LAST_INDEX_OF),
@@ -3579,6 +3615,24 @@ static const njs_object_prop_t njs_arra
.writable = 1,
.configurable = 1,
},
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("values"),
+ .value = njs_native_function2(njs_array_prototype_iterator_obj, 0,
+ NJS_ENUM_VALUES),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR),
+ .value = njs_native_function2(njs_array_prototype_iterator_obj, 0,
+ NJS_ENUM_VALUES),
+ .writable = 1,
+ .configurable = 1,
+ },
};
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_builtin.c
--- a/src/njs_builtin.c Fri Nov 06 11:41:32 2020 +0000
+++ b/src/njs_builtin.c Sun Oct 25 18:29:15 2020 +0300
@@ -85,6 +85,8 @@ static const njs_object_type_init_t *con
/* Hidden types. */
+ &njs_iterator_type_init,
+ &njs_array_iterator_type_init,
&njs_dirent_type_init,
&njs_hash_type_init,
&njs_hmac_type_init,
@@ -294,6 +296,10 @@ njs_builtin_objects_create(njs_vm_t *vm)
constructor = shared->constructors;
for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_MAX; i++) {
+ if (njs_object_type_init[i]->constructor_props == NULL) {
+ continue;
+ }
+
constructor[i] = njs_object_type_init[i]->constructor;
constructor[i].object.shared = 0;
@@ -360,6 +366,9 @@ njs_builtin_objects_clone(njs_vm_t *vm,
vm->prototypes[i].object.__proto__ = typed_array_prototype;
}
+ vm->prototypes[NJS_OBJ_TYPE_ARRAY_ITERATOR].object.__proto__ =
+ &vm->prototypes[NJS_OBJ_TYPE_ITERATOR].object;
+
vm->prototypes[NJS_OBJ_TYPE_BUFFER].object.__proto__ =
&vm->prototypes[NJS_OBJ_TYPE_UINT8_ARRAY].object;
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_iterator.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/njs_iterator.c Sun Oct 25 18:29:15 2020 +0300
@@ -0,0 +1,299 @@
+
+/*
+ * Copyright (C) Artem S. Povalyukhin
+ * Copyright (C) NGINX, Inc.
+ */
+
+
+#include <njs_main.h>
+
+
+struct njs_value_iterator_s {
+ njs_value_t target;
+ int64_t next;
+ njs_object_enum_t kind;
+};
+
+
+typedef struct njs_value_iterator_s njs_array_iterator_t;
+
+
+static const njs_value_t string_done = njs_string("done");
+static const njs_value_t string_value = njs_string("value");
+
+
+njs_int_t
+njs_array_iterator_create(njs_vm_t *vm, const njs_value_t *target,
+ njs_value_t *retval, njs_object_enum_t kind)
+{
+ njs_object_value_t *ov;
+ njs_array_iterator_t *it;
+
+ ov = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_value_t));
+ if (njs_slow_path(ov == NULL)) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ njs_lvlhsh_init(&ov->object.hash);
+ njs_lvlhsh_init(&ov->object.shared_hash);
+ ov->object.type = NJS_OBJECT_VALUE;
+ ov->object.shared = 0;
+ ov->object.extensible = 1;
+ ov->object.error_data = 0;
+ ov->object.fast_array = 0;
+
+ ov->object.__proto__ =
+ &vm->prototypes[NJS_OBJ_TYPE_ARRAY_ITERATOR].object;
+ ov->object.slots = NULL;
+
+ it = njs_mp_alloc(vm->mem_pool, sizeof(njs_array_iterator_t));
+ if (njs_slow_path(it == NULL)) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ /* GC retain it->target */
+ it->target = *target;
+ it->next = 0;
+ it->kind = kind;
+
+ njs_set_data(&ov->value, it, NJS_DATA_TAG_ARRAY_ITERATOR);
+ njs_set_object_value(retval, ov);
+
+ return NJS_OK;
+}
+
+
+njs_int_t
+njs_array_iterator_next(njs_vm_t *vm, njs_value_t *iterator,
+ njs_value_t *retval)
+{
+ int64_t length;
+ njs_int_t ret;
+ njs_array_t *array, *entry;
+ njs_typed_array_t *tarray;
+ const njs_value_t *value;
+ njs_array_iterator_t *it;
+
+ if (njs_slow_path(!njs_is_valid(njs_object_value(iterator)))) {
+ return NJS_DECLINED;
+ }
+
+ it = njs_object_data(iterator);
+ value = &njs_value_undefined;
+
+ if (njs_is_fast_array(&it->target)) {
+ array = njs_array(&it->target);
+ length = array->length;
+
+ if (it->next >= length) {
+ goto release;
+ }
+
+ if (it->kind > NJS_ENUM_KEYS && njs_is_valid(&array->start[it->next])) {
+ value = &array->start[it->next];
+ }
+
+ } else if (njs_is_typed_array(&it->target)) {
+ tarray = njs_typed_array(&it->target);
+
+ if (njs_slow_path(njs_is_detached_buffer(tarray->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
+ length = njs_typed_array_length(tarray);
+
+ if (it->next >= length) {
+ goto release;
+ }
+
+ if (it->kind > NJS_ENUM_KEYS) {
+ njs_set_number(retval, njs_typed_array_prop(tarray, it->next));
+ value = retval;
+ }
+
+ } else {
+ ret = njs_object_length(vm, &it->target, &length);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ if (it->next >= length) {
+ goto release;
+ }
+
+ if (it->kind > NJS_ENUM_KEYS) {
+ ret = njs_value_property_i64(vm, &it->target, it->next, retval);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ value = njs_is_valid(retval) ? retval
+ : &njs_value_undefined;
+ }
+ }
+
+ switch (it->kind) {
+ case NJS_ENUM_KEYS:
+ njs_set_number(retval, it->next++);
+ break;
+
+ case NJS_ENUM_VALUES:
+ it->next++;
+ *retval = *value;
+ break;
+
+ case NJS_ENUM_BOTH:
+ entry = njs_array_alloc(vm, 0, 2, 0);
+ if (njs_slow_path(entry == NULL)) {
+ return NJS_ERROR;
+ }
+
+ njs_set_number(&entry->start[0], it->next++);
+ entry->start[1] = *value;
+
+ njs_set_array(retval, entry);
+ break;
+
+ default:
+ njs_internal_error(vm, "invalid enum kind");
+ return NJS_ERROR;
+ }
+
+ return NJS_OK;
+
+release:
+
+ /* GC release it->target */
+ njs_mp_free(vm->mem_pool, it);
+ njs_set_invalid(njs_object_value(iterator));
+
+ return NJS_DECLINED;
+}
+
+
+static njs_int_t
+njs_iterator_prototype_get_this(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused)
+{
+ vm->retval = args[0];
+
+ return NJS_OK;
+}
+
+
+static const njs_object_prop_t njs_iterator_prototype_properties[] =
+{
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR),
+ .value = njs_native_function(njs_iterator_prototype_get_this, 0),
+ .configurable = 1,
+ .writable = 1,
+ },
+};
+
+
+static const njs_object_init_t njs_iterator_prototype_init = {
+ njs_iterator_prototype_properties,
+ njs_nitems(njs_iterator_prototype_properties),
+};
+
+
+const njs_object_type_init_t njs_iterator_type_init = {
+ .prototype_props = &njs_iterator_prototype_init,
+ .prototype_value = { .object = { .type = NJS_OBJECT } },
+};
+
+
+static njs_int_t
+njs_array_iterator_prototype_next(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t tag)
+{
+ njs_int_t ret;
+ njs_bool_t check;
+ njs_value_t *this;
+ njs_object_t *object;
+ njs_object_prop_t *prop_value, *prop_done;
+
+ this = njs_argument(args, 0);
+
+ check = njs_is_object_value(this)
+ && (njs_is_object_data(this, NJS_DATA_TAG_ARRAY_ITERATOR)
+ || !njs_is_valid(njs_object_value(this)));
+
+ if (njs_slow_path(!check)) {
+ njs_type_error(vm, "Method [Array Iterator].prototype.next"
+ " called on incompatible receiver");
+ return NJS_ERROR;
+ }
+
+ object = njs_object_alloc(vm);
+ if (njs_slow_path(object == NULL)) {
+ return NJS_ERROR;
+ }
+
+ njs_set_object(&vm->retval, object);
+
+ prop_value = njs_object_property_add(vm, &vm->retval,
+ njs_value_arg(&string_value), 0);
+ if (njs_slow_path(prop_value == NULL)) {
+ return NJS_ERROR;
+ }
+
+ prop_done = njs_object_property_add(vm, &vm->retval,
+ njs_value_arg(&string_done), 0);
+ if (njs_slow_path(prop_done == NULL)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_array_iterator_next(vm, this, &prop_value->value);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ if (njs_slow_path(ret == NJS_DECLINED)) {
+ njs_set_undefined(&prop_value->value);
+ njs_set_boolean(&prop_done->value, 1);
+
+ return NJS_OK;
+ }
+
+ njs_set_boolean(&prop_done->value, 0);
+
+ return NJS_OK;
+}
+
+
+static const njs_object_prop_t njs_array_iterator_prototype_properties[] =
+{
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("next"),
+ .value = njs_native_function2(njs_array_iterator_prototype_next, 0,
+ NJS_DATA_TAG_ARRAY_ITERATOR),
+ .configurable = 1,
+ .writable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG),
+ .value = njs_string("Array Iterator"),
+ .configurable = 1,
+ },
+};
+
+
+static const njs_object_init_t njs_array_iterator_prototype_init = {
+ njs_array_iterator_prototype_properties,
+ njs_nitems(njs_array_iterator_prototype_properties),
+};
+
+
+const njs_object_type_init_t njs_array_iterator_type_init = {
+ .prototype_props = &njs_array_iterator_prototype_init,
+ .prototype_value = { .object = { .type = NJS_OBJECT } },
+};
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_iterator.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/njs_iterator.h Sun Oct 25 18:29:15 2020 +0300
@@ -0,0 +1,21 @@
+
+/*
+ * Copyright (C) Artem S. Povalyukhin
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NJS_ITERATOR_H_INCLUDED_
+#define _NJS_ITERATOR_H_INCLUDED_
+
+
+njs_int_t njs_array_iterator_create(njs_vm_t *vm, const njs_value_t *src,
+ njs_value_t *dst, njs_object_enum_t kind);
+
+njs_int_t njs_array_iterator_next(njs_vm_t *vm, njs_value_t *iterator,
+ njs_value_t *retval);
+
+
+extern const njs_object_type_init_t njs_iterator_type_init;
+extern const njs_object_type_init_t njs_array_iterator_type_init;
+
+#endif /* _NJS_ITERATOR_H_INCLUDED_ */
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_main.h
--- a/src/njs_main.h Fri Nov 06 11:41:32 2020 +0000
+++ b/src/njs_main.h Sun Oct 25 18:29:15 2020 +0300
@@ -71,6 +71,7 @@
#include <njs_regexp_pattern.h>
#include <njs_date.h>
#include <njs_promise.h>
+#include <njs_iterator.h>
#include <njs_math.h>
#include <njs_json.h>
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_string.c
--- a/src/njs_string.c Fri Nov 06 11:41:32 2020 +0000
+++ b/src/njs_string.c Sun Oct 25 18:29:15 2020 +0300
@@ -3845,6 +3845,24 @@ njs_string_prototype_replace(njs_vm_t *v
}
+static njs_int_t
+njs_string_prototype_iterator_obj(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t kind)
+{
+ njs_int_t ret;
+ njs_value_t *this;
+
+ this = njs_argument(args, 0);
+
+ ret = njs_string_object_validate(vm, this);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ return njs_array_iterator_create(vm, this, &vm->retval, kind);
+}
+
+
double
njs_string_to_number(const njs_value_t *value, njs_bool_t parse_float)
{
@@ -4327,6 +4345,15 @@ static const njs_object_prop_t njs_stri
.writable = 1,
.configurable = 1,
},
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR),
+ .value = njs_native_function2(njs_string_prototype_iterator_obj, 0,
+ NJS_ENUM_VALUES),
+ .writable = 1,
+ .configurable = 1,
+ },
};
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_typed_array.c
--- a/src/njs_typed_array.c Fri Nov 06 11:41:32 2020 +0000
+++ b/src/njs_typed_array.c Sun Oct 25 18:29:15 2020 +0300
@@ -2184,6 +2184,29 @@ njs_typed_array_prototype_join(njs_vm_t
static njs_int_t
+njs_typed_array_prototype_iterator_obj(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t kind)
+{
+ njs_value_t *this;
+ njs_typed_array_t *array;
+
+ this = njs_argument(args, 0);
+ if (njs_slow_path(!njs_is_typed_array(this))) {
+ njs_type_error(vm, "this is not a typed array");
+ return NJS_ERROR;
+ }
+
+ array = njs_typed_array(this);
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
+ return njs_array_iterator_create(vm, this, &vm->retval, kind);
+}
+
+
+static njs_int_t
njs_typed_array_constructor_intrinsic(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused)
{
@@ -2326,6 +2349,15 @@ static const njs_object_prop_t njs_type
{
.type = NJS_PROPERTY,
+ .name = njs_string("entries"),
+ .value = njs_native_function2(njs_typed_array_prototype_iterator_obj, 0,
+ NJS_ENUM_BOTH),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
.name = njs_string("every"),
.value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
NJS_ARRAY_EVERY),
@@ -2403,6 +2435,15 @@ static const njs_object_prop_t njs_type
{
.type = NJS_PROPERTY,
+ .name = njs_string("keys"),
+ .value = njs_native_function2(njs_typed_array_prototype_iterator_obj, 0,
+ NJS_ENUM_KEYS),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
.name = njs_string("lastIndexOf"),
.value = njs_native_function2(njs_typed_array_prototype_index_of, 1, 2),
.writable = 1,
@@ -2490,6 +2531,24 @@ static const njs_object_prop_t njs_type
.writable = 1,
.configurable = 1,
},
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("values"),
+ .value = njs_native_function2(njs_typed_array_prototype_iterator_obj, 0,
+ NJS_ENUM_VALUES),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_wellknown_symbol(NJS_SYMBOL_ITERATOR),
+ .value = njs_native_function2(njs_typed_array_prototype_iterator_obj, 0,
+ NJS_ENUM_VALUES),
+ .writable = 1,
+ .configurable = 1,
+ },
};
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_value.h
--- a/src/njs_value.h Fri Nov 06 11:41:32 2020 +0000
+++ b/src/njs_value.h Sun Oct 25 18:29:15 2020 +0300
@@ -84,6 +84,7 @@ typedef enum {
NJS_DATA_TAG_CRYPTO_HMAC,
NJS_DATA_TAG_TEXT_ENCODER,
NJS_DATA_TAG_TEXT_DECODER,
+ NJS_DATA_TAG_ARRAY_ITERATOR,
NJS_DATA_TAG_MAX
} njs_data_tag_t;
diff -r 3e7f9e326219 -r 1c2313826b2b src/njs_vm.h
--- a/src/njs_vm.h Fri Nov 06 11:41:32 2020 +0000
+++ b/src/njs_vm.h Sun Oct 25 18:29:15 2020 +0300
@@ -89,7 +89,9 @@ typedef enum {
NJS_OBJ_TYPE_TEXT_ENCODER,
NJS_OBJ_TYPE_BUFFER,
-#define NJS_OBJ_TYPE_HIDDEN_MIN (NJS_OBJ_TYPE_FS_DIRENT)
+#define NJS_OBJ_TYPE_HIDDEN_MIN (NJS_OBJ_TYPE_ITERATOR)
+ NJS_OBJ_TYPE_ITERATOR,
+ NJS_OBJ_TYPE_ARRAY_ITERATOR,
NJS_OBJ_TYPE_FS_DIRENT,
NJS_OBJ_TYPE_CRYPTO_HASH,
NJS_OBJ_TYPE_CRYPTO_HMAC,
diff -r 3e7f9e326219 -r 1c2313826b2b src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Fri Nov 06 11:41:32 2020 +0000
+++ b/src/test/njs_unit_test.c Sun Oct 25 18:29:15 2020 +0300
@@ -6864,6 +6864,138 @@ static njs_unit_test_t njs_test[] =
{ njs_str("[1,2].sort(1)"),
njs_str("TypeError: comparefn must be callable or undefined") },
+ /*
+ Array.prototype.keys()
+ Array.prototype.values()
+ Array.prototype.entries()
+ */
+
+ { njs_str("['keys', 'values', 'entries', Symbol.iterator]"
+ ".every((x) => typeof Array.prototype[x] == 'function')"),
+ njs_str("true") },
+
+ { njs_str("['keys', 'values', 'entries', Symbol.iterator]"
+ ".every((x) => Array.prototype[x].length === 0)"),
+ njs_str("true") },
+
+#if 0
+ { njs_str("Array.prototype[Symbol.iterator] === Array.prototype.values"),
+ njs_str("true") },
+#endif
+
+ { njs_str("['keys', 'values', 'entries', Symbol.iterator]"
+ ".every((x) => typeof [][x]() == 'object')"),
+ njs_str("true") },
+
+ { njs_str("['keys', 'values', 'entries', Symbol.iterator]"
+ ".every((x) => typeof [][x]().next == 'function')"),
+ njs_str("true") },
+
+ { njs_str("var i = [1,2,3].keys();"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("0,1,2,") },
+
+ { njs_str("var i = [1,2,3].values();"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("1,2,3,") },
+
+ { njs_str("var a = [], i = a.values();"
+ "a.push(1); a.push(2); a.push(3);"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("1,2,3,") },
+
+ { njs_str("var a = [], i = a.values(); i.next();"
+ "a.push(1); a.push(2); a.push(3);"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str(",,,") },
+
+ { njs_str("var i = [1,2,3].entries();"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("0,1,1,2,2,3,") },
+
+ { njs_str("var i = Array.prototype.keys.call('abc');"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.done)"),
+ njs_str("false,false,false,true") },
+
+ { njs_str("var i = Array.prototype.values.call('abc');"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("a,b,c,") },
+
+ { njs_str("var x = [true, 1, Symbol()];"
+ "x.map((x) => Array.prototype.keys.call(x).next()).every((x) => x.done)"),
+ njs_str("true") },
+
+ { njs_str("var x = [true, 1, Symbol()];"
+ "x.forEach((x) => Object.getPrototypeOf(Object(x)).length = 1);"
+ "x.map((x) => Array.prototype.keys.call(x).next()).every((x) => !x.done)"),
+ njs_str("true") },
+
+ /*
+ TypedArray.prototype.keys()
+ TypedArray.prototype.values()
+ TypedArray.prototype.entries()
+ */
+
+ { njs_str("['keys', 'values', 'entries', Symbol.iterator]"
+ ".every((x) => typeof Buffer.prototype[x] == 'function')"),
+ njs_str("true") },
+
+ { njs_str("var i = Buffer.from([1,2,3]).keys();"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("0,1,2,") },
+
+ { njs_str("var i = Buffer.from([1,2,3]).values();"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("1,2,3,") },
+
+ { njs_str("var i = Buffer.from([1,2,3]).entries();"
+ "[i.next(), i.next(), i.next(), i.next()].map((x) => x.value)"),
+ njs_str("0,1,1,2,2,3,") },
+
+ { njs_str("[true, 1, Symbol(), 'test', [], { length: 1 }]"
+ ".map((x) => { try { Buffer.prototype.keys.call(x); return x; } catch (e) { return e; } })"
+ ".every((x) => x instanceof TypeError)"),
+ njs_str("true") },
+
+ /* %IteratorPrototype% */
+
+ { njs_str("var x = Object.getPrototypeOf(Object.getPrototypeOf([].keys()));"
+ "typeof x[Symbol.iterator] == 'function'"),
+ njs_str("true") },
+
+ { njs_str("var x = Object.getPrototypeOf(Object.getPrototypeOf([].keys()));"
+ "x[Symbol.iterator]() === x"),
+ njs_str("true") },
+
+ /* %ArrayIteratorPrototype% */
+
+ { njs_str("var x = Object.getPrototypeOf([].keys());"
+ "typeof x.next == 'function'"),
+ njs_str("true") },
+
+ { njs_str("var x = Object.getPrototypeOf([].keys());"
+ "x[Symbol.toStringTag] == 'Array Iterator'"),
+ njs_str("true") },
+
+ /* %StringIteratorPrototype% */
+
+ { njs_str("typeof String.prototype[Symbol.iterator] == 'function'"),
+ njs_str("true") },
+
+ { njs_str("var x = Object.getPrototypeOf(''[Symbol.iterator]());"
+ "typeof x.next == 'function'"),
+ njs_str("true") },
+
+#if 0
+ { njs_str("var x = Object.getPrototypeOf(''[Symbol.iterator]());"
+ "x[Symbol.toStringTag] == 'String Iterator'"),
+ njs_str("true") },
+#else
+ { njs_str("var x = Object.getPrototypeOf(''[Symbol.iterator]());"
+ "x[Symbol.toStringTag] == 'Array Iterator'"),
+ njs_str("true") },
+#endif
+
/* Template literal. */
{ njs_str("`"),
More information about the nginx-devel
mailing list