/* * Copyright (C) Igor Sysoev * Copyright (C) Dmitry Volyntsev * Copyright (C) NGINX, Inc. */ #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; static void njs_typed_array_prop_set(njs_vm_t *vm, njs_typed_array_t *array, uint32_t index, double v); njs_typed_array_t * njs_typed_array_alloc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_bool_t zeroing, njs_object_type_t type) { double num; int64_t i, length; uint32_t element_size; uint64_t size, offset; njs_int_t ret; njs_value_t *value, prop; njs_typed_array_t *array, *src_tarray; njs_array_buffer_t *buffer; size = 0; length = 0; offset = 0; buffer = NULL; src_tarray = NULL; element_size = njs_typed_array_element_size(type); value = njs_arg(args, nargs, 0); if (njs_is_array_buffer(value)) { buffer = njs_array_buffer(value); ret = njs_value_to_index(vm, njs_arg(args, nargs, 1), &offset); if (njs_slow_path(ret != NJS_OK)) { return NULL; } if (njs_slow_path((offset % element_size) != 0)) { njs_range_error(vm, "start offset must be multiple of %uD", element_size); return NULL; } if (njs_is_defined(njs_arg(args, nargs, 2))) { ret = njs_value_to_index(vm, njs_argument(args, 2), &size); if (njs_slow_path(ret != NJS_OK)) { return NULL; } } if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NULL; } if (njs_is_defined(njs_arg(args, nargs, 2))) { ret = njs_value_to_index(vm, njs_argument(args, 2), &size); if (njs_slow_path(ret != NJS_OK)) { return NULL; } size *= element_size; if (njs_slow_path((offset + size) > buffer->size)) { njs_range_error(vm, "Invalid typed array length: %uL", size); return NULL; } } else { if (njs_slow_path((buffer->size % element_size) != 0)) { njs_range_error(vm, "byteLength of buffer must be " "multiple of %uD", element_size); return NULL; } if (offset > buffer->size) { njs_range_error(vm, "byteOffset %uL is outside the bound of " "the buffer", offset); return NULL; } size = buffer->size - offset; } } else if (njs_is_typed_array(value)) { src_tarray = njs_typed_array(value); if (njs_slow_path(njs_is_detached_buffer(src_tarray->buffer))) { njs_type_error(vm, "detached buffer"); return NULL; } size = (uint64_t) njs_typed_array_length(src_tarray) * element_size; } else if (njs_is_object(value)) { ret = njs_object_length(vm, value, &length); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } size = length * element_size; } else { ret = njs_value_to_index(vm, value, &size); if (njs_slow_path(ret != NJS_OK)) { return NULL; } size *= element_size; } if (buffer == NULL) { buffer = njs_array_buffer_alloc(vm, size, zeroing); if (njs_slow_path(buffer == NULL)) { return NULL; } } array = njs_mp_zalloc(vm->mem_pool, sizeof(njs_typed_array_t)); if (njs_slow_path(array == NULL)) { goto memory_error; } array->buffer = buffer; array->offset = offset / element_size; array->byte_length = size; array->type = type; if (src_tarray != NULL) { if (type != src_tarray->type) { length = njs_typed_array_length(src_tarray); for (i = 0; i < length; i++) { njs_typed_array_prop_set(vm, array, i, njs_typed_array_prop(src_tarray, i)); } } else { memcpy(&buffer->u.u8[0], &src_tarray->buffer->u.u8[0], size); } } else if (!njs_is_array_buffer(value) && njs_is_object(value)) { for (i = 0; i < length; i++) { ret = njs_value_property_i64(vm, value, i, &prop); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } num = NAN; if (ret == NJS_OK) { ret = njs_value_to_number(vm, &prop, &num); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } } njs_typed_array_prop_set(vm, array, i, num); } } njs_lvlhsh_init(&array->object.hash); njs_lvlhsh_init(&array->object.shared_hash); array->object.__proto__ = njs_vm_proto(vm, type); array->object.type = NJS_TYPED_ARRAY; array->object.extensible = 1; array->object.fast_array = 1; return array; memory_error: njs_memory_error(vm); return NULL; } static njs_int_t njs_typed_array_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t magic, njs_value_t *retval) { njs_typed_array_t *array; if (!vm->top_frame->ctor) { njs_type_error(vm, "Constructor of TypedArray requires 'new'"); return NJS_ERROR; } array = njs_typed_array_alloc(vm, &args[1], nargs - 1, 1, magic); if (njs_slow_path(array == NULL)) { return NJS_ERROR; } njs_set_typed_array(retval, array); return NJS_OK; } static njs_int_t njs_typed_array_create(njs_vm_t *vm, njs_value_t *constructor, njs_value_t *args, njs_uint_t nargs, njs_value_t *retval) { njs_int_t ret; njs_typed_array_t *array; ret = njs_value_construct(vm, constructor, args, nargs, retval); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } if (njs_slow_path(!njs_is_typed_array(retval))) { njs_type_error(vm, "Derived TypedArray constructor " "returned not a typed array"); return NJS_ERROR; } array = njs_typed_array(retval); if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } if (njs_slow_path(nargs == 1 && njs_is_number(&args[0]) && njs_typed_array_length(array) < njs_number(&args[0]))) { njs_type_error(vm, "Derived TypedArray constructor " "returned too short array"); return NJS_ERROR; } return NJS_OK; } static njs_int_t njs_typed_array_species_create(njs_vm_t *vm, njs_value_t *exemplar, njs_value_t *args, njs_uint_t nargs, njs_value_t *retval) { njs_int_t ret; njs_value_t constructor; njs_typed_array_t *array; array = njs_typed_array(exemplar); njs_set_function(&constructor, &njs_vm_ctor(vm, array->type)); ret = njs_value_species_constructor(vm, exemplar, &constructor, &constructor); if (njs_slow_path(ret != NJS_OK)) { return ret; } return njs_typed_array_create(vm, &constructor, args, nargs, retval); } static njs_int_t njs_typed_array_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { double num; uint32_t length, i; njs_int_t ret; njs_value_t *this; njs_value_t argument; njs_typed_array_t *array; this = njs_argument(args, 0); if (njs_slow_path(!njs_is_constructor(this))) { njs_type_error(vm, "%s is not a constructor", njs_type_string(this->type)); return NJS_ERROR; } length = nargs - 1; njs_set_number(&argument, length); ret = njs_typed_array_create(vm, this, &argument, 1, retval); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } array = njs_typed_array(retval); for (i = 0; i < length; i++) { ret = njs_value_to_number(vm, njs_argument(args, i + 1), &num); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } njs_typed_array_prop_set(vm, array, i, num); } njs_set_typed_array(retval, array); return NJS_OK; } static njs_int_t njs_typed_array_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { double num; int64_t length, i; njs_int_t ret; njs_value_t *this, *source, *mapfn; njs_value_t arguments[3], value; njs_function_t *function; njs_typed_array_t *array; this = njs_argument(args, 0); if (njs_slow_path(!njs_is_constructor(this))) { njs_type_error(vm, "%s is not a constructor", njs_type_string(this->type)); return NJS_ERROR; } mapfn = njs_arg(args, nargs, 2); if (njs_slow_path(!njs_is_function_or_undefined(mapfn))) { njs_type_error(vm, "\"mapfn\" argument is not callable"); return NJS_ERROR; } function = NULL; if (njs_is_function(mapfn)) { function = njs_function(mapfn); } source = njs_arg(args, nargs, 1); ret = njs_value_to_object(vm, source); if (njs_slow_path(ret != NJS_OK)) { return ret; } ret = njs_object_length(vm, source, &length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } njs_set_number(&arguments[0], length); ret = njs_typed_array_create(vm, this, arguments, 1, retval); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } array = njs_typed_array(retval); arguments[0] = *njs_arg(args, nargs, 3); for (i = 0; i < length; i++) { ret = njs_value_property_i64(vm, source, i, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } if (function != NULL) { njs_value_assign(&arguments[1], &value); njs_set_number(&arguments[2], i); ret = njs_function_apply(vm, function, arguments, 3, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } } ret = njs_value_to_number(vm, &value, &num); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } njs_typed_array_prop_set(vm, array, i, num); } njs_set_typed_array(retval, array); return NJS_OK; } static njs_int_t njs_typed_array_get_this(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { njs_value_assign(retval, njs_argument(args, 0)); return NJS_OK; } njs_array_buffer_t * njs_typed_array_writable(njs_vm_t *vm, njs_typed_array_t *array) { njs_int_t ret; njs_array_buffer_t *buffer; buffer = array->buffer; if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NULL; } ret = njs_array_buffer_writable(vm, buffer); if (njs_slow_path(ret != NJS_OK)) { return NULL; } return buffer; } static njs_int_t njs_typed_array_get_string_tag(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { njs_value_t *this; static const uint32_t tags[NJS_OBJ_TYPE_TYPED_ARRAY_SIZE] = { NJS_ATOM_STRING_Uint8Array, NJS_ATOM_STRING_Uint8ClampedArray, NJS_ATOM_STRING_Int8Array, NJS_ATOM_STRING_Uint16Array, NJS_ATOM_STRING_Int16Array, NJS_ATOM_STRING_Uint32Array, NJS_ATOM_STRING_Int32Array, NJS_ATOM_STRING_Float32Array, NJS_ATOM_STRING_Float64Array, }; this = njs_argument(args, 0); if (!njs_is_typed_array(this)) { njs_set_undefined(retval); return NJS_OK; } njs_atom_to_value(vm, retval, tags[njs_typed_array_index(njs_typed_array(this)->type)]); return NJS_OK; } static njs_int_t njs_typed_array_prototype_length(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { uint32_t length; njs_value_t *this; njs_typed_array_t *array; this = njs_argument(args, 0); if (!njs_is_typed_array(this)) { njs_type_error(vm, "Method TypedArray.prototype.length called " "on incompatible receiver"); return NJS_ERROR; } array = njs_typed_array(this); length = njs_typed_array_length(array); if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { length = 0; } njs_set_number(retval, length); return NJS_OK; } static njs_int_t njs_typed_array_prototype_buffer(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { njs_value_t *this; njs_typed_array_t *array; this = njs_argument(args, 0); if (!njs_is_typed_array(this) && !njs_is_data_view(this)) { njs_type_error(vm, "Method TypedArray.prototype.buffer called " "on incompatible receiver"); return NJS_ERROR; } array = njs_typed_array(this); njs_set_array_buffer(retval, njs_typed_array_buffer(array)); return NJS_OK; } static njs_int_t njs_typed_array_prototype_byte_length(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { size_t byte_length; njs_value_t *this; njs_typed_array_t *array; this = njs_argument(args, 0); if (!njs_is_typed_array(this) && !njs_is_data_view(this)) { njs_type_error(vm, "Method TypedArray.prototype.byteLength called " "on incompatible receiver"); return NJS_ERROR; } array = njs_typed_array(this); byte_length = array->byte_length; if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { if (njs_is_data_view(this)) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } byte_length = 0; } njs_set_number(retval, byte_length); return NJS_OK; } static njs_int_t njs_typed_array_prototype_byte_offset(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { size_t byte_offset; njs_value_t *this; njs_typed_array_t *array; this = njs_argument(args, 0); if (!njs_is_typed_array(this) && !njs_is_data_view(this)) { njs_type_error(vm, "Method TypedArray.prototype.byteOffset called " "on incompatible receiver"); return NJS_ERROR; } array = njs_typed_array(this); byte_offset = njs_typed_array_offset(array); if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { if (njs_is_data_view(this)) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } byte_offset = 0; } njs_set_number(retval, byte_offset); return NJS_OK; } static void njs_typed_array_prop_set(njs_vm_t *vm, njs_typed_array_t *array, uint32_t index, double v) { int8_t i8; int16_t i16; int32_t i32; njs_array_buffer_t *buffer; buffer = array->buffer; index += array->offset; njs_assert(!buffer->object.shared); switch (array->type) { case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY: if (isnan(v) || v < 0) { v = 0; } else if (v > 255) { v = 255; } buffer->u.u8[index] = lrint(v); break; case NJS_OBJ_TYPE_UINT8_ARRAY: case NJS_OBJ_TYPE_INT8_ARRAY: i8 = njs_number_to_int32(v); buffer->u.u8[index] = i8; break; case NJS_OBJ_TYPE_UINT16_ARRAY: case NJS_OBJ_TYPE_INT16_ARRAY: i16 = njs_number_to_int32(v); buffer->u.u16[index] = i16; break; case NJS_OBJ_TYPE_UINT32_ARRAY: case NJS_OBJ_TYPE_INT32_ARRAY: i32 = njs_number_to_int32(v); buffer->u.u32[index] = i32; break; case NJS_OBJ_TYPE_FLOAT32_ARRAY: buffer->u.f32[index] = v; break; default: /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ buffer->u.f64[index] = v; } } njs_int_t njs_typed_array_set_value(njs_vm_t *vm, njs_typed_array_t *array, uint32_t index, njs_value_t *setval) { double num; njs_int_t ret; njs_array_buffer_t *buffer; ret = njs_value_to_number(vm, setval, &num); if (njs_slow_path(ret != NJS_OK)) { return ret; } buffer = njs_typed_array_writable(vm, array); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } njs_typed_array_prop_set(vm, array, index, num); return NJS_OK; } static njs_int_t njs_typed_array_prototype_set(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { double num; int64_t i, length, src_length, offset; njs_int_t ret; njs_value_t *this, *src, *value, prop; njs_typed_array_t *self, *src_tarray; 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; } self = njs_typed_array(this); src = njs_arg(args, nargs, 1); value = njs_arg(args, nargs, 2); ret = njs_value_to_integer(vm, value, &offset); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } if (njs_slow_path(offset < 0)) { njs_range_error(vm, "offset is out of bounds"); return NJS_ERROR; } buffer = njs_typed_array_writable(vm, self); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } length = njs_typed_array_length(self); if (njs_is_typed_array(src)) { src_tarray = njs_typed_array(src); if (njs_slow_path(njs_is_detached_buffer(src_tarray->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } src_length = njs_typed_array_length(src_tarray); if (njs_slow_path((src_length > length) || (offset > length - src_length))) { njs_range_error(vm, "source is too large"); return NJS_ERROR; } length = njs_min(njs_typed_array_length(src_tarray), length - offset); for (i = 0; i < length; i++) { njs_typed_array_prop_set(vm, self, offset + i, njs_typed_array_prop(src_tarray, i)); } } else { ret = njs_value_to_object(vm, src); if (njs_slow_path(ret != NJS_OK)) { return ret; } ret = njs_object_length(vm, src, &src_length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } if (njs_slow_path((src_length > length) || (offset > length - src_length))) { njs_range_error(vm, "source is too large"); return NJS_ERROR; } length = njs_min(src_length, length - offset); for (i = 0; i < length; i++) { ret = njs_value_property_i64(vm, src, i, &prop); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } num = NAN; if (ret == NJS_OK) { ret = njs_value_to_number(vm, &prop, &num); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } } if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } njs_typed_array_prop_set(vm, self, offset + i, num); } } njs_set_undefined(retval); return NJS_OK; } static njs_int_t njs_typed_array_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { float f32; int8_t i8; double num; int16_t i16; int32_t i32; uint8_t u8; int64_t start, end, offset; uint32_t i, length; njs_int_t ret; njs_value_t *this, *setval, lvalue; 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); if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } length = njs_typed_array_length(array); setval = njs_lvalue_arg(&lvalue, args, nargs, 1); ret = njs_value_to_number(vm, setval, &num); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &start); if (njs_slow_path(ret != NJS_OK)) { return ret; } start = (start < 0) ? njs_max(length + start, 0) : njs_min(start, length); if (njs_is_undefined(njs_arg(args, nargs, 3))) { end = length; } else { ret = njs_value_to_integer(vm, njs_arg(args, nargs, 3), &end); if (njs_slow_path(ret != NJS_OK)) { return ret; } } end = (end < 0) ? njs_max(length + end, 0) : njs_min(end, length); buffer = njs_typed_array_writable(vm, array); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } njs_set_typed_array(retval, array); offset = array->offset; switch (array->type) { case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY: if (isnan(num) || num < 0) { u8 = 0; } else if (num > 255) { u8 = 255; } else { u8 = lrint(num); } if (start < end) { memset(&buffer->u.u8[start + offset], u8, end - start); } break; case NJS_OBJ_TYPE_UINT8_ARRAY: case NJS_OBJ_TYPE_INT8_ARRAY: i8 = njs_number_to_int32(num); if (start < end) { memset(&buffer->u.u8[start + offset], i8, end - start); } break; case NJS_OBJ_TYPE_UINT16_ARRAY: case NJS_OBJ_TYPE_INT16_ARRAY: i16 = njs_number_to_int32(num); for (i = start; i < end; i++) { buffer->u.u16[i + offset] = i16; } break; case NJS_OBJ_TYPE_UINT32_ARRAY: case NJS_OBJ_TYPE_INT32_ARRAY: i32 = njs_number_to_int32(num); for (i = start; i < end; i++) { buffer->u.u32[i + offset] = i32; } break; case NJS_OBJ_TYPE_FLOAT32_ARRAY: f32 = num; for (i = start; i < end; i++) { buffer->u.f32[i + offset] = f32; } break; default: /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ for (i = start; i < end; i++) { buffer->u.f64[i + offset] = num; } } return NJS_OK; } njs_int_t njs_typed_array_prototype_slice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t copy, njs_value_t *retval) { int64_t start, end, count, offset; uint32_t i, element_size, length; njs_int_t ret; njs_value_t arguments[3], *this, *value; njs_typed_array_t *array, *new_array; njs_array_buffer_t *buffer, *new_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 = njs_typed_array_buffer(array); if (njs_slow_path(copy && njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &start); if (njs_slow_path(ret != NJS_OK)) { njs_range_error(vm, "invalid start"); return NJS_ERROR; } start = (start < 0) ? njs_max(length + start, 0) : njs_min(start, length); value = njs_arg(args, nargs, 2); if (njs_is_undefined(value)) { end = length; } else { ret = njs_value_to_integer(vm, value, &end); if (njs_slow_path(ret != NJS_OK)) { njs_range_error(vm, "invalid end"); return NJS_ERROR; } } end = (end < 0) ? njs_max(length + end, 0) : njs_min(end, length); element_size = njs_typed_array_element_size(array->type); if (copy) { count = njs_max(end - start, 0); njs_set_number(&arguments[0], count); ret = njs_typed_array_species_create(vm, this, njs_value_arg(arguments), 1, retval); if (njs_slow_path(ret != NJS_OK)) { return ret; } if (count == 0) { return NJS_OK; } if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } new_array = njs_typed_array(retval); new_buffer = njs_typed_array_buffer(new_array); element_size = njs_typed_array_element_size(array->type); if (njs_fast_path(array->type == new_array->type)) { start = start * element_size; count = count * element_size; memcpy(&new_buffer->u.u8[0], &buffer->u.u8[start], count); } else { for (i = 0; i < count; i++) { njs_typed_array_prop_set(vm, new_array, i, njs_typed_array_prop(array, i + start)); } } return NJS_OK; } offset = array->offset * element_size; offset += start * element_size; njs_set_array_buffer(&arguments[0], buffer); njs_set_number(&arguments[1], offset); njs_set_number(&arguments[2], njs_max(end - start, 0)); return njs_typed_array_species_create(vm, this, njs_value_arg(arguments), 3, retval); } static njs_int_t njs_typed_array_prototype_copy_within(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { int64_t length, to, from, final, count; uint32_t element_size; njs_int_t ret; njs_value_t *this, *value; 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); if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } length = njs_typed_array_length(array); value = njs_arg(args, nargs, 1); ret = njs_value_to_integer(vm, value, &to); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } to = to < 0 ? njs_max(to + length, 0) : njs_min(to, length); value = njs_arg(args, nargs, 2); ret = njs_value_to_integer(vm, value, &from); if (njs_slow_path(ret != NJS_OK)) { return ret; } from = from < 0 ? njs_max(from + length, 0) : njs_min(from, length); value = njs_arg(args, nargs, 3); final = length; if (njs_is_defined(value)) { ret = njs_value_to_integer(vm, value, &final); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } } final = (final < 0) ? njs_max(final + length, 0) : njs_min(final, length); njs_set_typed_array(retval, array); count = njs_min(final - from, length - to); if (count <= 0) { return NJS_OK; } buffer = njs_typed_array_writable(vm, array); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } element_size = njs_typed_array_element_size(array->type); to = (to + array->offset) * element_size; from = (from + array->offset) * element_size; count = count * element_size; memmove(&buffer->u.u8[to], &buffer->u.u8[from], count); return NJS_OK; } 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, njs_value_t *retval) { 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], value; njs_function_t *function; njs_typed_array_t *array, *dst; 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; } 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); buffer = array->buffer; 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, &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } dst = njs_typed_array(&value); break; case NJS_ARRAY_FILTER: default: r = njs_arr_init(vm->mem_pool, &results, NULL, 4, sizeof(njs_value_t)); if (njs_slow_path(r == NULL)) { return NJS_ERROR; } } for (i = 0; i < length; i++) { if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } val = njs_typed_array_prop(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, retval); if (njs_slow_path(ret != NJS_OK)) { goto exception; } switch (type) { case NJS_ARRAY_EVERY: if (!njs_is_true(retval)) { njs_set_boolean(retval, 0); 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(retval)) { continue; } switch (type) { case NJS_ARRAY_SOME: njs_set_boolean(retval, 1); break; case NJS_ARRAY_FIND: njs_set_number(retval, val); break; default: njs_set_number(retval, i); break; } goto done; case NJS_ARRAY_MAP: ret = njs_typed_array_set_value(vm, dst, i, retval); if (njs_slow_path(ret != NJS_OK)) { goto exception; } break; default: /* NJS_ARRAY_FILTER. */ if (!njs_is_true(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: njs_set_boolean(retval, 1); break; case NJS_ARRAY_SOME: njs_set_boolean(retval, 0); break; case NJS_ARRAY_FOR_EACH: case NJS_ARRAY_FIND: njs_set_undefined(retval); break; case NJS_ARRAY_FIND_INDEX: njs_set_number(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, &value); if (njs_slow_path(ret != NJS_OK)) { goto exception; } dst = njs_typed_array(&value); 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(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, njs_value_t *retval) { 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; } } if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } v = njs_number(njs_argument(args, 1)); i64 = njs_unsafe_cast_double_to_int64(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(retval, index != -1); } else { njs_set_number(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, njs_value_t *retval) { 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; 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); 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; } buffer = array->buffer; if (nargs > 2) { accumulator = *njs_argument(args, 2); } else { if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } njs_set_number(&accumulator, njs_typed_array_prop(array, from)); from += increment; } for (i = from; i != to; i += increment) { if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } njs_set_undefined(&arguments[0]); arguments[1] = accumulator; njs_set_number(&arguments[2], njs_typed_array_prop(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; } } njs_value_assign(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 to_reversed, njs_value_t *retval) { double *f64; uint8_t *u8; int64_t i, length; uint16_t *u16; uint32_t *u32; njs_value_t *this, arguments[1]; njs_typed_array_t *array, *self; 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); if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } if (to_reversed) { self = array; njs_set_number(&arguments[0], njs_typed_array_length(self)); array = njs_typed_array_alloc(vm, arguments, 1, 0, self->type); if (njs_slow_path(array == NULL)) { return NJS_ERROR; } memcpy(&array->buffer->u.u8[0], &self->buffer->u.u8[0], self->byte_length); } length = njs_typed_array_length(array); buffer = njs_typed_array_writable(vm, array); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } 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(retval, array); return NJS_OK; } static int njs_typed_array_compare_i8(const void *a, const void *b, void *c) { return *((const int8_t *) a) - *((const int8_t *) b); } static int njs_typed_array_compare_u8(const void *a, const void *b, void *c) { return *((const uint8_t *) a) - *((const uint8_t *) b); } static int njs_typed_array_compare_i16(const void *a, const void *b, void *c) { return *((const int16_t *) a) - *((const int16_t *) b); } static int njs_typed_array_compare_u16(const void *a, const void *b, void *c) { return *((const uint16_t *) a) - *((const uint16_t *) b); } static int njs_typed_array_compare_i32(const void *a, const void *b, void *c) { int32_t ai, bi; ai = *(const int32_t *) a; bi = *(const int32_t *) b; return (ai > bi) - (ai < bi); } static int njs_typed_array_compare_u32(const void *a, const void *b, void *c) { uint32_t au, bu; au = *(const uint32_t *) a; bu = *(const uint32_t *) b; return (au > bu) - (au < bu); } njs_inline int njs_typed_array_compare(double a, double b) { if (njs_slow_path(isnan(a))) { if (isnan(b)) { return 0; } return 1; } if (njs_slow_path(isnan(b))) { return -1; } if (a < b) { return -1; } if (a > b) { return 1; } return signbit(b) - signbit(a); } static int njs_typed_array_compare_f32(const void *a, const void *b, void *c) { return njs_typed_array_compare(*(const float *) a, *(const float *) b); } static int njs_typed_array_compare_f64(const void *a, const void *b, void *c) { return njs_typed_array_compare(*(const double *) a, *(const double *) b); } static double njs_typed_array_get_u8(const void *a) { return *(const uint8_t *) a; } static double njs_typed_array_get_i8(const void *a) { return *(const int8_t *) a; } static double njs_typed_array_get_u16(const void *a) { return *(const uint16_t *) a; } static double njs_typed_array_get_i16(const void *a) { return *(const int16_t *) a; } static double njs_typed_array_get_u32(const void *a) { return *(const uint32_t *) a; } static double njs_typed_array_get_i32(const void *a) { return *(const int32_t *) a; } static double njs_typed_array_get_f32(const void *a) { return *(const float *) a; } static double njs_typed_array_get_f64(const void *a) { return *(const double *) a; } typedef struct { njs_vm_t *vm; njs_array_buffer_t *buffer; njs_function_t *function; njs_bool_t exception; double (*get)(const void *v); } njs_typed_array_sort_ctx_t; typedef int (*njs_typed_array_cmp_t)(const void *, const void *, void *ctx); static int njs_typed_array_generic_compare(const void *a, const void *b, void *c) { double num; njs_int_t ret; njs_value_t arguments[3], retval; njs_typed_array_sort_ctx_t *ctx; ctx = c; if (njs_slow_path(ctx->exception)) { return 0; } njs_set_undefined(&arguments[0]); njs_set_number(&arguments[1], ctx->get(a)); njs_set_number(&arguments[2], ctx->get(b)); ret = njs_function_apply(ctx->vm, ctx->function, arguments, 3, &retval); if (njs_slow_path(ret != NJS_OK)) { goto exception; } ret = njs_value_to_number(ctx->vm, &retval, &num); if (njs_slow_path(ret != NJS_OK)) { goto exception; } if (njs_slow_path(njs_is_detached_buffer(ctx->buffer))) { njs_type_error(ctx->vm, "detached buffer"); goto exception; } if (njs_slow_path(isnan(num))) { return 0; } if (num != 0) { return (num > 0) - (num < 0); } return 0; exception: ctx->exception = 1; return 0; } static njs_int_t njs_typed_array_prototype_sort(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t to_sorted, njs_value_t *retval) { u_char *base, *orig; int64_t length; uint32_t element_size; njs_value_t *this, *comparefn, arguments[1]; njs_typed_array_t *array, *self; njs_array_buffer_t *buffer; njs_typed_array_cmp_t cmp; njs_typed_array_sort_ctx_t ctx; 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; } if (to_sorted) { self = array; njs_set_number(&arguments[0], njs_typed_array_length(self)); array = njs_typed_array_alloc(vm, arguments, 1, 0, self->type); if (njs_slow_path(array == NULL)) { return NJS_ERROR; } memcpy(&array->buffer->u.u8[0], &self->buffer->u.u8[0], self->byte_length); } ctx.vm = vm; ctx.buffer = array->buffer; ctx.exception = 0; comparefn = njs_arg(args, nargs, 1); if (njs_is_defined(comparefn)) { if (njs_slow_path(!njs_is_function(comparefn))) { njs_type_error(vm, "comparefn must be callable or undefined"); return NJS_ERROR; } ctx.function = njs_function(comparefn); } else { ctx.function = NULL; } switch (array->type) { case NJS_OBJ_TYPE_UINT8_ARRAY: case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY: cmp = njs_typed_array_compare_u8; ctx.get = njs_typed_array_get_u8; break; case NJS_OBJ_TYPE_INT8_ARRAY: cmp = njs_typed_array_compare_i8; ctx.get = njs_typed_array_get_i8; break; case NJS_OBJ_TYPE_UINT16_ARRAY: cmp = njs_typed_array_compare_u16; ctx.get = njs_typed_array_get_u16; break; case NJS_OBJ_TYPE_INT16_ARRAY: cmp = njs_typed_array_compare_i16; ctx.get = njs_typed_array_get_i16; break; case NJS_OBJ_TYPE_UINT32_ARRAY: cmp = njs_typed_array_compare_u32; ctx.get = njs_typed_array_get_u32; break; case NJS_OBJ_TYPE_INT32_ARRAY: cmp = njs_typed_array_compare_i32; ctx.get = njs_typed_array_get_i32; break; case NJS_OBJ_TYPE_FLOAT32_ARRAY: cmp = njs_typed_array_compare_f32; ctx.get = njs_typed_array_get_f32; break; default: /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ cmp = njs_typed_array_compare_f64; ctx.get = njs_typed_array_get_f64; break; } buffer = njs_typed_array_writable(vm, array); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } length = njs_typed_array_length(array); element_size = njs_typed_array_element_size(array->type); base = &buffer->u.u8[array->offset * element_size]; orig = base; if (ctx.function != NULL) { cmp = njs_typed_array_generic_compare; base = njs_mp_alloc(vm->mem_pool, length * element_size); if (njs_slow_path(base == NULL)) { njs_memory_error(vm); return NJS_ERROR; } memcpy(base, &buffer->u.u8[array->offset * element_size], length * element_size); } njs_qsort(base, length, element_size, cmp, &ctx); if (njs_slow_path(ctx.exception)) { return NJS_ERROR; } if (ctx.function != NULL) { if (&buffer->u.u8[array->offset * element_size] == orig) { memcpy(orig, base, length * element_size); } njs_mp_free(vm->mem_pool, base); } njs_set_typed_array(retval, array); return NJS_OK; } void njs_typed_array_to_chain(njs_vm_t *vm, njs_chb_t *chain, njs_typed_array_t *array, njs_value_t *sep) { size_t length; uint32_t i; njs_string_prop_t separator; if (sep != NULL && njs_is_string(sep)) { (void) njs_string_prop(vm, &separator, sep); } else { separator.start = (u_char *) ","; separator.size = 1; separator.length = 1; } length = njs_typed_array_length(array); if (length == 0) { return; } for (i = 0; i < length; i++) { njs_number_to_chain(vm, chain, njs_typed_array_prop(array, i)); njs_chb_append(chain, separator.start, separator.size); } njs_chb_drop(chain, separator.size); } static njs_int_t njs_typed_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { size_t length; njs_int_t ret; njs_chb_t chain; njs_value_t *this, *separator; 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; } length = njs_typed_array_length(array); separator = njs_arg(args, nargs, 1); if (njs_slow_path(!njs_is_string(separator))) { if (njs_is_defined(separator)) { ret = njs_value_to_string(vm, separator, separator); if (njs_slow_path(ret != NJS_OK)) { return ret; } } } if (length == 0) { njs_set_empty_string(vm, retval); return NJS_OK; } if (njs_slow_path(njs_is_detached_buffer(array->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } NJS_CHB_MP_INIT(&chain, njs_vm_memory_pool(vm)); njs_typed_array_to_chain(vm, &chain, array, separator); ret = njs_string_create_chb(vm, retval, &chain); njs_chb_destroy(&chain); return ret; } 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 *retval) { 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, 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, njs_value_t *retval) { njs_type_error(vm, "Abstract class TypedArray not directly constructable"); return NJS_ERROR; } static const njs_object_prop_init_t njs_typed_array_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(0), NJS_DECLARE_PROP_NAME("TypedArray"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_GETTER(SYMBOL_species, njs_typed_array_get_this, 0), NJS_DECLARE_PROP_NATIVE(STRING_of, njs_typed_array_of, 0, 0), NJS_DECLARE_PROP_NATIVE(STRING_from, njs_typed_array_from, 1, 0), }; static const njs_object_init_t njs_typed_array_constructor_init = { njs_typed_array_constructor_props, njs_nitems(njs_typed_array_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_prototype_properties[] = { NJS_DECLARE_PROP_GETTER(SYMBOL_toStringTag, njs_typed_array_get_string_tag, 0), NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_GETTER(STRING_buffer, njs_typed_array_prototype_buffer, 0), NJS_DECLARE_PROP_GETTER(STRING_byteLength, njs_typed_array_prototype_byte_length, 0), NJS_DECLARE_PROP_GETTER(STRING_byteOffset, njs_typed_array_prototype_byte_offset, 0), NJS_DECLARE_PROP_GETTER(STRING_length, njs_typed_array_prototype_length, 0), NJS_DECLARE_PROP_NATIVE(STRING_copyWithin, njs_typed_array_prototype_copy_within, 2, 0), NJS_DECLARE_PROP_NATIVE(STRING_entries, njs_typed_array_prototype_iterator_obj, 0, NJS_ENUM_BOTH), NJS_DECLARE_PROP_NATIVE(STRING_every, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_EVERY), NJS_DECLARE_PROP_NATIVE(STRING_filter, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FILTER), NJS_DECLARE_PROP_NATIVE(STRING_find, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FIND), NJS_DECLARE_PROP_NATIVE(STRING_findIndex, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FIND_INDEX), NJS_DECLARE_PROP_NATIVE(STRING_forEach, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_FOR_EACH), NJS_DECLARE_PROP_NATIVE(STRING_includes, njs_typed_array_prototype_index_of, 1, 1), NJS_DECLARE_PROP_NATIVE(STRING_indexOf, njs_typed_array_prototype_index_of, 1, 0), NJS_DECLARE_PROP_NATIVE(STRING_join, njs_typed_array_prototype_join, 1, 0), NJS_DECLARE_PROP_NATIVE(STRING_fill, njs_typed_array_prototype_fill, 1, 0), NJS_DECLARE_PROP_NATIVE(STRING_keys, njs_typed_array_prototype_iterator_obj, 0, NJS_ENUM_KEYS), NJS_DECLARE_PROP_NATIVE(STRING_lastIndexOf, njs_typed_array_prototype_index_of, 1, 2), NJS_DECLARE_PROP_NATIVE(STRING_map, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_MAP), NJS_DECLARE_PROP_NATIVE(STRING_reduce, njs_typed_array_prototype_reduce, 1, 0), NJS_DECLARE_PROP_NATIVE(STRING_reduceRight, njs_typed_array_prototype_reduce, 1, 1), NJS_DECLARE_PROP_NATIVE(STRING_reverse, njs_typed_array_prototype_reverse, 0, 0), NJS_DECLARE_PROP_NATIVE(STRING_set, njs_typed_array_prototype_set, 2, 0), NJS_DECLARE_PROP_NATIVE(STRING_slice, njs_typed_array_prototype_slice, 2, 1), NJS_DECLARE_PROP_NATIVE(STRING_some, njs_typed_array_prototype_iterator, 1, NJS_ARRAY_SOME), NJS_DECLARE_PROP_NATIVE(STRING_sort, njs_typed_array_prototype_sort, 1, 0), NJS_DECLARE_PROP_NATIVE(STRING_subarray, njs_typed_array_prototype_slice, 2, 0), NJS_DECLARE_PROP_NATIVE(STRING_toReversed, njs_typed_array_prototype_reverse, 0, 1), NJS_DECLARE_PROP_NATIVE(STRING_toSorted, njs_typed_array_prototype_sort, 1, 1), NJS_DECLARE_PROP_NATIVE(STRING_toString, njs_array_prototype_to_string, 0, 0), NJS_DECLARE_PROP_NATIVE(STRING_values, njs_typed_array_prototype_iterator_obj, 0, NJS_ENUM_VALUES), NJS_DECLARE_PROP_NATIVE(SYMBOL_iterator, njs_typed_array_prototype_iterator_obj, 0, NJS_ENUM_VALUES), }; static const njs_object_init_t njs_typed_array_prototype_init = { njs_typed_array_prototype_properties, njs_nitems(njs_typed_array_prototype_properties), }; const njs_object_type_init_t njs_typed_array_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor_intrinsic, 0, 0), .prototype_props = &njs_typed_array_prototype_init, .constructor_props = &njs_typed_array_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static njs_int_t njs_data_view_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { uint64_t size, offset; njs_int_t ret; njs_data_view_t *view; njs_array_buffer_t *buffer; if (!vm->top_frame->ctor) { njs_type_error(vm, "Constructor of DataView requires 'new'"); return NJS_ERROR; } if (!njs_is_array_buffer(njs_arg(args, nargs, 1))) { njs_type_error(vm, "buffer is not an ArrayBuffer"); return NJS_ERROR; } size = 0; offset = 0; ret = njs_value_to_index(vm, njs_arg(args, nargs, 2), &offset); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } buffer = njs_array_buffer(njs_argument(args, 1)); if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } if (!njs_is_undefined(njs_arg(args, nargs, 3))) { ret = njs_value_to_index(vm, njs_argument(args, 3), &size); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } if (njs_slow_path((offset + size) > buffer->size)) { njs_range_error(vm, "Invalid DataView length: %uL", size); return NJS_ERROR; } } else { if (offset > buffer->size) { njs_range_error(vm, "byteOffset %uL is outside the bound of " "the buffer", offset); return NJS_ERROR; } size = buffer->size - offset; } view = njs_mp_zalloc(vm->mem_pool, sizeof(njs_data_view_t)); if (njs_slow_path(view == NULL)) { goto memory_error; } view->buffer = buffer; view->offset = offset; view->byte_length = size; view->type = NJS_OBJ_TYPE_DATA_VIEW; njs_lvlhsh_init(&view->object.hash); njs_lvlhsh_init(&view->object.shared_hash); view->object.__proto__ = njs_vm_proto(vm, view->type); view->object.type = NJS_DATA_VIEW; view->object.extensible = 1; njs_set_data_view(retval, view); return NJS_OK; memory_error: njs_memory_error(vm); return NJS_ERROR; } static const njs_object_prop_init_t njs_data_view_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_NAME("DataView"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), }; static const njs_object_init_t njs_data_view_constructor_init = { njs_data_view_constructor_props, njs_nitems(njs_data_view_constructor_props), }; static njs_int_t njs_data_view_prototype_get(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t type, njs_value_t *retval) { double v; uint32_t u32; uint64_t index; njs_int_t ret; njs_bool_t swap; njs_value_t *this; const uint8_t *u8; njs_conv_f32_t conv_f32; njs_conv_f64_t conv_f64; njs_data_view_t *view; njs_array_buffer_t *buffer; this = njs_argument(args, 0); if (njs_slow_path(!njs_is_data_view(this))) { njs_type_error(vm, "this is not a DataView"); return NJS_ERROR; } ret = njs_value_to_index(vm, njs_arg(args, nargs, 1), &index); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } swap = njs_bool(njs_arg(args, nargs, 2)); #if NJS_HAVE_LITTLE_ENDIAN swap = !swap; #endif view = njs_data_view(this); if (njs_slow_path(njs_is_detached_buffer(view->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } if (njs_typed_array_element_size(type) + index > view->byte_length) { njs_range_error(vm, "index %uL is outside the bound of the buffer", index); return NJS_ERROR; } buffer = view->buffer; u8 = &buffer->u.u8[index + view->offset]; switch (type) { case NJS_OBJ_TYPE_UINT8_ARRAY: v = *u8; break; case NJS_OBJ_TYPE_INT8_ARRAY: v = (int8_t) *u8; break; case NJS_OBJ_TYPE_UINT16_ARRAY: u32 = njs_get_u16(u8); if (swap) { u32 = njs_bswap_u16(u32); } v = u32; break; case NJS_OBJ_TYPE_INT16_ARRAY: u32 = njs_get_u16(u8); if (swap) { u32 = njs_bswap_u16(u32); } v = (int16_t) u32; break; case NJS_OBJ_TYPE_UINT32_ARRAY: case NJS_OBJ_TYPE_INT32_ARRAY: case NJS_OBJ_TYPE_FLOAT32_ARRAY: u32 = njs_get_u32(u8); if (swap) { u32 = njs_bswap_u32(u32); } switch (type) { case NJS_OBJ_TYPE_UINT32_ARRAY: v = u32; break; case NJS_OBJ_TYPE_INT32_ARRAY: v = (int32_t) u32; break; default: conv_f32.u = u32; v = conv_f32.f; } break; default: /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ conv_f64.u = njs_get_u64(u8); if (swap) { conv_f64.u = njs_bswap_u64(conv_f64.u); } v = conv_f64.f; } njs_set_number(retval, v); return NJS_OK; } static njs_int_t njs_data_view_prototype_set(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t type, njs_value_t *retval) { double v; uint8_t *u8; uint32_t u32; uint64_t index; njs_int_t ret; njs_bool_t swap; njs_value_t *this; njs_conv_f32_t conv_f32; njs_conv_f64_t conv_f64; njs_data_view_t *view; njs_array_buffer_t *buffer; this = njs_argument(args, 0); if (njs_slow_path(!njs_is_data_view(this))) { njs_type_error(vm, "this is not a DataView"); return NJS_ERROR; } ret = njs_value_to_index(vm, njs_arg(args, nargs, 1), &index); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } ret = njs_value_to_number(vm, njs_arg(args, nargs, 2), &v); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } swap = njs_bool(njs_arg(args, nargs, 3)); #if NJS_HAVE_LITTLE_ENDIAN swap = !swap; #endif view = njs_data_view(this); if (njs_slow_path(njs_is_detached_buffer(view->buffer))) { njs_type_error(vm, "detached buffer"); return NJS_ERROR; } if (njs_typed_array_element_size(type) + index > view->byte_length) { njs_range_error(vm, "index %uL is outside the bound of the buffer", index); return NJS_ERROR; } buffer = view->buffer; u8 = &buffer->u.u8[index + view->offset]; switch (type) { case NJS_OBJ_TYPE_UINT8_ARRAY: case NJS_OBJ_TYPE_INT8_ARRAY: *u8 = njs_number_to_int32(v); break; case NJS_OBJ_TYPE_UINT16_ARRAY: case NJS_OBJ_TYPE_INT16_ARRAY: u32 = (uint16_t) njs_number_to_int32(v); if (swap) { u32 = njs_bswap_u16(u32); } njs_set_u16(u8, u32); break; case NJS_OBJ_TYPE_UINT32_ARRAY: case NJS_OBJ_TYPE_INT32_ARRAY: u32 = njs_number_to_int32(v); if (swap) { u32 = njs_bswap_u32(u32); } njs_set_u32(u8, u32); break; case NJS_OBJ_TYPE_FLOAT32_ARRAY: conv_f32.f = (float) v; if (swap) { conv_f32.u = njs_bswap_u32(conv_f32.u); } njs_set_u32(u8, conv_f32.u); break; default: /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ conv_f64.f = v; if (swap) { conv_f64.u = njs_bswap_u64(conv_f64.u); } njs_set_u64(u8, conv_f64.u); } njs_set_undefined(retval); return NJS_OK; } static const njs_object_prop_init_t njs_data_view_prototype_properties[] = { NJS_DECLARE_PROP_VALUE(SYMBOL_toStringTag, njs_ascii_strval("DataView"), NJS_OBJECT_PROP_VALUE_C), NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_GETTER(STRING_buffer, njs_typed_array_prototype_buffer, 0), NJS_DECLARE_PROP_GETTER(STRING_byteLength, njs_typed_array_prototype_byte_length, 0), NJS_DECLARE_PROP_GETTER(STRING_byteOffset, njs_typed_array_prototype_byte_offset, 0), NJS_DECLARE_PROP_NATIVE(STRING_getUint8, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_UINT8_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_getInt8, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_INT8_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_getUint16, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_UINT16_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_getInt16, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_INT16_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_getUint32, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_UINT32_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_getInt32, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_INT32_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_getFloat32, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_FLOAT32_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_getFloat64, njs_data_view_prototype_get, 1, NJS_OBJ_TYPE_FLOAT64_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setUint8, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_UINT8_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setInt8, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_INT8_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setUint16, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_UINT16_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setInt16, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_INT16_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setUint32, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_UINT32_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setInt32, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_INT32_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setFloat32, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_FLOAT32_ARRAY), NJS_DECLARE_PROP_NATIVE(STRING_setFloat64, njs_data_view_prototype_set, 2, NJS_OBJ_TYPE_FLOAT64_ARRAY), }; static const njs_object_init_t njs_data_view_prototype_init = { njs_data_view_prototype_properties, njs_nitems(njs_data_view_prototype_properties), }; const njs_object_type_init_t njs_data_view_type_init = { .constructor = njs_native_ctor(njs_data_view_constructor, 1, 0), .prototype_props = &njs_data_view_prototype_init, .constructor_props = &njs_data_view_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_u8_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Uint8Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 1), 0), }; static const njs_object_init_t njs_typed_array_u8_constructor_init = { njs_typed_array_u8_constructor_props, njs_nitems(njs_typed_array_u8_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_u8_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 1), 0), }; static const njs_object_init_t njs_typed_array_u8_prototype_init = { njs_typed_array_u8_prototype_properties, njs_nitems(njs_typed_array_u8_prototype_properties), }; const njs_object_type_init_t njs_typed_array_u8_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_UINT8_ARRAY), .prototype_props = &njs_typed_array_u8_prototype_init, .constructor_props = &njs_typed_array_u8_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_u8c_constructor_props[] = { NJS_DECLARE_PROP_VALUE(STRING_name, njs_ascii_strval("Uint8ClampedArray"), NJS_OBJECT_PROP_VALUE_C), NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 1), 0), }; static const njs_object_init_t njs_typed_array_u8c_constructor_init = { njs_typed_array_u8c_constructor_props, njs_nitems(njs_typed_array_u8c_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_u8c_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 1), 0), }; static const njs_object_init_t njs_typed_array_u8c_prototype_init = { njs_typed_array_u8c_prototype_properties, njs_nitems(njs_typed_array_u8c_prototype_properties), }; const njs_object_type_init_t njs_typed_array_u8clamped_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY), .prototype_props = &njs_typed_array_u8c_prototype_init, .constructor_props = &njs_typed_array_u8c_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_i8_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Int8Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 1), 0), }; static const njs_object_init_t njs_typed_array_i8_constructor_init = { njs_typed_array_i8_constructor_props, njs_nitems(njs_typed_array_i8_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_i8_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 1), 0), }; static const njs_object_init_t njs_typed_array_i8_prototype_init = { njs_typed_array_i8_prototype_properties, njs_nitems(njs_typed_array_i8_prototype_properties), }; const njs_object_type_init_t njs_typed_array_i8_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_INT8_ARRAY), .prototype_props = &njs_typed_array_i8_prototype_init, .constructor_props = &njs_typed_array_i8_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_u16_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Uint16Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 2), 0), }; static const njs_object_init_t njs_typed_array_u16_constructor_init = { njs_typed_array_u16_constructor_props, njs_nitems(njs_typed_array_u16_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_u16_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 2), 0), }; static const njs_object_init_t njs_typed_array_u16_prototype_init = { njs_typed_array_u16_prototype_properties, njs_nitems(njs_typed_array_u16_prototype_properties), }; const njs_object_type_init_t njs_typed_array_u16_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_UINT16_ARRAY), .prototype_props = &njs_typed_array_u16_prototype_init, .constructor_props = &njs_typed_array_u16_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_i16_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Int16Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 2), 0), }; static const njs_object_init_t njs_typed_array_i16_constructor_init = { njs_typed_array_i16_constructor_props, njs_nitems(njs_typed_array_i16_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_i16_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 2), 0), }; static const njs_object_init_t njs_typed_array_i16_prototype_init = { njs_typed_array_i16_prototype_properties, njs_nitems(njs_typed_array_i16_prototype_properties), }; const njs_object_type_init_t njs_typed_array_i16_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_INT16_ARRAY), .prototype_props = &njs_typed_array_i16_prototype_init, .constructor_props = &njs_typed_array_i16_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_u32_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Uint32Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 4), 0), }; static const njs_object_init_t njs_typed_array_u32_constructor_init = { njs_typed_array_u32_constructor_props, njs_nitems(njs_typed_array_u32_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_u32_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 4), 0), }; static const njs_object_init_t njs_typed_array_u32_prototype_init = { njs_typed_array_u32_prototype_properties, njs_nitems(njs_typed_array_u32_prototype_properties), }; const njs_object_type_init_t njs_typed_array_u32_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_UINT32_ARRAY), .prototype_props = &njs_typed_array_u32_prototype_init, .constructor_props = &njs_typed_array_u32_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_i32_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Int32Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 4), 0), }; static const njs_object_init_t njs_typed_array_i32_constructor_init = { njs_typed_array_i32_constructor_props, njs_nitems(njs_typed_array_i32_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_i32_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 4), 0), }; static const njs_object_init_t njs_typed_array_i32_prototype_init = { njs_typed_array_i32_prototype_properties, njs_nitems(njs_typed_array_i32_prototype_properties), }; const njs_object_type_init_t njs_typed_array_i32_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_INT32_ARRAY), .prototype_props = &njs_typed_array_i32_prototype_init, .constructor_props = &njs_typed_array_i32_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_f32_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Float32Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 4), 0), }; static const njs_object_init_t njs_typed_array_f32_constructor_init = { njs_typed_array_f32_constructor_props, njs_nitems(njs_typed_array_f32_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_f32_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 4), 0), }; static const njs_object_init_t njs_typed_array_f32_prototype_init = { njs_typed_array_f32_prototype_properties, njs_nitems(njs_typed_array_f32_prototype_properties), }; const njs_object_type_init_t njs_typed_array_f32_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_FLOAT32_ARRAY), .prototype_props = &njs_typed_array_f32_prototype_init, .constructor_props = &njs_typed_array_f32_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, }; static const njs_object_prop_init_t njs_typed_array_f64_constructor_props[] = { NJS_DECLARE_PROP_LENGTH(3), NJS_DECLARE_PROP_NAME("Float64Array"), NJS_DECLARE_PROP_HANDLER(STRING_prototype, njs_object_prototype_create, 0, 0), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 8), 0), }; static const njs_object_init_t njs_typed_array_f64_constructor_init = { njs_typed_array_f64_constructor_props, njs_nitems(njs_typed_array_f64_constructor_props), }; static const njs_object_prop_init_t njs_typed_array_f64_prototype_properties[] = { NJS_DECLARE_PROP_HANDLER(STRING_constructor, njs_object_prototype_create_constructor, 0, NJS_OBJECT_PROP_VALUE_CW), NJS_DECLARE_PROP_VALUE(STRING_BYTES_PER_ELEMENT, njs_value(NJS_NUMBER, 1, 8), 0), }; static const njs_object_init_t njs_typed_array_f64_prototype_init = { njs_typed_array_f64_prototype_properties, njs_nitems(njs_typed_array_f64_prototype_properties), }; const njs_object_type_init_t njs_typed_array_f64_type_init = { .constructor = njs_native_ctor(njs_typed_array_constructor, 3, NJS_OBJ_TYPE_FLOAT64_ARRAY), .prototype_props = &njs_typed_array_f64_prototype_init, .constructor_props = &njs_typed_array_f64_constructor_init, .prototype_value = { .object = { .type = NJS_OBJECT } }, };