From 4fb121fed1e0786d774af9b96e733fa9e557f155 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Fri, 21 Aug 2020 13:07:48 +0000 Subject: [PATCH] Added remaining methods for %TypedArray%.prototype. The following methods were added: every(), filter(), find(), findIndex(), forEach(), includes(), indexOf(), lastIndexOf(), map(), reduce(), reduceRight(), reverse(), some(). --- src/njs_typed_array.c | 698 ++++++++++++++++++++++++++++++++++++++- src/njs_utils.c | 56 ---- src/njs_utils.h | 57 ++++ src/test/njs_unit_test.c | 377 ++++++++++++++++++--- 4 files changed, 1079 insertions(+), 109 deletions(-) diff --git a/src/njs_typed_array.c b/src/njs_typed_array.c index cf4543cb..8f55d34c 100644 --- a/src/njs_typed_array.c +++ b/src/njs_typed_array.c @@ -8,6 +8,17 @@ #include +typedef enum { + NJS_ARRAY_EVERY = 0, + NJS_ARRAY_FOR_EACH, + NJS_ARRAY_SOME, + NJS_ARRAY_FIND, + NJS_ARRAY_FIND_INDEX, + NJS_ARRAY_FILTER, + NJS_ARRAY_MAP, +} njs_array_iterator_fun_t; + + njs_typed_array_t * njs_typed_array_alloc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_object_type_t type) @@ -826,6 +837,558 @@ njs_typed_array_prototype_copy_within(njs_vm_t *vm, njs_value_t *args, } +static njs_int_t +njs_typed_array_prototype_iterator(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t type) +{ + double val; + int64_t i, length; + njs_int_t ret; + njs_arr_t results; + njs_value_t *this, *this_arg, *r; + njs_value_t arguments[4], retval; + njs_function_t *function; + njs_typed_array_t *array, *dst; + + 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; + } + + dst = NULL; + array = njs_typed_array(this); + length = njs_typed_array_length(array); + + if (njs_slow_path(!njs_is_function(njs_arg(args, nargs, 1)))) { + njs_type_error(vm, "callback argument is not callable"); + return NJS_ERROR; + } + + function = njs_function(njs_argument(args, 1)); + this_arg = njs_arg(args, nargs, 2); + + results.separate = 0; + results.pointer = 0; + + switch (type) { + case NJS_ARRAY_MAP: + njs_set_number(&arguments[0], length); + ret = njs_typed_array_species_create(vm, this, njs_value_arg(arguments), + 1, &retval); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + dst = njs_typed_array(&retval); + break; + + case NJS_ARRAY_FILTER: + r = njs_arr_init(vm->mem_pool, &results, NULL, 4, sizeof(njs_value_t)); + if (njs_slow_path(r == NULL)) { + return NJS_ERROR; + } + + default: + break; + } + + for (i = 0; i < length; i++) { + val = njs_typed_array_get(array, i); + + arguments[0] = *this_arg; + njs_set_number(&arguments[1], val); + njs_set_number(&arguments[2], i); + njs_set_typed_array(&arguments[3], array); + + ret = njs_function_apply(vm, function, arguments, 4, &vm->retval); + if (njs_slow_path(ret != NJS_OK)) { + goto exception; + } + + switch (type) { + case NJS_ARRAY_EVERY: + if (!njs_is_true(&vm->retval)) { + vm->retval = njs_value_false; + goto done; + } + + break; + + case NJS_ARRAY_FOR_EACH: + break; + + case NJS_ARRAY_SOME: + case NJS_ARRAY_FIND: + case NJS_ARRAY_FIND_INDEX: + if (!njs_is_true(&vm->retval)) { + continue; + } + + switch (type) { + case NJS_ARRAY_SOME: + vm->retval = njs_value_true; + break; + + case NJS_ARRAY_FIND: + njs_set_number(&vm->retval, val); + break; + + default: + njs_set_number(&vm->retval, i); + break; + } + + goto done; + + case NJS_ARRAY_MAP: + ret = njs_typed_array_set_value(vm, dst, i, &vm->retval); + if (njs_slow_path(ret != NJS_OK)) { + goto exception; + } + + break; + + default: + /* NJS_ARRAY_FILTER. */ + + if (!njs_is_true(&vm->retval)) { + continue; + } + + r = njs_arr_add(&results); + if (njs_slow_path(r == NULL)) { + goto exception; + } + + njs_set_number(r, val); + } + } + + /* Default values. */ + + switch (type) { + case NJS_ARRAY_EVERY: + vm->retval = njs_value_true; + break; + + case NJS_ARRAY_SOME: + vm->retval = njs_value_false; + break; + + case NJS_ARRAY_FOR_EACH: + case NJS_ARRAY_FIND: + njs_set_undefined(&vm->retval); + break; + + case NJS_ARRAY_FIND_INDEX: + njs_set_number(&vm->retval, -1); + break; + + case NJS_ARRAY_MAP: + case NJS_ARRAY_FILTER: + default: + if (type == NJS_ARRAY_FILTER) { + njs_set_number(&arguments[0], results.items); + ret = njs_typed_array_species_create(vm, this, + njs_value_arg(arguments), + 1, &retval); + if (njs_slow_path(ret != NJS_OK)) { + goto exception; + } + + dst = njs_typed_array(&retval); + + i = 0; + + while (i < results.items) { + r = njs_arr_item(&results, i); + ret = njs_typed_array_set_value(vm, dst, i++, r); + if (njs_slow_path(ret != NJS_OK)) { + goto exception; + } + } + } + + njs_set_typed_array(&vm->retval, dst); + break; + } + +done: + + ret = NJS_OK; + +exception: + + njs_arr_destroy(&results); + + return ret; +} + + +static njs_int_t +njs_typed_array_prototype_index_of(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t type) +{ + double v; + int64_t i, i64, from, to, index, increment, offset, length; + njs_int_t ret, integer; + njs_value_t *this; + const float *f32; + const double *f64; + const uint8_t *u8; + const uint16_t *u16; + const uint32_t *u32; + njs_typed_array_t *array; + njs_array_buffer_t *buffer; + + 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; + } + + index = -1; + array = njs_typed_array(this); + length = njs_typed_array_length(array); + + if (!njs_is_number(njs_arg(args, nargs, 1)) || length == 0) { + goto done; + } + + if (type & 2) { + /* lastIndexOf(). */ + + if (nargs > 2) { + ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &from); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + from = length - 1; + } + + if (from >= 0) { + from = njs_min(from, length - 1); + + } else if (from < 0) { + from += length; + } + + to = -1; + increment = -1; + + if (from <= to) { + goto done; + } + + } else { + /* indexOf(), includes(). */ + + ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &from); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (from < 0) { + from += length; + + if (from < 0) { + from = 0; + } + } + + to = length; + increment = 1; + + if (from >= to) { + goto done; + } + } + + v = njs_number(njs_argument(args, 1)); + + i64 = v; + integer = (v == i64); + + buffer = array->buffer; + offset = array->offset; + + switch (array->type) { + case NJS_OBJ_TYPE_INT8_ARRAY: + if (integer && ((int8_t) i64 == i64)) { + goto search8; + } + + break; + + case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY: + case NJS_OBJ_TYPE_UINT8_ARRAY: + if (integer && ((uint8_t) i64 == i64)) { +search8: + u8 = &buffer->u.u8[0]; + for (i = from; i != to; i += increment) { + if (u8[offset + i] == (uint8_t) i64) { + index = i; + break; + } + } + } + + break; + + case NJS_OBJ_TYPE_INT16_ARRAY: + if (integer && ((int16_t) i64 == i64)) { + goto search16; + } + + break; + + case NJS_OBJ_TYPE_UINT16_ARRAY: + if (integer && ((uint16_t) i64 == i64)) { +search16: + u16 = &buffer->u.u16[0]; + for (i = from; i != to; i += increment) { + if (u16[offset + i] == (uint16_t) i64) { + index = i; + break; + } + } + } + + break; + + case NJS_OBJ_TYPE_INT32_ARRAY: + if (integer && ((int32_t) i64 == i64)) { + goto search32; + } + + break; + + case NJS_OBJ_TYPE_UINT32_ARRAY: + if (integer && ((uint32_t) i64 == i64)) { +search32: + u32 = &buffer->u.u32[0]; + for (i = from; i != to; i += increment) { + if (u32[offset + i] == (uint32_t) i64) { + index = i; + break; + } + } + } + + break; + + case NJS_OBJ_TYPE_FLOAT32_ARRAY: + f32 = &buffer->u.f32[0]; + + if (((float) v == v)) { + for (i = from; i != to; i += increment) { + if (f32[offset + i] == (float) v) { + index = i; + break; + } + } + + } else if ((type & 1) && isnan(v)) { + /* includes() handles NaN. */ + + for (i = from; i != to; i += increment) { + if (isnan(f32[offset + i])) { + index = i; + break; + } + } + } + + break; + + default: + + /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ + + f64 = &buffer->u.f64[0]; + + if ((type & 1) && isnan(v)) { + /* includes() handles NaN. */ + + for (i = from; i != to; i += increment) { + if (isnan(f64[offset + i])) { + index = i; + break; + } + } + + } else { + for (i = from; i != to; i += increment) { + if (f64[offset + i] == v) { + index = i; + break; + } + } + } + } + +done: + + /* Default values. */ + + if (type & 1) { + njs_set_boolean(&vm->retval, index != -1); + + } else { + njs_set_number(&vm->retval, index); + } + + return NJS_OK; +} + + +static njs_int_t +njs_typed_array_prototype_reduce(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t right) +{ + int64_t i, from, to, increment, length; + njs_int_t ret; + njs_value_t *this, accumulator; + njs_value_t arguments[5]; + njs_function_t *function; + 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); + length = njs_typed_array_length(array); + + if (njs_slow_path(!njs_is_function(njs_arg(args, nargs, 1)))) { + njs_type_error(vm, "callback argument is not callable"); + return NJS_ERROR; + } + + function = njs_function(njs_argument(args, 1)); + + if (length == 0 && nargs <= 2) { + njs_type_error(vm, "Reduce of empty object with no initial value"); + return NJS_ERROR; + } + + if (right) { + from = length - 1; + to = -1; + increment = -1; + + } else { + from = 0; + to = length; + increment = 1; + } + + if (nargs > 2) { + accumulator = *njs_argument(args, 2); + + } else { + njs_set_number(&accumulator, njs_typed_array_get(array, from)); + from += increment; + } + + for (i = from; i != to; i += increment) { + njs_set_undefined(&arguments[0]); + arguments[1] = accumulator; + njs_set_number(&arguments[2], njs_typed_array_get(array, i)); + njs_set_number(&arguments[3], i); + njs_set_typed_array(&arguments[4], array); + + ret = njs_function_apply(vm, function, arguments, 5, &accumulator); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + vm->retval = accumulator; + + return NJS_OK; +} + + +static njs_int_t +njs_typed_array_prototype_reverse(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused) +{ + double *f64; + uint8_t *u8; + int64_t i, length; + uint16_t *u16; + uint32_t *u32; + njs_value_t *this; + njs_typed_array_t *array; + njs_array_buffer_t *buffer; + + 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); + length = njs_typed_array_length(array); + + buffer = array->buffer; + + switch (array->type) { + case NJS_OBJ_TYPE_UINT8_ARRAY: + case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY: + case NJS_OBJ_TYPE_INT8_ARRAY: + u8 = &buffer->u.u8[array->offset]; + + for (i = 0; i < length / 2; i++) { + njs_swap_u8(&u8[i], &u8[length - i - 1], 0); + } + + break; + + case NJS_OBJ_TYPE_INT16_ARRAY: + case NJS_OBJ_TYPE_UINT16_ARRAY: + u16 = &buffer->u.u16[array->offset]; + + for (i = 0; i < length / 2; i++) { + njs_swap_u16(&u16[i], &u16[length - i - 1], 0); + } + + break; + + case NJS_OBJ_TYPE_INT32_ARRAY: + case NJS_OBJ_TYPE_UINT32_ARRAY: + case NJS_OBJ_TYPE_FLOAT32_ARRAY: + u32 = &buffer->u.u32[array->offset]; + + for (i = 0; i < length / 2; i++) { + njs_swap_u32(&u32[i], &u32[length - i - 1], 0); + } + + break; + + default: + + /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ + + f64 = &buffer->u.f64[array->offset]; + + for (i = 0; i < length / 2; i++) { + njs_swap_u64(&f64[i], &f64[length - i - 1], 0); + } + } + + njs_set_typed_array(&vm->retval, array); + + return NJS_OK; +} + + static int njs_typed_array_compare_i8(const void *a, const void *b, void *c) { @@ -1367,48 +1930,69 @@ static const njs_object_prop_t njs_typed_array_prototype_properties[] = { .type = NJS_PROPERTY, - .name = njs_string("set"), - .value = njs_native_function(njs_typed_array_prototype_set, 2), + .name = njs_string("copyWithin"), + .value = njs_native_function(njs_typed_array_prototype_copy_within, 2), .writable = 1, .configurable = 1, }, { .type = NJS_PROPERTY, - .name = njs_string("slice"), - .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 1), + .name = njs_string("every"), + .value = njs_native_function2(njs_typed_array_prototype_iterator, 1, + NJS_ARRAY_EVERY), .writable = 1, .configurable = 1, }, { .type = NJS_PROPERTY, - .name = njs_string("subarray"), - .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 0), + .name = njs_string("filter"), + .value = njs_native_function2(njs_typed_array_prototype_iterator, 1, + NJS_ARRAY_FILTER), .writable = 1, .configurable = 1, }, { .type = NJS_PROPERTY, - .name = njs_string("sort"), - .value = njs_native_function(njs_typed_array_prototype_sort, 1), + .name = njs_string("find"), + .value = njs_native_function2(njs_typed_array_prototype_iterator, 1, + NJS_ARRAY_FIND), .writable = 1, .configurable = 1, }, { .type = NJS_PROPERTY, - .name = njs_string("copyWithin"), - .value = njs_native_function(njs_typed_array_prototype_copy_within, 2), + .name = njs_string("findIndex"), + .value = njs_native_function2(njs_typed_array_prototype_iterator, 1, + NJS_ARRAY_FIND_INDEX), .writable = 1, .configurable = 1, }, { .type = NJS_PROPERTY, - .name = njs_string("fill"), - .value = njs_native_function(njs_typed_array_prototype_fill, 1), + .name = njs_string("forEach"), + .value = njs_native_function2(njs_typed_array_prototype_iterator, 1, + NJS_ARRAY_FOR_EACH), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("includes"), + .value = njs_native_function2(njs_typed_array_prototype_index_of, 1, 1), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("indexOf"), + .value = njs_native_function2(njs_typed_array_prototype_index_of, 1, 0), .writable = 1, .configurable = 1, }, @@ -1421,6 +2005,96 @@ static const njs_object_prop_t njs_typed_array_prototype_properties[] = .configurable = 1, }, + { + .type = NJS_PROPERTY, + .name = njs_string("fill"), + .value = njs_native_function(njs_typed_array_prototype_fill, 1), + .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, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("map"), + .value = njs_native_function2(njs_typed_array_prototype_iterator, 1, + NJS_ARRAY_MAP), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("reduce"), + .value = njs_native_function2(njs_typed_array_prototype_reduce, 1, 0), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("reduceRight"), + .value = njs_native_function2(njs_typed_array_prototype_reduce, 1, 1), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("reverse"), + .value = njs_native_function(njs_typed_array_prototype_reverse, 0), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("set"), + .value = njs_native_function(njs_typed_array_prototype_set, 2), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("slice"), + .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 1), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("some"), + .value = njs_native_function2(njs_typed_array_prototype_iterator, 1, + NJS_ARRAY_SOME), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("sort"), + .value = njs_native_function(njs_typed_array_prototype_sort, 1), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("subarray"), + .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 0), + .writable = 1, + .configurable = 1, + }, + { .type = NJS_PROPERTY, .name = njs_string("toString"), diff --git a/src/njs_utils.c b/src/njs_utils.c index c58cf342..2a921ff6 100644 --- a/src/njs_utils.c +++ b/src/njs_utils.c @@ -11,62 +11,6 @@ typedef void (*njs_swap_t) (void *a, void *b, size_t size); -njs_inline void -njs_swap_u8(void *a, void *b, size_t size) -{ - uint8_t u, *au, *bu; - - au = (uint8_t *) a; - bu = (uint8_t *) b; - - u = au[0]; - au[0] = bu[0]; - bu[0] = u; -} - - -njs_inline void -njs_swap_u16(void *a, void *b, size_t size) -{ - uint16_t u, *au, *bu; - - au = (uint16_t *) a; - bu = (uint16_t *) b; - - u = au[0]; - au[0] = bu[0]; - bu[0] = u; -} - - -njs_inline void -njs_swap_u32(void *a, void *b, size_t size) -{ - uint32_t u, *au, *bu; - - au = (uint32_t *) a; - bu = (uint32_t *) b; - - u = au[0]; - au[0] = bu[0]; - bu[0] = u; -} - - -njs_inline void -njs_swap_u64(void *a, void *b, size_t size) -{ - uint64_t u, *au, *bu; - - au = (uint64_t *) a; - bu = (uint64_t *) b; - - u = au[0]; - au[0] = bu[0]; - bu[0] = u; -} - - njs_inline void njs_swap_u128(void *a, void *b, size_t size) { diff --git a/src/njs_utils.h b/src/njs_utils.h index 30207887..1ba7462a 100644 --- a/src/njs_utils.h +++ b/src/njs_utils.h @@ -15,4 +15,61 @@ void njs_qsort(void *base, size_t n, size_t size, njs_sort_cmp_t cmp, const char *njs_errno_string(int errnum); + +njs_inline void +njs_swap_u8(void *a, void *b, size_t size) +{ + uint8_t u, *au, *bu; + + au = (uint8_t *) a; + bu = (uint8_t *) b; + + u = au[0]; + au[0] = bu[0]; + bu[0] = u; +} + + +njs_inline void +njs_swap_u16(void *a, void *b, size_t size) +{ + uint16_t u, *au, *bu; + + au = (uint16_t *) a; + bu = (uint16_t *) b; + + u = au[0]; + au[0] = bu[0]; + bu[0] = u; +} + + +njs_inline void +njs_swap_u32(void *a, void *b, size_t size) +{ + uint32_t u, *au, *bu; + + au = (uint32_t *) a; + bu = (uint32_t *) b; + + u = au[0]; + au[0] = bu[0]; + bu[0] = u; +} + + +njs_inline void +njs_swap_u64(void *a, void *b, size_t size) +{ + uint64_t u, *au, *bu; + + au = (uint64_t *) a; + bu = (uint64_t *) b; + + u = au[0]; + au[0] = bu[0]; + bu[0] = u; +} + + #endif /* _NJS_UTILS_H_INCLUDED_ */ diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 3f7f0412..f8ed01a9 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -5895,6 +5895,312 @@ static njs_unit_test_t njs_test[] = " return a.toString() === '4,5,3,4,5'})"), njs_str("true") }, + { njs_str("Uint8Array.prototype.every.call(1)"), + njs_str("TypeError: this is not a typed array") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([1,2,3])).every(e=>e>0) === true})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([1,2,3])).every(function(e) {" + " if (this != undefined) {throw 'Oops';}" + " return e > 0}) === true})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([1,2,3])).every(function(e) {" + " if (this != 'QQ') {throw 'Oops';}" + " return e > 0}, 'QQ') === true})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([1,2,3])).every(e=>e>1) === false})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,1,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.every(e=>e<4)})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var collect = []; (new v([42,43])).forEach(e=>collect.push(e)); " + " return collect.join('|') === '42|43'})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([7,10,3,8,5])).filter(q=>q%2).join('|') === '7|3|5'})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,7,10,3,8,5,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 5);" + " return a.filter(q=>q%2).join('|') === '7|3|5'})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,1,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.find(e=>e>2) === 3})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,1,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.find(e=>e===255) === undefined})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,1,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.findIndex(e=>e>2) === 2})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,1,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.findIndex(e=>e===255) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([1,2,3])).some(e=>e==2)})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,1,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.some(e=>e==255)})"), + njs_str("false") }, + + { njs_str("Uint8Array.prototype.includes.call(1)"), + njs_str("TypeError: this is not a typed array") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v()).includes(0, {valueOf(){throw 'Oops'}}) === false})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([0,1,2,3])).includes(2) === true})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([0,1,2,3])).includes(2,3) === false})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v(5);" + " return a.includes(0, 4) === true " + " && a.includes(0, 5) === false;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([0,1,2,3])).includes(-0) === true})"), + njs_str("true") }, + + { njs_str(NJS_FLOAT_TYPED_ARRAY_LIST + ".every(v=>{return (new v([42, 43, NaN, 41])).includes(NaN) === true})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,0,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.includes(255) === false})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v()).indexOf(0, {valueOf(){throw 'Oops'}}) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1])).indexOf(2) === 1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1])).indexOf(2,2) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1])).indexOf(2,Infinity) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1])).indexOf(2,-Infinity) === 1})"), + njs_str("true") }, + + { njs_str(NJS_FLOAT_TYPED_ARRAY_LIST + ".every(v=>{return (new v([42, 43, NaN, 41])).indexOf(NaN) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1])).indexOf(257) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1])).indexOf(2.00001) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1,0])).indexOf(-0) === 3})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v(5);" + " return a.indexOf(0, 4) === 4" + " && a.indexOf(0, 5) === -1;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,0,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.indexOf(255) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1,2])).lastIndexOf(2) === 3})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1,2])).lastIndexOf(4) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([42, 43])).lastIndexOf(42,0) === 0})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([42, 43, 43, 41])).lastIndexOf(43,Infinity) === 2})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([42, 43, 43, 41])).lastIndexOf(43,-Infinity) === -1})"), + njs_str("true") }, + + { njs_str(NJS_FLOAT_TYPED_ARRAY_LIST + ".every(v=>{return (new v([42, 43, NaN, 41])).lastIndexOf(NaN) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,0,2,3,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.lastIndexOf(255) === -1})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{return (new v([3,2,1])).map(q=>2*q).join('|') === '6|4|2'})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var orig = new v([255,255,6,4,2,255]);" + " var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);" + " return a.map(q=>q/2).join('|') === '3|2|1'})"), + njs_str("true") }, + + { njs_str("Uint8Array.prototype.reduce.call(1)"), + njs_str("TypeError: this is not a typed array") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ try { (new v([])).reduce((p, q) => p + q) } " + " catch (e) { return e.name == 'TypeError'} })"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([])).reduce((p, q) => p + q, 10) == 10})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([7])).reduce((p, q) => p + q) == 7})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([7])).reduce((p, q) => p + q, 10) == 17})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3])).reduce((p, q) => p + q) == 6})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3])).reduce((p, q) => p + q, 10) == 16})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3])).reduce((p, q) => p + q, '') == '123'})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([3,2,1])).reduce((p, q, i) => { " + " if (q + i != 3) {throw 'Oops'}; " + " return p + q;}) == 6})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ var a = new v([3,2,1]); " + " return a.reduce((p, q, _, o) => { " + " if (a != o) {throw 'Oops'}; " + " return p + q;}) == 6})"), + njs_str("true") }, + + { njs_str("var a = [3,2,1]; a.reduce((p, v, _, o) => { if (a != o) {throw 'Oops'};return p + v})"), + njs_str("6") }, + + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ try { (new v([])).reduceRight((p, q) => p + q) } " + " catch (e) { return e.name == 'TypeError'} })"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([])).reduceRight((p, q) => p + q, 10) == 10})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([7])).reduceRight((p, q) => p + q) == 7})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([7])).reduceRight((p, q) => p + q, 10) == 17})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3])).reduceRight((p, q) => p + q) == 6})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3])).reduceRight((p, q) => p + q, 10) == 16})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3])).reduceRight((p, q) => p + q, '') == '321'})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([3,2,1])).reduceRight((p, q, i) => { " + " if (q + i != 3) {throw 'Oops'}; " + " return p + q;}) == 6})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ var a = new v([3,2,1]); " + " return a.reduceRight((p, q, _, o) => { " + " if (a != o) {throw 'Oops'}; " + " return p + q;}) == 6})"), + njs_str("true") }, + + { njs_str("var a = [3,2,1]; a.reduceRight((p, v, _, o) => { if (a != o) {throw 'Oops'};return p + v})"), + njs_str("6") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3])).reverse().join('|') == '3|2|1'})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{ return (new v([1,2,3,4])).reverse().join('|') == '4|3|2|1'})"), + njs_str("true") }, + + { njs_str("Uint8Array.prototype.sort.call(1)"), + njs_str("TypeError: this is not a typed array") }, + { njs_str(NJS_TYPED_ARRAY_LIST ".every(v=>{var a = new v([]); a.sort(); " " return a.toString() === ''})"), @@ -6164,45 +6470,42 @@ static njs_unit_test_t njs_test[] = { njs_str("Array.prototype.map.call({0:9, length:2**16}, val=>val<10).length"), njs_str("65536") }, - { njs_str("var a = [];" - "a.reduce(function(p, v, i, a) { return p + v })"), + { njs_str("[].reduce((p, v) => p + v)"), njs_str("TypeError: Reduce of empty object with no initial value") }, - { njs_str("var a = [];" - "a.reduce(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[].reduce((p, v) => p + v, 10)"), njs_str("10") }, - { njs_str("var a = [,,];" - "a.reduce(function(p, v, i, a) { return p + v })"), + { njs_str("[,,].reduce((p, v) => p + v)"), njs_str("TypeError: Reduce of empty object with no initial value") }, - { njs_str("var a = [,,];" - "a.reduce(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[,,].reduce((p, v) => p + v, 10)"), njs_str("10") }, - { njs_str("var a = [1];" - "a.reduce(function(p, v, i, a) { return p + v })"), + { njs_str("[1].reduce((p, v) => p + v)"), njs_str("1") }, - { njs_str("var a = [1];" - "a.reduce(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[1].reduce((p, v) => p + v, 10)"), njs_str("11") }, - { njs_str("var a = [1,2,3];" - "a.reduce(function(p, v, i, a) { return p + v })"), + { njs_str("[1,2,3].reduce((p, v) => p + v)"), njs_str("6") }, - { njs_str("var a = [1,2,3];" - "a.reduce(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[1,2,3].reduce((p, v) => p + v, 10)"), njs_str("16") }, - { njs_str("[[0, 1], [2, 3], [4, 5]].reduce(function(a, b)" - " { return a.concat(b) }, [])"), + { njs_str("[3,2,1].reduce((p, v, i) => { if (v + i != 3) {throw 'Oops'};return p + v})"), + njs_str("6") }, + + { njs_str("var a = [3,2,1]; a.reduce((p, v, _, o) => { if (a != o) {throw 'Oops'};return p + v})"), + njs_str("6") }, + + { njs_str("[[0, 1], [2, 3], [4, 5]].reduce((a, b) => a.concat(b), [])"), njs_str("0,1,2,3,4,5") }, { njs_str("var o = {0: 'a', 1: 'b', 2: 'c', 'length': { valueOf() { return 3 }}};" - "var reducer = (a, b) => a + b;" - "var a = Array.prototype.reduce.call(o, reducer); a"), + "var reducer = (a, b) => a + b;" + "var a = Array.prototype.reduce.call(o, reducer); a"), njs_str("abc") }, { njs_str("function reducer(a, b, i, arr) {" @@ -6224,46 +6527,38 @@ static njs_unit_test_t njs_test[] = "var r = Array.prototype.reduce.call(o, (a, b) => a + b); r"), njs_str("abcd") }, - { njs_str("var a = [];" - "a.reduceRight(function(p, v, i, a) { return p + v })"), + { njs_str("[].reduceRight((p, v) => p + v)"), njs_str("TypeError: Reduce of empty object with no initial value") }, - { njs_str("var a = [];" - "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[].reduceRight((p, v) => p + v, 10)"), njs_str("10") }, - { njs_str("var a = [,,];" - "a.reduceRight(function(p, v, i, a) { return p + v })"), + { njs_str("[,,].reduceRight((p, v) => p + v)"), njs_str("TypeError: Reduce of empty object with no initial value") }, - { njs_str("var a = [,,];" - "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[,,].reduceRight((p, v) => p + v, 10)"), njs_str("10") }, - { njs_str("var a = [1];" - "a.reduceRight(function(p, v, i, a) { return p + v })"), + { njs_str("[1].reduceRight((p, v) => p + v)"), njs_str("1") }, - { njs_str("var a = [1];" - "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[1].reduceRight((p, v) => p + v, 10)"), njs_str("11") }, - { njs_str("var a = [1,2,3];" - "a.reduceRight(function(p, v, i, a) { return p + v })"), + { njs_str("[1,2,3].reduceRight((p, v) => p + v)"), njs_str("6") }, - { njs_str("var a = [1,2,3];" - "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"), + { njs_str("[1,2,3].reduceRight((p, v) => p + v, 10)"), njs_str("16") }, + { njs_str("[3,2,1].reduceRight((p, v, i) => { if (v + i != 3) {throw 'Oops'};return p + v})"), + njs_str("6") }, + { njs_str("var a = [1,2,3];" - "a.reduceRight(function(p, v, i, a)" - " { a.shift(); return p + v })"), + "a.reduceRight(function(p, v, _, a) { a.shift(); return p + v })"), njs_str("7") }, - { njs_str("var a = [1,2,3];" - "a.reduceRight(function(p, v, i, a)" - " { a.shift(); return p + v }, 10)"), + "a.reduceRight(function(p, v, _, a) { a.shift(); return p + v }, 10)"), njs_str("19") }, { njs_str("var o = {0: 'a', 1: 'b', 2: 'c'};" -- 2.47.3