njs_array_t *array;
- uint32_t from;
- uint32_t to;
+ int64_t from;
+ int64_t to;
} njs_array_iterator_args_t;
typedef njs_int_t (*njs_array_iterator_handler_t)(njs_vm_t *vm,
- njs_array_iterator_args_t *args, njs_value_t *entry, uint32_t n);
+ njs_array_iterator_args_t *args, njs_value_t *entry, uint64_t n);
static njs_int_t njs_array_prototype_slice_copy(njs_vm_t *vm,
length = array->length;
for (i = 0; i < length; i++) {
- njs_uint32_to_string(&index, i);
-
if (njs_is_valid(&array->start[i])) {
+ njs_uint32_to_string(&index, i);
prop = njs_object_property_add(vm, &value, &index, 0);
if (njs_slow_path(prop == NULL)) {
return NJS_ERROR;
njs_object_prop_t *prev, njs_value_t *setval)
{
double num, idx;
- uint32_t i, length, prev_length;
+ uint32_t i, length;
+ uint64_t prev_length;
njs_int_t ret;
njs_array_t *array, *keys;
return ret;
}
- length = njs_number_to_length(num);
+ length = (uint32_t) njs_number_to_length(num);
if ((double) length != num) {
njs_range_error(vm, "Invalid array length");
return NJS_ERROR;
size += size / 2;
}
- if (njs_slow_path(size > NJS_ARRAY_MAX_LENGTH)) {
+ if (njs_slow_path(size > (UINT32_MAX / sizeof(njs_value_t)))) {
goto memory_error;
}
if (size == 1 && njs_is_number(&args[0])) {
num = njs_number(&args[0]);
- size = (uint32_t) num;
+ size = (uint32_t) njs_number_to_length(num);
if ((double) size != num) {
njs_range_error(vm, "Invalid array length");
return ret;
}
- length = njs_number_to_length(num);
+ length = (uint32_t) njs_number_to_length(num);
if ((double) length != num) {
njs_range_error(vm, "Invalid array length");
return NJS_ERROR;
njs_index_t unused)
{
int64_t start, end, length;
- uint32_t object_length;
+ uint64_t object_length;
njs_int_t ret;
njs_value_t *this;
uint32_t n;
njs_int_t ret;
njs_array_t *array, *keys;
- njs_value_t *value, index, retval, array_value;
+ njs_value_t *value, retval, self;
const u_char *src, *end;
njs_slice_prop_t string_slice;
njs_string_prop_t string;
/* src value may be in Array.prototype object. */
- njs_uint32_to_string(&index, start++);
-
value = &array->start[n++];
- ret = njs_value_property(vm, this, &index, value);
+ ret = njs_value_property_i64(vm, this, start++, value);
if (njs_slow_path(ret == NJS_ERROR)) {
return NJS_ERROR;
}
} else if (njs_is_object(this)) {
do {
- njs_uint32_to_string(&index, start++);
-
value = &array->start[n++];
- ret = njs_value_property(vm, this, &index, value);
+ ret = njs_value_property_i64(vm, this, start++, value);
if (ret != NJS_OK) {
njs_set_invalid(value);
goto done;
}
- njs_set_array(&array_value, array);
+ njs_set_array(&self, array);
if (njs_fast_object(length)) {
do {
- njs_uint32_to_string(&index, start++);
-
- ret = njs_value_property(vm, this, &index, &retval);
+ ret = njs_value_property_i64(vm, this, start++, &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return NJS_ERROR;
}
if (ret == NJS_OK) {
- ret = njs_value_property_set(vm, &array_value, &index, &retval);
+ ret = njs_value_property_i64_set(vm, &self, start, &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
goto done;
}
- ret = njs_value_property_set(vm, &array_value, &keys->start[n],
- &retval);
+ ret = njs_value_property_set(vm, &self, &keys->start[n], &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
goto done;
}
njs_array_prototype_push(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- uint32_t length;
+ uint64_t length;
njs_int_t ret;
njs_uint_t i;
njs_array_t *array;
- njs_value_t *this, index;
+ njs_value_t *this;
length = 0;
this = njs_argument(args, 0);
return ret;
}
- for (i = 1; i < nargs; i++) {
- njs_uint32_to_string(&index, length++);
+ if (njs_slow_path((length + nargs - 1) > NJS_MAX_LENGTH)) {
+ njs_type_error(vm, "Invalid length");
+ return NJS_ERROR;
+ }
- ret = njs_value_property_set(vm, this, &index, &args[i]);
+ for (i = 1; i < nargs; i++) {
+ ret = njs_value_property_i64_set(vm, this, length++, &args[i]);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
njs_array_prototype_pop(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- uint32_t length;
+ uint64_t length;
njs_int_t ret;
njs_array_t *array;
- njs_value_t *this, *entry, index;
+ njs_value_t *this, *entry;
this = njs_argument(args, 0);
if (njs_is_valid(entry)) {
vm->retval = *entry;
+
+ } else {
+ /* src value may be in Array.prototype object. */
+
+ ret = njs_value_property_i64(vm, this, array->length,
+ &vm->retval);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
}
}
return ret;
}
- if (length != 0) {
- njs_uint32_to_string(&index, --length);
+ if (length == 0) {
+ njs_set_undefined(&vm->retval);
+ goto done;
+ }
- ret = njs_value_property_delete(vm, this, &index, &vm->retval);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
- }
+ ret = njs_value_property_i64(vm, this, --length, &vm->retval);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ ret = njs_value_property_i64_delete(vm, this, length, NULL);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
}
+done:
+
ret = njs_object_length_set(vm, this, length);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
njs_index_t unused)
{
double idx;
- uint32_t from, to, length;
+ uint64_t from, to, length;
njs_int_t ret;
njs_uint_t n;
njs_array_t *array, *keys;
- njs_value_t *this, entry, index;
+ njs_value_t *this, entry;
this = njs_argument(args, 0);
length = 0;
return ret;
}
- if (njs_is_fast_array(this)) {
+ if (njs_fast_path(njs_is_fast_array(this))) {
array = njs_array(this);
- if (array->length > (UINT32_MAX - n)) {
- njs_type_error(vm, "Invalid length");
- return NJS_ERROR;
- }
-
if (n != 0) {
ret = njs_array_expand(vm, array, n, 0);
if (njs_slow_path(ret != NJS_OK)) {
goto done;
}
- if (length > (UINT32_MAX - n)) {
+ if (njs_slow_path((length + n) > NJS_MAX_LENGTH)) {
njs_type_error(vm, "Invalid length");
return NJS_ERROR;
}
}
if (ret == NJS_OK) {
- idx = njs_string_to_index(&keys->start[from]);
-
- njs_uint32_to_string(&index, (uint32_t) idx + nargs - 1);
+ idx = njs_string_to_index(&keys->start[from]) + n;
- ret = njs_value_property_set(vm, this, &index, &entry);
+ ret = njs_value_property_i64_set(vm, this, idx, &entry);
if (njs_slow_path(ret == NJS_ERROR)) {
njs_array_destroy(vm, keys);
return ret;
njs_array_destroy(vm, keys);
- length += nargs - 1;
+ length += n;
goto copy;
}
to = length;
while (from > 0) {
- njs_uint32_to_string(&index, --from);
-
- ret = njs_value_property_delete(vm, this, &index, &entry);
+ ret = njs_value_property_i64_delete(vm, this, --from, &entry);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
to--;
if (ret == NJS_OK) {
- njs_uint32_to_string(&index, to);
-
- ret = njs_value_property_set(vm, this, &index, &entry);
+ ret = njs_value_property_i64_set(vm, this, to, &entry);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
copy:
for (n = 1; n < nargs; n++) {
- njs_uint32_to_string(&index, n - 1);
-
- ret = njs_value_property_set(vm, this, &index, &args[n]);
+ ret = njs_value_property_i64_set(vm, this, n - 1, &args[n]);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
njs_array_prototype_shift(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- uint32_t i, length;
+ uint64_t i, length;
njs_int_t ret;
njs_array_t *array;
- njs_value_t *this, *item, entry, index;
+ njs_value_t *this, *item, entry;
this = njs_argument(args, 0);
length = 0;
if (array->length != 0) {
array->length--;
-
item = &array->start[0];
- array->start++;
if (njs_is_valid(item)) {
vm->retval = *item;
+
+ } else {
+ /* src value may be in Array.prototype object. */
+
+ ret = njs_value_property_i64(vm, this, 0, &vm->retval);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
}
+
+ array->start++;
}
return NJS_OK;
goto done;
}
- njs_uint32_to_string(&index, 0);
-
- ret = njs_value_property_delete(vm, this, &index, &vm->retval);
+ ret = njs_value_property_i64_delete(vm, this, 0, &vm->retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
for (i = 1; i < length; i++) {
- njs_uint32_to_string(&index, i);
-
- ret = njs_value_property_delete(vm, this, &index, &entry);
+ ret = njs_value_property_i64_delete(vm, this, i, &entry);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
if (ret == NJS_OK) {
- njs_uint32_to_string(&index, i - 1);
-
- ret = njs_value_property_set(vm, this, &index, &entry);
+ ret = njs_value_property_i64_set(vm, this, i - 1, &entry);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
njs_array_prototype_reverse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- uint32_t length;
+ uint64_t length;
njs_int_t ret;
njs_uint_t i, n;
njs_value_t value, *this;
njs_index_t unused)
{
u_char *p, *last;
- size_t size;
- ssize_t length;
- uint32_t len;
+ int64_t length;
+ uint64_t i, len, size;
njs_int_t ret;
njs_chb_t chain;
njs_utf8_t utf8;
- njs_uint_t i;
njs_array_t *array;
- njs_value_t *value, *this, index, entry;
+ njs_value_t *value, *this, entry;
njs_string_prop_t separator, string;
this = njs_argument(args, 0);
njs_chb_init(&chain, vm->mem_pool);
for (i = 0; i < len; i++) {
- if (njs_fast_path(array != NULL)) {
+ if (njs_fast_path(njs_object(this)->fast_array
+ && njs_is_valid(&array->start[i])))
+ {
value = &array->start[i];
} else {
- njs_uint32_to_string(&index, i);
-
- ret = njs_value_property(vm, this, &index, &entry);
+ ret = njs_value_property_i64(vm, this, i, &entry);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
length += separator.length;
njs_chb_append(&chain, separator.start, separator.size);
+
+ if (njs_slow_path(length > NJS_STRING_MAX_LENGTH)) {
+ njs_range_error(vm, "invalid string length");
+ return NJS_ERROR;
+ }
}
njs_chb_drop(&chain, separator.size);
njs_inline njs_int_t
njs_array_object_handler(njs_vm_t *vm, njs_array_iterator_handler_t handler,
- njs_array_iterator_args_t *args, njs_value_t *key, uint32_t i)
+ njs_array_iterator_args_t *args, njs_value_t *key, uint64_t i)
{
njs_int_t ret;
njs_value_t prop, *entry;
- ret = njs_value_property(vm, args->value, key, &prop);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
+ if (key != NULL) {
+ ret = njs_value_property(vm, args->value, key, &prop);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ } else {
+ ret = njs_value_property_i64(vm, args->value, i, &prop);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
}
entry = (ret == NJS_OK) ? &prop : njs_value_arg(&njs_value_invalid);
njs_array_iterator_handler_t handler)
{
double idx;
- uint32_t length, i, from, to;
+ uint64_t length, i, from, to;
njs_int_t ret;
- njs_array_t *keys;
- njs_value_t *value, character, index, string_obj;
+ njs_array_t *array, *keys;
+ njs_value_t *value, *entry, prop, character, string_obj;
njs_object_t *object;
const u_char *p, *end, *pos;
njs_string_prop_t string_prop;
to = args->to;
if (njs_is_array(value)) {
- if (njs_slow_path(!njs_is_fast_array(value))) {
- goto process_object;
- }
+ array = njs_array(value);
- for (i = from; i < to; i++) {
- if (i < njs_array_len(value)) {
- ret = handler(vm, args, &njs_array_start(value)[i], i);
+ for (; from < to; from++) {
+ if (njs_slow_path(!array->object.fast_array)) {
+ goto process_object;
+ }
+
+ if (njs_fast_path(from < array->length
+ && njs_is_valid(&array->start[from])))
+ {
+ ret = handler(vm, args, &array->start[from], from);
} else {
- ret = handler(vm, args, njs_value_arg(&njs_value_invalid), i);
+ entry = njs_value_arg(&njs_value_invalid);
+ ret = njs_value_property_i64(vm, value, from, &prop);
+ if (njs_slow_path(ret != NJS_DECLINED)) {
+ if (ret == NJS_ERROR) {
+ return NJS_ERROR;
+ }
+
+ entry = ∝
+ }
+
+ ret = handler(vm, args, entry, from);
}
if (njs_slow_path(ret != NJS_OK)) {
value = njs_object_value(value);
}
- length = (uint32_t) njs_string_prop(&string_prop, value);
+ length = njs_string_prop(&string_prop, value);
p = string_prop.start;
end = p + string_prop.size;
}
for (i = from; i < to; i++) {
- njs_uint32_to_string(&index, i);
-
- ret = njs_array_object_handler(vm, handler, args, &index, i);
+ ret = njs_array_object_handler(vm, handler, args, NULL, i);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
njs_array_iterator_handler_t handler)
{
double idx;
- uint32_t i, from, to, length;
+ uint64_t i, from, to, length;
njs_int_t ret;
- njs_array_t *keys;
- njs_value_t *entry, *value, character, index, string_obj;
+ njs_array_t *array, *keys;
+ njs_value_t *entry, *value, prop, character, string_obj;
njs_object_t *object;
const u_char *p, *end, *pos;
njs_string_prop_t string_prop;
to = args->to;
if (njs_is_array(value)) {
- if (njs_slow_path(!njs_is_fast_array(value))) {
- goto process_object;
- }
+ array = njs_array(value);
- i = from + 1;
+ from += 1;
- while (i-- > to) {
- entry = &njs_array_start(value)[i];
+ while (from-- > to) {
+ if (njs_slow_path(!array->object.fast_array)) {
+ goto process_object;
+ }
+
+ if (njs_fast_path(from < array->length
+ && njs_is_valid(&array->start[from])))
+ {
+ ret = handler(vm, args, &array->start[from], from);
+
+ } else {
+ entry = njs_value_arg(&njs_value_invalid);
+ ret = njs_value_property_i64(vm, value, from, &prop);
+ if (njs_slow_path(ret != NJS_DECLINED)) {
+ if (ret == NJS_ERROR) {
+ return NJS_ERROR;
+ }
+
+ entry = ∝
+ }
+
+ ret = handler(vm, args, entry, from);
+ }
- ret = handler(vm, args, entry, i);
if (njs_slow_path(ret != NJS_OK)) {
if (ret > 0) {
return NJS_DECLINED;
value = njs_object_value(value);
}
- length = (uint32_t) njs_string_prop(&string_prop, value);
+ length = njs_string_prop(&string_prop, value);
end = string_prop.start + string_prop.size;
if (length == string_prop.size) {
i = from + 1;
while (i-- > to) {
- njs_uint32_to_string(&index, i);
-
- ret = njs_array_object_handler(vm, handler, args, &index, i);
+ ret = njs_array_object_handler(vm, handler, args, NULL, i);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
njs_index_t unused)
{
double idx;
- uint32_t len;
- uint64_t length;
+ uint64_t i, k, len, length;
njs_int_t ret;
- njs_uint_t i, k;
- njs_value_t this, index, retval, *value, *e;
+ njs_value_t this, retval, *value, *e;
njs_array_t *array, *keys;
ret = njs_value_to_object(vm, &args[0]);
return ret;
}
- if (njs_slow_path((length + len) >= NJS_ARRAY_MAX_LENGTH53)) {
+ if (njs_slow_path((length + len) > NJS_MAX_LENGTH)) {
njs_type_error(vm, "Invalid length");
return NJS_ERROR;
}
value = &njs_array_start(e)[k];
if (njs_slow_path(!njs_is_valid(value))) {
- njs_uint32_to_string(&index, k);
- ret = njs_value_property(vm, e, &index,
- &retval);
+ ret = njs_value_property_i64(vm, e, k, &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
if (njs_fast_object(len)) {
for (k = 0; k < len; k++, length++) {
- njs_uint32_to_string(&index, k);
-
- ret = njs_value_property(vm, e, &index, &retval);
+ ret = njs_value_property_i64(vm, e, k, &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
continue;
}
- njs_uint32_to_string(&index, length);
-
- ret = njs_value_property_set(vm, &this, &index, &retval);
+ ret = njs_value_property_i64_set(vm, &this, length,
+ &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
return ret;
}
- idx = njs_string_to_index(&keys->start[k]);
+ idx = njs_string_to_index(&keys->start[k]) + length;
if (ret == NJS_OK) {
- njs_uint32_to_string(&index, length + idx);
-
- ret = njs_value_property_set(vm, &this, &index, &retval);
+ ret = njs_value_property_i64_set(vm, &this, idx, &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
njs_array_destroy(vm, keys);
return ret;
continue;
}
- if (njs_slow_path((length + len) >= NJS_ARRAY_MAX_LENGTH53)) {
+ if (njs_slow_path((length + len) >= NJS_MAX_LENGTH)) {
njs_type_error(vm, "Invalid length");
return NJS_ERROR;
}
}
} else {
- njs_uint32_to_string(&index, length);
-
- ret = njs_value_property_set(vm, &this, &index, e);
+ ret = njs_value_property_i64_set(vm, &this, length, e);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
static njs_int_t
njs_array_handler_index_of(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
if (njs_values_strict_equal(args->argument, entry)) {
njs_set_number(&vm->retval, n);
njs_index_t unused)
{
int64_t from;
- uint32_t length;
+ uint64_t length;
njs_int_t ret;
njs_array_iterator_args_t iargs;
}
}
- iargs.from = (uint32_t) from;
+ iargs.from = from;
iargs.to = length;
ret = njs_array_iterator(vm, &iargs, njs_array_handler_index_of);
- if (njs_fast_path(ret == NJS_DECLINED)) {
- return NJS_OK;
+ if (njs_fast_path(ret != NJS_OK)) {
+ return (ret == NJS_DECLINED) ? NJS_OK : NJS_ERROR;
}
not_found:
njs_uint_t nargs, njs_index_t unused)
{
int64_t from;
- uint32_t length;
+ uint64_t length;
njs_int_t ret;
njs_array_iterator_args_t iargs;
}
if (from >= 0) {
- from = njs_min(from, length - 1);
+ from = njs_min((uint64_t) from, length - 1);
} else if (from < 0) {
from += length;
iargs.to = 0;
ret = njs_array_reverse_iterator(vm, &iargs, njs_array_handler_index_of);
- if (njs_fast_path(ret == NJS_DECLINED)) {
- return NJS_OK;
+ if (njs_fast_path(ret != NJS_OK)) {
+ return (ret == NJS_DECLINED) ? NJS_OK : NJS_ERROR;
}
not_found:
static njs_int_t
njs_array_handler_includes(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
if (!njs_is_valid(entry)) {
entry = njs_value_arg(&njs_value_undefined);
njs_index_t unused)
{
int64_t from;
- uint32_t length;
+ uint64_t length;
njs_int_t ret;
njs_array_iterator_args_t iargs;
}
}
- iargs.from = (uint32_t) from;
+ iargs.from = from;
iargs.to = length;
ret = njs_array_iterator(vm, &iargs, njs_array_handler_includes);
- if (njs_fast_path(ret == NJS_DECLINED)) {
- return NJS_OK;
+ if (njs_fast_path(ret != NJS_OK)) {
+ return (ret == NJS_DECLINED) ? NJS_OK : NJS_ERROR;
}
not_found:
njs_array_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- int64_t start, end;
- uint32_t length;
- njs_int_t i, ret;
+ int64_t i, length, start, end;
+ njs_int_t ret;
njs_array_t *array;
- njs_value_t name, *this, *value;
+ njs_value_t *this, *value;
this = njs_argument(args, 0);
length = array->length;
} else {
- ret = njs_object_length(vm, this, &length);
+ ret = njs_object_length(vm, this, (uint64_t *) &length);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
value = njs_arg(args, nargs, 1);
while (start < end) {
- njs_uint32_to_string(&name, start++);
-
- ret = njs_value_property_set(vm, this, &name, value);
+ ret = njs_value_property_i64_set(vm, this, start++, value);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
return ret;
}
- ret = njs_value_length(vm, iargs->value, &iargs->to);
+ ret = njs_value_length(vm, iargs->value, (uint64_t *) &iargs->to);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
static njs_int_t
njs_array_handler_for_each(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
if (njs_is_valid(entry)) {
return njs_array_iterator_call(vm, args, entry, n);
static njs_int_t
njs_array_handler_some(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_int_t ret;
static njs_int_t
njs_array_handler_every(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_int_t ret;
static njs_int_t
njs_array_handler_filter(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_int_t ret;
njs_value_t copy;
static njs_int_t
njs_array_handler_find(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_int_t ret;
njs_value_t copy;
static njs_int_t
njs_array_handler_find_index(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_int_t ret;
njs_value_t copy;
static njs_int_t
njs_array_handler_map(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_int_t ret;
njs_array_t *retval;
- njs_value_t this, key;
+ njs_value_t this;
retval = args->array;
} else {
njs_set_array(&this, retval);
- njs_uint32_to_string(&key, n);
- ret = njs_value_property_set(vm, &this, &key, &vm->retval);
+ ret = njs_value_property_i64_set(vm, &this, n, &vm->retval);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
njs_array_prototype_map(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- uint32_t length, i;
+ uint64_t length, i;
njs_int_t ret;
njs_array_t *array;
njs_value_t *this;
njs_inline njs_int_t
njs_array_iterator_reduce(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_value_t arguments[5];
static njs_int_t
njs_array_handler_reduce(njs_vm_t *vm, njs_array_iterator_args_t *args,
- njs_value_t *entry, uint32_t n)
+ njs_value_t *entry, uint64_t n)
{
njs_int_t ret;
return ret;
}
- ret = njs_value_length(vm, iargs.value, &iargs.from);
+ ret = njs_value_length(vm, iargs.value, (uint64_t *) &iargs.from);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
static njs_int_t
-njs_array_string_sort(njs_vm_t *vm, njs_value_t *args,
- njs_uint_t nargs, njs_index_t unused)
+njs_array_string_sort(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t unused)
{
njs_int_t ret;
njs_uint_t i;
static njs_int_t
-njs_array_prototype_sort(njs_vm_t *vm, njs_value_t *args,
- njs_uint_t nargs, njs_index_t unused)
+njs_array_prototype_sort(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t unused)
{
- uint32_t n, index, length, current;
+ uint64_t n, index, length, current;
njs_int_t ret;
njs_array_t *array;
njs_value_t retval, value, *this, *start, arguments[3];
njs_uint_t nargs, njs_index_t unused)
{
int8_t direction;
- int64_t count, to, from, end;
- uint32_t length;
+ int64_t length, count, to, from, end;
njs_int_t ret;
njs_array_t *array;
- njs_value_t *this, *value, from_key, to_key, prop;
+ njs_value_t *this, *value, prop;
this = njs_argument(args, 0);
return ret;
}
- ret = njs_value_length(vm, this, &length);
+ ret = njs_value_length(vm, this, (uint64_t *) &length);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
}
while (count-- > 0) {
- /* FIXME: largest index is 2**53-1. */
-
- njs_uint32_to_string(&from_key, (uint32_t) from);
- njs_uint32_to_string(&to_key, (uint32_t) to);
-
- ret = njs_value_property(vm, this, &from_key, &prop);
+ ret = njs_value_property_i64(vm, this, from, &prop);
if (ret == NJS_OK) {
- ret = njs_value_property_set(vm, this, &to_key, &prop);
+ ret = njs_value_property_i64_set(vm, this, to, &prop);
} else {
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
- ret = njs_value_property_delete(vm, this, &to_key, NULL);
+ ret = njs_value_property_i64_delete(vm, this, to, NULL);
}
if (njs_slow_path(ret == NJS_ERROR)) {
{ njs_str("var obj = {}; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 0"),
njs_str("true") },
+ { njs_str("Array.prototype[1] = 1; [0,,].pop()"),
+ njs_str("1") },
+
+ { njs_str("Array.prototype[1] = 1; var a = [0,,]; a.pop(); a.length"),
+ njs_str("1") },
+
+ { njs_str("Object.prototype[1] = 1; Object.prototype.length = 2; Array.prototype.pop.call({0:0})"),
+ njs_str("1") },
+
{ njs_str("var o = Object.freeze({0: 0, 1: 1, length: 2}); Array.prototype.pop.call(o)"),
njs_str("TypeError: Cannot delete property \"1\" of object") },
"Array.prototype.pop.call(a); [a.length, a[a.length - 1]]"),
njs_str("32768,y") },
- { njs_str("Array.prototype.shift()"),
- njs_str("undefined") },
-
{ njs_str("[0,1].slice()"),
njs_str("0,1") },
"catch (e) {i += '; ' + e} i"),
njs_str("1; TypeError: Cannot set property \"length\" of object which has only a getter") },
+ { njs_str("var x = []; x.length = 4294967295; var push = x.push(); push === 4294967295"),
+ njs_str("true") },
+
+ { njs_str("var x = []; x.length = 4294967295; x.push(); x.push(1)"),
+ njs_str("RangeError: Invalid array length") },
+
+ { njs_str("var x = []; x.length = 4294967295; x.push(); "
+ "try {x.push('x')} catch (e) {}; x[4294967295]"),
+ njs_str("x") },
+
+ { njs_str("var x = []; x.length = 4294967295; x.push(); "
+ "try {x.push('x')} catch (e) {}; x.length"),
+ njs_str("4294967295") },
+
+ { njs_str("["
+ " [2**53-2, [1]],"
+ " [2**53-2, [1,2]],"
+ " [2**53-1, [1]],"
+ " [2**53, []],"
+ " [Number.POSITIVE_INFINITY, []],"
+ "]"
+ ".map(args=>{ try {return Array.prototype.push.apply({length:args[0]}, args[1])}"
+ " catch (e) {return e.name} })"),
+ njs_str("9007199254740991,TypeError,TypeError,9007199254740991,9007199254740991") },
+
+ { njs_str("Array.prototype.shift()"),
+ njs_str("undefined") },
+
{ njs_str("var a = [1,2,3]; a.shift() +' '+ a[0] +' '+ a.length"),
njs_str("1 2 2") },
+ { njs_str("Array.prototype[0] = 1; var x = [,2]; x.length = 2; x.shift()"),
+ njs_str("1") },
+
{ njs_str("var x = {'0': 'x', '1': 'y', '2': 'z', 'length': 3};"
"Array.prototype.shift.call(x) +' '+ x[0] +' '+ x.length"),
njs_str("x y 2") },
"Array.prototype.forEach.call(x, (v, k) => a.push(k + ':' + v)); a + ', ' + x.length"),
njs_str("0:0,1:1,7:2,12:3,13:4,14:5,22:6, 23") },
- { njs_str("var x = {0: 0, length: 4294967294};"
- "Array.prototype.unshift.call(x, '0', '1');"),
- njs_str("TypeError: Invalid length") },
+ { njs_str("var x = {0: 0, length: 2**32-2};"
+ "Array.prototype.unshift.call(x, '0', '1'); Object.keys(x).sort()"),
+ njs_str("0,1,2,length") },
+
+ { njs_str("var x = {0: 0, length: 2**53-3};"
+ "Array.prototype.unshift.call(x, '0', '1'); x.length"),
+ njs_str("9007199254740991") },
{ njs_str("var x = {0: 0}; Array.prototype.unshift.call(x); x.length"),
njs_str("0") },
"Array.prototype.indexOf.call(o); i"),
njs_str("1") },
-#if (!NJS_HAVE_MEMORY_SANITIZER) /* False-positive in MSAN? */
{ njs_str("var a = new Array(); a[100] =1; a[99999] = ''; a[10] = new Object(); "
"a[5555] = 5.5; a[123456] = 'str'; a[5] = 1E+309; "
"[1, '', 'str', 1E+309, 5.5, true, 5, 'str1', null, new Object()].map(v=>a.indexOf(v))"),
njs_str("100,99999,123456,5,5555,-1,-1,-1,-1,-1") },
-#endif
{ njs_str("Array.prototype.indexOf.call({199:true, 200:'200.59', length:200}, '200.59')"),
njs_str("-1") },
{ njs_str("Array.prototype.indexOf.call({1:true, 2:'200.59', length:3}, '200.59')"),
njs_str("2") },
+ { njs_str("var stopped = 0;"
+ "var o = {length:3}; "
+ "Object.defineProperty(o, '1',{get:()=>{throw 'Oops'}});"
+ "Object.defineProperty(o, '2', {get:()=>stopped++});"
+ "try { Array.prototype.indexOf.call(o, 7)} catch (e) {};"
+ "stopped"),
+ njs_str("0") },
+
{ njs_str("[].lastIndexOf(1, -1)"),
njs_str("-1") },
{ njs_str("[1,2,1].lastIndexOf(1)"),
njs_str("2") },
+ { njs_str("var stopped = 0;"
+ "var o = {length:3}; "
+ "Object.defineProperty(o, '1', {get:()=>stopped++});"
+ "Object.defineProperty(o, '2',{get:()=>{throw 'Oops'}});"
+ "try { Array.prototype.lastIndexOf.call(o)} catch (e) {};"
+ "stopped"),
+ njs_str("0") },
+
{ njs_str("var o = 'addc';"
"Array.prototype.lastIndexOf.call(o, 'd')"),
njs_str("2") },
"Array.prototype.lastIndexOf.call(o, 'd')"),
njs_str("3") },
-#if (!NJS_HAVE_MEMORY_SANITIZER) /* False-positive in MSAN? */
{ njs_str("var a = new Array(); a[100] =1; a[99999] = ''; a[10] = new Object(); "
"a[5555] = 5.5; a[123456] = 'str'; a[5] = 1E+309; "
"[1,'', 'str', 1E+309, 5.5, true, 5, 'str1', null, new Object()].map(v=>a.lastIndexOf(v))"),
njs_str("100,99999,123456,5,5555,-1,-1,-1,-1,-1") },
-#endif
{ njs_str("var obj = {'10000000': 'x', '10000001': 'y', '10000002': 'z'}; var a = [];"
"obj.length = 90000000;"
"Array.prototype.includes.call(obj, 'a', fromIndex);"),
njs_str("false") },
+ { njs_str("var stopped = 0;"
+ "var o = {length:3}; "
+ "Object.defineProperty(o, '1',{get:()=>{throw 'Oops'}});"
+ "Object.defineProperty(o, '2', {get:()=>stopped++});"
+ "try { Array.prototype.includes.call(o, 7)} catch (e) {};"
+ "stopped"),
+ njs_str("0") },
+
{ njs_str("var a = []; var s = { sum: 0 };"
"a.forEach(function(v, i, a) { this.sum += v }, s); s.sum"),
njs_str("0") },
"Array.prototype.every.call(obj, (val,idx,obj)=>!(obj instanceof Date))"),
njs_str("false") },
+ { njs_str("Array.prototype.every.call({0:11,1:9,length:2**32+1}, val=>val>10)"),
+ njs_str("false") },
+
{ njs_str("var vis = false; var a = []; "
"Object.defineProperty(a, '0', {get:()=>{vis = true; return 11;}, configurable:true});"
"Object.defineProperty(a, '1', {get:()=>{if (vis) {return 9;} else {return 11}}, configurable:true});"
"Array.prototype.slice.call(Array.prototype.fill.call(o, 1))"),
njs_str("1,1") },
+ { njs_str("Array.prototype.slice.call({length:2**32})"),
+ njs_str("RangeError: Invalid array length") },
+
+ { njs_str("Array.prototype.slice.call({0:'x', [2**32-1]:'y',length:2**32}, 0, 2**32)"),
+ njs_str("RangeError: Invalid array length") },
+
+ { njs_str("Array.prototype.slice.call({length:2**32+2, [2**32]:'x', [2**32+1]:'y'}, 2**32)"),
+ njs_str("x,y") },
+
+ { njs_str("Array.prototype.slice.call({length:2**53+2, [2**53-3]:'x', [2**53-2]:'y', [2**53-1]:'z'}, 2**53-3)"),
+ njs_str("x,y") },
+
{ njs_str("var o = {}; Object.defineProperty(o, 'length', {get:()=> {throw TypeError('Boom')}}); "
"Array.prototype.fill.call(o, 1)"),
njs_str("TypeError: Boom") },
"var a = Array.prototype.reduce.call(o, reducer); a"),
njs_str("abc") },
+ { njs_str("function reducer(a, b, i, arr) {"
+ " if (i == 2) Object.defineProperty(arr, i, {enumerable:false}); "
+ " return a + b;"
+ "};"
+ "Array.prototype.reduce.call([1,2,3,4], reducer)"),
+ njs_str("10") },
+
{ njs_str("var o = {0: 'a', 1: 'b', 2: 'c'};"
"Object.defineProperty(o, 'length', {get: () => 4});"
"Object.defineProperty(o, '3', {get: () => 'd'});"
"m.join('')"),
njs_str("0а00000000000000000000000000000") },
+ { njs_str("function reducer(a, b, i, arr) {"
+ " if (i == 2) Object.defineProperty(arr, i, {enumerable:false}); "
+ " return a + b;"
+ "};"
+ "Array.prototype.reduceRight.call([1,2,3,4], reducer)"),
+ njs_str("10") },
+
+ { njs_str("Array.prototype[0] = 1; Array.prototype[1] = 2; Array.prototype[2] = 3;"
+ "[,,].reduceRight((a,b)=>a+b)"),
+ njs_str("3") },
+
{ njs_str("var a = ['1','2','3','4','5','6']; a.sort()"),
njs_str("1,2,3,4,5,6") },
{ njs_str("[1,2,3].join(undefined)"),
njs_str("1,2,3") },
+ { njs_str("Array.prototype[1] = 1; var x = [0]; x.length = 2; x.join()"),
+ njs_str("0,1") },
+
+ { njs_str("Object.prototype[1] = 1; Object.prototype.length = 2; Array.prototype.join.call({0:0})"),
+ njs_str("0,1") },
+
+ { njs_str("var x = [0,,4]; x.length = 3; "
+ "Object.defineProperty(Array.prototype, 1, "
+ "{get:()=>{Object.defineProperty(x, 2, {value:'x', enumerable:false}); return 1}});"
+ "x.join()"),
+ njs_str("0,1,x") },
+
{ njs_str("[].slice.call()"),
njs_str("TypeError: cannot convert null or undefined to object") },