1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 14:07:45 +00:00

LibJS: Sort TypedArray.prototype methods in spec order

Makes it much easier to scroll through the file while comparing to the
spec. Proposals are inserted alphabetically as that's where they will
likely end up once merged into the main spec.
This commit is contained in:
Timothy Flynn 2022-07-15 08:03:57 -04:00 committed by Linus Groh
parent f19c4ab693
commit 999ad734ec
2 changed files with 444 additions and 442 deletions

View file

@ -26,13 +26,17 @@ void TypedArrayPrototype::initialize(GlobalObject& object)
Object::initialize(object); Object::initialize(object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_accessor(vm.names.length, length_getter, nullptr, Attribute::Configurable);
define_native_accessor(vm.names.buffer, buffer_getter, nullptr, Attribute::Configurable); define_native_accessor(vm.names.buffer, buffer_getter, nullptr, Attribute::Configurable);
define_native_accessor(vm.names.byteLength, byte_length_getter, nullptr, Attribute::Configurable); define_native_accessor(vm.names.byteLength, byte_length_getter, nullptr, Attribute::Configurable);
define_native_accessor(vm.names.byteOffset, byte_offset_getter, nullptr, Attribute::Configurable); define_native_accessor(vm.names.byteOffset, byte_offset_getter, nullptr, Attribute::Configurable);
define_native_accessor(vm.names.length, length_getter, nullptr, Attribute::Configurable);
define_native_function(vm.names.at, at, 1, attr); define_native_function(vm.names.at, at, 1, attr);
define_native_function(vm.names.copyWithin, copy_within, 2, attr);
define_native_function(vm.names.entries, entries, 0, attr);
define_native_function(vm.names.every, every, 1, attr); define_native_function(vm.names.every, every, 1, attr);
define_native_function(vm.names.fill, fill, 1, attr); define_native_function(vm.names.fill, fill, 1, attr);
define_native_function(vm.names.filter, filter, 1, attr);
define_native_function(vm.names.find, find, 1, attr); define_native_function(vm.names.find, find, 1, attr);
define_native_function(vm.names.findIndex, find_index, 1, attr); define_native_function(vm.names.findIndex, find_index, 1, attr);
define_native_function(vm.names.findLast, find_last, 1, attr); define_native_function(vm.names.findLast, find_last, 1, attr);
@ -40,26 +44,23 @@ void TypedArrayPrototype::initialize(GlobalObject& object)
define_native_function(vm.names.forEach, for_each, 1, attr); define_native_function(vm.names.forEach, for_each, 1, attr);
define_native_function(vm.names.includes, includes, 1, attr); define_native_function(vm.names.includes, includes, 1, attr);
define_native_function(vm.names.indexOf, index_of, 1, attr); define_native_function(vm.names.indexOf, index_of, 1, attr);
define_native_function(vm.names.lastIndexOf, last_index_of, 1, attr);
define_native_function(vm.names.reduce, reduce, 1, attr);
define_native_function(vm.names.reduceRight, reduce_right, 1, attr);
define_native_function(vm.names.some, some, 1, attr);
define_native_function(vm.names.join, join, 1, attr); define_native_function(vm.names.join, join, 1, attr);
define_native_function(vm.names.keys, keys, 0, attr); define_native_function(vm.names.keys, keys, 0, attr);
define_native_function(vm.names.values, values, 0, attr); define_native_function(vm.names.lastIndexOf, last_index_of, 1, attr);
define_native_function(vm.names.entries, entries, 0, attr); define_native_function(vm.names.map, map, 1, attr);
define_native_function(vm.names.reduce, reduce, 1, attr);
define_native_function(vm.names.reduceRight, reduce_right, 1, attr);
define_native_function(vm.names.reverse, reverse, 0, attr);
define_native_function(vm.names.set, set, 1, attr); define_native_function(vm.names.set, set, 1, attr);
define_native_function(vm.names.slice, slice, 2, attr); define_native_function(vm.names.slice, slice, 2, attr);
define_native_function(vm.names.some, some, 1, attr);
define_native_function(vm.names.sort, sort, 1, attr); define_native_function(vm.names.sort, sort, 1, attr);
define_native_function(vm.names.subarray, subarray, 2, attr); define_native_function(vm.names.subarray, subarray, 2, attr);
define_native_function(vm.names.reverse, reverse, 0, attr);
define_native_function(vm.names.copyWithin, copy_within, 2, attr);
define_native_function(vm.names.filter, filter, 1, attr);
define_native_function(vm.names.map, map, 1, attr);
define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr); define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
define_native_function(vm.names.toReversed, to_reversed, 0, attr); define_native_function(vm.names.toReversed, to_reversed, 0, attr);
define_native_function(vm.names.toSorted, to_sorted, 1, attr); define_native_function(vm.names.toSorted, to_sorted, 1, attr);
define_native_function(vm.names.toSpliced, to_spliced, 2, attr); define_native_function(vm.names.toSpliced, to_spliced, 2, attr);
define_native_function(vm.names.values, values, 0, attr);
define_native_accessor(*vm.well_known_symbol_to_string_tag(), to_string_tag_getter, nullptr, Attribute::Configurable); define_native_accessor(*vm.well_known_symbol_to_string_tag(), to_string_tag_getter, nullptr, Attribute::Configurable);
@ -163,17 +164,6 @@ static ThrowCompletionOr<TypedArrayBase*> typed_array_species_create(GlobalObjec
return result; return result;
} }
// 23.2.3.19 get %TypedArray%.prototype.length, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.length
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::length_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
if (array_buffer->is_detached())
return Value(0);
return Value(typed_array->array_length());
}
// 23.2.3.1 %TypedArray%.prototype.at ( index ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.at // 23.2.3.1 %TypedArray%.prototype.at ( index ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.at
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::at) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::at)
{ {
@ -194,6 +184,212 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::at)
return TRY(typed_array->get(index.value())); return TRY(typed_array->get(index.value()));
} }
// 23.2.3.2 get %TypedArray%.prototype.buffer, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.buffer
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::buffer_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
return Value(array_buffer);
}
// 23.2.3.3 get %TypedArray%.prototype.byteLength, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.bytelength
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_length_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
if (array_buffer->is_detached())
return Value(0);
return Value(typed_array->byte_length());
}
// 23.2.3.4 get %TypedArray%.prototype.byteOffset, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.byteoffset
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_offset_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
if (array_buffer->is_detached())
return Value(0);
return Value(typed_array->byte_offset());
}
// 23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.copywithin
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::copy_within)
{
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length();
// 4. Let relativeTarget be ? ToIntegerOrInfinity(target).
auto relative_target = TRY(vm.argument(0).to_integer_or_infinity(global_object));
double to;
if (Value(relative_target).is_negative_infinity()) {
// 5. If relativeTarget is -∞, let to be 0.
to = 0.0;
} else if (relative_target < 0) {
// 6. Else if relativeTarget < 0, let to be max(len + relativeTarget, 0)
to = max(length + relative_target, 0.0);
} else {
// 7. Else, let to be min(relativeTarget, len).
to = min(relative_target, (double)length);
}
// 8. Let relativeStart be ? ToIntegerOrInfinity(start).
auto relative_start = TRY(vm.argument(1).to_integer_or_infinity(global_object));
double from;
if (Value(relative_start).is_negative_infinity()) {
// 9. If relativeStart is -∞, let from be 0.
from = 0.0;
} else if (relative_start < 0) {
// 10. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
from = max(length + relative_start, 0.0);
} else {
// 11. Else, let from be min(relativeStart, len).
from = min(relative_start, (double)length);
}
double relative_end;
// 12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
if (vm.argument(2).is_undefined())
relative_end = length;
else
relative_end = TRY(vm.argument(2).to_integer_or_infinity(global_object));
double final;
if (Value(relative_end).is_negative_infinity()) {
// 13. If relativeEnd is -∞, let final be 0.
final = 0.0;
} else if (relative_end < 0) {
// 14. Else if relativeEnd < 0, let final be max(len + relativeEnd, 0).
final = max(length + relative_end, 0.0);
} else {
// 15. Else, let final be min(relativeEnd, len).
final = min(relative_end, (double)length);
}
// 16. Let count be min(final - from, len - to).
double count = min(final - from, length - to);
// 17. If count > 0, then
if (count > 0.0) {
// a. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
// b. Let buffer be O.[[ViewedArrayBuffer]].
auto buffer = typed_array->viewed_array_buffer();
// c. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
if (buffer->is_detached())
return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
// d. Let elementSize be TypedArrayElementSize(O).
auto element_size = typed_array->element_size();
// e. Let byteOffset be O.[[ByteOffset]].
auto byte_offset = typed_array->byte_offset();
// FIXME: Not exactly sure what we should do when overflow occurs.
// Just return as if succeeded for now. (This goes for steps g to j)
// f. Let toByteIndex be to × elementSize + byteOffset.
Checked<size_t> to_byte_index_checked = static_cast<size_t>(to);
to_byte_index_checked *= element_size;
to_byte_index_checked += byte_offset;
if (to_byte_index_checked.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: to_byte_index overflowed, returning as if succeeded.");
return typed_array;
}
// g. Let fromByteIndex be from × elementSize + byteOffset.
Checked<size_t> from_byte_index_checked = static_cast<size_t>(from);
from_byte_index_checked *= element_size;
from_byte_index_checked += byte_offset;
if (from_byte_index_checked.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: from_byte_index_checked overflowed, returning as if succeeded.");
return typed_array;
}
// h. Let countBytes be count × elementSize.
Checked<size_t> count_bytes_checked = static_cast<size_t>(count);
count_bytes_checked *= element_size;
if (count_bytes_checked.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: count_bytes_checked overflowed, returning as if succeeded.");
return typed_array;
}
auto to_byte_index = to_byte_index_checked.value();
auto from_byte_index = from_byte_index_checked.value();
auto count_bytes = count_bytes_checked.value();
Checked<size_t> from_plus_count = from_byte_index;
from_plus_count += count_bytes;
if (from_plus_count.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: from_plus_count overflowed, returning as if succeeded.");
return typed_array;
}
i8 direction;
// i. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
if (from_byte_index < to_byte_index && to_byte_index < from_plus_count.value()) {
// i. Let direction be -1.
direction = -1;
// ii. Set fromByteIndex to fromByteIndex + countBytes - 1.
from_byte_index = from_plus_count.value() - 1;
Checked<size_t> to_plus_count = to_byte_index;
to_plus_count += count_bytes;
if (to_plus_count.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: to_plus_count overflowed, returning as if succeeded.");
return typed_array;
}
// iii. Set toByteIndex to toByteIndex + countBytes - 1.
to_byte_index = to_plus_count.value() - 1;
}
// j. Else,
else {
// i. Let direction be 1.
direction = 1;
}
// k. Repeat, while countBytes > 0,
for (; count_bytes > 0; --count_bytes) {
// i. Let value be GetValueFromBuffer(buffer, fromByteIndex, Uint8, true, Unordered).
auto value = buffer->get_value<u8>(from_byte_index, true, ArrayBuffer::Order::Unordered);
// ii. Perform SetValueInBuffer(buffer, toByteIndex, Uint8, value, true, Unordered).
buffer->set_value<u8>(to_byte_index, value, true, ArrayBuffer::Order::Unordered);
// iii. Set fromByteIndex to fromByteIndex + direction.
from_byte_index += direction;
// iv. Set toByteIndex to toByteIndex + direction.
to_byte_index += direction;
// v. Set countBytes to countBytes - 1.
}
}
// 18. Return O.
return typed_array;
}
// 23.2.3.7 %TypedArray%.prototype.entries ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::entries)
{
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
return ArrayIterator::create(global_object, typed_array, Object::PropertyKind::KeyAndValue);
}
// 23.2.3.8 %TypedArray%.prototype.every ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.every // 23.2.3.8 %TypedArray%.prototype.every ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.every
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::every) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::every)
{ {
@ -254,6 +450,70 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::fill)
return typed_array; return typed_array;
} }
// 23.2.3.10 %TypedArray%.prototype.filter ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
{
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto initial_length = typed_array->array_length();
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
auto* callback_function = TRY(callback_from_args(global_object, "filter"));
// 5. Let kept be a new empty List.
MarkedVector<Value> kept(vm.heap());
// 7. Let captured be 0.
size_t captured = 0;
auto this_value = vm.argument(1);
// 5. Let k be 0.
// 8. Repeat, while k < len,
for (size_t i = 0; i < initial_length; ++i) {
// a. Let Pk be ! ToString(𝔽(k)).
// b. Let kValue be ! Get(O, Pk).
auto value = MUST(typed_array->get(i));
// c. Let selected be ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto callback_result = TRY(call(global_object, *callback_function, this_value, value, Value((i32)i), typed_array)).to_boolean();
// d. If selected is true, then
if (callback_result) {
// i. Append kValue to the end of kept.
kept.append(value);
// ii. Set captured to captured + 1.
++captured;
}
// e. Set k to k + 1.
}
// 9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) »).
MarkedVector<Value> arguments(vm.heap());
arguments.empend(captured);
auto* filter_array = TRY(typed_array_species_create(global_object, *typed_array, move(arguments)));
// 10. Let n be 0.
size_t index = 0;
// 11. For each element e of kept, do
for (auto& value : kept) {
// a. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
MUST(filter_array->set(index, value, Object::ShouldThrowExceptions::Yes));
// b. Set n to n + 1.
++index;
}
// 12. Return A.
return filter_array;
}
// 23.2.3.11 %TypedArray%.prototype.find ( predicate [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.find // 23.2.3.11 %TypedArray%.prototype.find ( predicate [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.find
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find)
{ {
@ -400,6 +660,36 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::index_of)
return Value(-1); return Value(-1);
} }
// 23.2.3.16 %TypedArray%.prototype.join ( separator ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.join
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::join)
{
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
auto length = typed_array->array_length();
String separator = ",";
if (!vm.argument(0).is_undefined())
separator = TRY(vm.argument(0).to_string(global_object));
StringBuilder builder;
for (size_t i = 0; i < length; ++i) {
if (i > 0)
builder.append(separator);
auto value = TRY(typed_array->get(i));
if (value.is_nullish())
continue;
auto string = TRY(value.to_string(global_object));
builder.append(string);
}
return js_string(vm, builder.to_string());
}
// 23.2.3.17 %TypedArray%.prototype.keys ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::keys)
{
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
return ArrayIterator::create(global_object, typed_array, Object::PropertyKind::Key);
}
// 23.2.3.18 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof // 23.2.3.18 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::last_index_of) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::last_index_of)
{ {
@ -443,6 +733,57 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::last_index_of)
return Value(-1); return Value(-1);
} }
// 23.2.3.19 get %TypedArray%.prototype.length, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.length
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::length_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
if (array_buffer->is_detached())
return Value(0);
return Value(typed_array->array_length());
}
// 23.2.3.20 %TypedArray%.prototype.map ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.map
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::map)
{
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto initial_length = typed_array->array_length();
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
auto* callback_function = TRY(callback_from_args(global_object, "map"));
// 5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) »).
MarkedVector<Value> arguments(vm.heap());
arguments.empend(initial_length);
auto* return_array = TRY(typed_array_species_create(global_object, *typed_array, move(arguments)));
auto this_value = vm.argument(1);
// 6. Let k be 0.
// 7. Repeat, while k < len,
for (size_t i = 0; i < initial_length; ++i) {
// a. Let Pk be ! ToString(𝔽(k)).
// b. Let kValue be ! Get(O, Pk).
auto value = MUST(typed_array->get(i));
// c. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
auto mapped_value = TRY(call(global_object, *callback_function, this_value, value, Value((i32)i), typed_array));
// d. Perform ? Set(A, Pk, mappedValue, true).
TRY(return_array->set(i, mapped_value, Object::ShouldThrowExceptions::Yes));
// e. Set k to k + 1.
}
// 8. Return A.
return return_array;
}
// 23.2.3.21 %TypedArray%.prototype.reduce ( callbackfn [ , initialValue ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce // 23.2.3.21 %TypedArray%.prototype.reduce ( callbackfn [ , initialValue ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce)
{ {
@ -503,108 +844,47 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce_right)
return accumulator; return accumulator;
} }
// 23.2.3.26 %TypedArray%.prototype.some ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.some // 23.2.3.23 %TypedArray%.prototype.reverse ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::some) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reverse)
{
auto result = false;
TRY(for_each_item(vm, global_object, "some", [&](auto, auto, auto callback_result) {
if (callback_result.to_boolean()) {
result = true;
return IterationDecision::Break;
}
return IterationDecision::Continue;
}));
return Value(result);
}
// 23.2.3.16 %TypedArray%.prototype.join ( separator ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.join
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::join)
{ {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length(); auto length = typed_array->array_length();
String separator = ",";
if (!vm.argument(0).is_undefined())
separator = TRY(vm.argument(0).to_string(global_object));
StringBuilder builder; // 4. Let middle be floor(len / 2).
for (size_t i = 0; i < length; ++i) { auto middle = length / 2;
if (i > 0)
builder.append(separator); // 5. Let lower be 0.
auto value = TRY(typed_array->get(i)); // 6. Repeat, while lower ≠ middle,
if (value.is_nullish()) for (size_t lower = 0; lower != middle; ++lower) {
continue; // a. Let upper be len - lower - 1.
auto string = TRY(value.to_string(global_object)); auto upper = length - lower - 1;
builder.append(string);
// b. Let upperP be ! ToString(𝔽(upper)).
// d. Let lowerValue be ! Get(O, lowerP).
auto lower_value = MUST(typed_array->get(lower));
// c. Let lowerP be ! ToString(𝔽(lower)).
// e. Let upperValue be ! Get(O, upperP).
auto upper_value = MUST(typed_array->get(upper));
// f. Perform ! Set(O, lowerP, upperValue, true).
MUST(typed_array->set(lower, upper_value, Object::ShouldThrowExceptions::Yes));
// g. Perform ! Set(O, upperP, lowerValue, true).
MUST(typed_array->set(upper, lower_value, Object::ShouldThrowExceptions::Yes));
// h. Set lower to lower + 1.
} }
return js_string(vm, builder.to_string()); // 7. Return O.
return typed_array;
} }
// 23.2.3.17 %TypedArray%.prototype.keys ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys // 23.2.3.24.1 SetTypedArrayFromTypedArray ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromtypedarray
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::keys)
{
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
return ArrayIterator::create(global_object, typed_array, Object::PropertyKind::Key);
}
// 23.2.3.31 %TypedArray%.prototype.values ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::values)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
return ArrayIterator::create(global_object, typed_array, Object::PropertyKind::Value);
}
// 23.2.3.7 %TypedArray%.prototype.entries ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::entries)
{
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
return ArrayIterator::create(global_object, typed_array, Object::PropertyKind::KeyAndValue);
}
// 23.2.3.2 get %TypedArray%.prototype.buffer, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.buffer
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::buffer_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
return Value(array_buffer);
}
// 23.2.3.3 get %TypedArray%.prototype.byteLength, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.bytelength
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_length_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
if (array_buffer->is_detached())
return Value(0);
return Value(typed_array->byte_length());
}
// 23.2.3.4 get %TypedArray%.prototype.byteOffset, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.byteoffset
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_offset_getter)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer);
if (array_buffer->is_detached())
return Value(0);
return Value(typed_array->byte_offset());
}
// 23.2.3.33 get %TypedArray%.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_string_tag_getter)
{
auto this_value = vm.this_value(global_object);
if (!this_value.is_object())
return js_undefined();
auto& this_object = this_value.as_object();
if (!this_object.is_typed_array())
return js_undefined();
return js_string(vm, static_cast<TypedArrayBase&>(this_object).element_name());
}
// 23.2.3.23.1 SetTypedArrayFromTypedArray ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromtypedarray
static ThrowCompletionOr<void> set_typed_array_from_typed_array(GlobalObject& global_object, TypedArrayBase& target, double target_offset, TypedArrayBase& source) static ThrowCompletionOr<void> set_typed_array_from_typed_array(GlobalObject& global_object, TypedArrayBase& target, double target_offset, TypedArrayBase& source)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
@ -726,7 +1006,7 @@ static ThrowCompletionOr<void> set_typed_array_from_typed_array(GlobalObject& gl
return {}; return {};
} }
// 23.2.3.23.2 SetTypedArrayFromArrayLike ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromarraylike // 23.2.3.24.2 SetTypedArrayFromArrayLike ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromarraylike
static ThrowCompletionOr<void> set_typed_array_from_array_like(GlobalObject& global_object, TypedArrayBase& target, double target_offset, Value source) static ThrowCompletionOr<void> set_typed_array_from_array_like(GlobalObject& global_object, TypedArrayBase& target, double target_offset, Value source)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
@ -956,6 +1236,20 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::slice)
return new_array; return new_array;
} }
// 23.2.3.26 %TypedArray%.prototype.some ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.some
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::some)
{
auto result = false;
TRY(for_each_item(vm, global_object, "some", [&](auto, auto, auto callback_result) {
if (callback_result.to_boolean()) {
result = true;
return IterationDecision::Break;
}
return IterationDecision::Continue;
}));
return Value(result);
}
static ThrowCompletionOr<void> typed_array_merge_sort(GlobalObject& global_object, FunctionObject* compare_function, ArrayBuffer& buffer, MarkedVector<Value>& arr_to_sort) static ThrowCompletionOr<void> typed_array_merge_sort(GlobalObject& global_object, FunctionObject* compare_function, ArrayBuffer& buffer, MarkedVector<Value>& arr_to_sort)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
@ -1148,318 +1442,6 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::subarray)
return TRY(typed_array_species_create(global_object, *typed_array, move(arguments))); return TRY(typed_array_species_create(global_object, *typed_array, move(arguments)));
} }
// 23.2.3.23 %TypedArray%.prototype.reverse ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reverse)
{
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length();
// 4. Let middle be floor(len / 2).
auto middle = length / 2;
// 5. Let lower be 0.
// 6. Repeat, while lower ≠ middle,
for (size_t lower = 0; lower != middle; ++lower) {
// a. Let upper be len - lower - 1.
auto upper = length - lower - 1;
// b. Let upperP be ! ToString(𝔽(upper)).
// d. Let lowerValue be ! Get(O, lowerP).
auto lower_value = MUST(typed_array->get(lower));
// c. Let lowerP be ! ToString(𝔽(lower)).
// e. Let upperValue be ! Get(O, upperP).
auto upper_value = MUST(typed_array->get(upper));
// f. Perform ! Set(O, lowerP, upperValue, true).
MUST(typed_array->set(lower, upper_value, Object::ShouldThrowExceptions::Yes));
// g. Perform ! Set(O, upperP, lowerValue, true).
MUST(typed_array->set(upper, lower_value, Object::ShouldThrowExceptions::Yes));
// h. Set lower to lower + 1.
}
// 7. Return O.
return typed_array;
}
// 23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.copywithin
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::copy_within)
{
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length();
// 4. Let relativeTarget be ? ToIntegerOrInfinity(target).
auto relative_target = TRY(vm.argument(0).to_integer_or_infinity(global_object));
double to;
if (Value(relative_target).is_negative_infinity()) {
// 5. If relativeTarget is -∞, let to be 0.
to = 0.0;
} else if (relative_target < 0) {
// 6. Else if relativeTarget < 0, let to be max(len + relativeTarget, 0)
to = max(length + relative_target, 0.0);
} else {
// 7. Else, let to be min(relativeTarget, len).
to = min(relative_target, (double)length);
}
// 8. Let relativeStart be ? ToIntegerOrInfinity(start).
auto relative_start = TRY(vm.argument(1).to_integer_or_infinity(global_object));
double from;
if (Value(relative_start).is_negative_infinity()) {
// 9. If relativeStart is -∞, let from be 0.
from = 0.0;
} else if (relative_start < 0) {
// 10. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
from = max(length + relative_start, 0.0);
} else {
// 11. Else, let from be min(relativeStart, len).
from = min(relative_start, (double)length);
}
double relative_end;
// 12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
if (vm.argument(2).is_undefined())
relative_end = length;
else
relative_end = TRY(vm.argument(2).to_integer_or_infinity(global_object));
double final;
if (Value(relative_end).is_negative_infinity()) {
// 13. If relativeEnd is -∞, let final be 0.
final = 0.0;
} else if (relative_end < 0) {
// 14. Else if relativeEnd < 0, let final be max(len + relativeEnd, 0).
final = max(length + relative_end, 0.0);
} else {
// 15. Else, let final be min(relativeEnd, len).
final = min(relative_end, (double)length);
}
// 16. Let count be min(final - from, len - to).
double count = min(final - from, length - to);
// 17. If count > 0, then
if (count > 0.0) {
// a. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
// b. Let buffer be O.[[ViewedArrayBuffer]].
auto buffer = typed_array->viewed_array_buffer();
// c. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
if (buffer->is_detached())
return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
// d. Let elementSize be TypedArrayElementSize(O).
auto element_size = typed_array->element_size();
// e. Let byteOffset be O.[[ByteOffset]].
auto byte_offset = typed_array->byte_offset();
// FIXME: Not exactly sure what we should do when overflow occurs.
// Just return as if succeeded for now. (This goes for steps g to j)
// f. Let toByteIndex be to × elementSize + byteOffset.
Checked<size_t> to_byte_index_checked = static_cast<size_t>(to);
to_byte_index_checked *= element_size;
to_byte_index_checked += byte_offset;
if (to_byte_index_checked.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: to_byte_index overflowed, returning as if succeeded.");
return typed_array;
}
// g. Let fromByteIndex be from × elementSize + byteOffset.
Checked<size_t> from_byte_index_checked = static_cast<size_t>(from);
from_byte_index_checked *= element_size;
from_byte_index_checked += byte_offset;
if (from_byte_index_checked.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: from_byte_index_checked overflowed, returning as if succeeded.");
return typed_array;
}
// h. Let countBytes be count × elementSize.
Checked<size_t> count_bytes_checked = static_cast<size_t>(count);
count_bytes_checked *= element_size;
if (count_bytes_checked.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: count_bytes_checked overflowed, returning as if succeeded.");
return typed_array;
}
auto to_byte_index = to_byte_index_checked.value();
auto from_byte_index = from_byte_index_checked.value();
auto count_bytes = count_bytes_checked.value();
Checked<size_t> from_plus_count = from_byte_index;
from_plus_count += count_bytes;
if (from_plus_count.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: from_plus_count overflowed, returning as if succeeded.");
return typed_array;
}
i8 direction;
// i. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
if (from_byte_index < to_byte_index && to_byte_index < from_plus_count.value()) {
// i. Let direction be -1.
direction = -1;
// ii. Set fromByteIndex to fromByteIndex + countBytes - 1.
from_byte_index = from_plus_count.value() - 1;
Checked<size_t> to_plus_count = to_byte_index;
to_plus_count += count_bytes;
if (to_plus_count.has_overflow()) {
dbgln("TypedArrayPrototype::copy_within: to_plus_count overflowed, returning as if succeeded.");
return typed_array;
}
// iii. Set toByteIndex to toByteIndex + countBytes - 1.
to_byte_index = to_plus_count.value() - 1;
}
// j. Else,
else {
// i. Let direction be 1.
direction = 1;
}
// k. Repeat, while countBytes > 0,
for (; count_bytes > 0; --count_bytes) {
// i. Let value be GetValueFromBuffer(buffer, fromByteIndex, Uint8, true, Unordered).
auto value = buffer->get_value<u8>(from_byte_index, true, ArrayBuffer::Order::Unordered);
// ii. Perform SetValueInBuffer(buffer, toByteIndex, Uint8, value, true, Unordered).
buffer->set_value<u8>(to_byte_index, value, true, ArrayBuffer::Order::Unordered);
// iii. Set fromByteIndex to fromByteIndex + direction.
from_byte_index += direction;
// iv. Set toByteIndex to toByteIndex + direction.
to_byte_index += direction;
// v. Set countBytes to countBytes - 1.
}
}
// 18. Return O.
return typed_array;
}
// 23.2.3.10 %TypedArray%.prototype.filter ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
{
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto initial_length = typed_array->array_length();
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
auto* callback_function = TRY(callback_from_args(global_object, "filter"));
// 5. Let kept be a new empty List.
MarkedVector<Value> kept(vm.heap());
// 7. Let captured be 0.
size_t captured = 0;
auto this_value = vm.argument(1);
// 5. Let k be 0.
// 8. Repeat, while k < len,
for (size_t i = 0; i < initial_length; ++i) {
// a. Let Pk be ! ToString(𝔽(k)).
// b. Let kValue be ! Get(O, Pk).
auto value = MUST(typed_array->get(i));
// c. Let selected be ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto callback_result = TRY(call(global_object, *callback_function, this_value, value, Value((i32)i), typed_array)).to_boolean();
// d. If selected is true, then
if (callback_result) {
// i. Append kValue to the end of kept.
kept.append(value);
// ii. Set captured to captured + 1.
++captured;
}
// e. Set k to k + 1.
}
// 9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) »).
MarkedVector<Value> arguments(vm.heap());
arguments.empend(captured);
auto* filter_array = TRY(typed_array_species_create(global_object, *typed_array, move(arguments)));
// 10. Let n be 0.
size_t index = 0;
// 11. For each element e of kept, do
for (auto& value : kept) {
// a. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
MUST(filter_array->set(index, value, Object::ShouldThrowExceptions::Yes));
// b. Set n to n + 1.
++index;
}
// 12. Return A.
return filter_array;
}
// 23.2.3.20 %TypedArray%.prototype.map ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.map
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::map)
{
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object));
// 3. Let len be O.[[ArrayLength]].
auto initial_length = typed_array->array_length();
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
auto* callback_function = TRY(callback_from_args(global_object, "map"));
// 5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) »).
MarkedVector<Value> arguments(vm.heap());
arguments.empend(initial_length);
auto* return_array = TRY(typed_array_species_create(global_object, *typed_array, move(arguments)));
auto this_value = vm.argument(1);
// 6. Let k be 0.
// 7. Repeat, while k < len,
for (size_t i = 0; i < initial_length; ++i) {
// a. Let Pk be ! ToString(𝔽(k)).
// b. Let kValue be ! Get(O, Pk).
auto value = MUST(typed_array->get(i));
// c. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
auto mapped_value = TRY(call(global_object, *callback_function, this_value, value, Value((i32)i), typed_array));
// d. Perform ? Set(A, Pk, mappedValue, true).
TRY(return_array->set(i, mapped_value, Object::ShouldThrowExceptions::Yes));
// e. Set k to k + 1.
}
// 8. Return A.
return return_array;
}
// 23.2.3.29 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring // 23.2.3.29 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring
// 19.5.1 Array.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-array.prototype.tolocalestring // 19.5.1 Array.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-array.prototype.tolocalestring
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
@ -1733,4 +1715,23 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_spliced)
return return_array; return return_array;
} }
// 23.2.3.31 %TypedArray%.prototype.values ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::values)
{
auto* typed_array = TRY(typed_array_from_this(global_object));
return ArrayIterator::create(global_object, typed_array, Object::PropertyKind::Value);
}
// 23.2.3.33 get %TypedArray%.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_string_tag_getter)
{
auto this_value = vm.this_value(global_object);
if (!this_value.is_object())
return js_undefined();
auto& this_object = this_value.as_object();
if (!this_object.is_typed_array())
return js_undefined();
return js_string(vm, static_cast<TypedArrayBase&>(this_object).element_name());
}
} }

View file

@ -20,14 +20,17 @@ public:
virtual ~TypedArrayPrototype() override = default; virtual ~TypedArrayPrototype() override = default;
private: private:
JS_DECLARE_NATIVE_FUNCTION(length_getter);
JS_DECLARE_NATIVE_FUNCTION(buffer_getter); JS_DECLARE_NATIVE_FUNCTION(buffer_getter);
JS_DECLARE_NATIVE_FUNCTION(byte_length_getter); JS_DECLARE_NATIVE_FUNCTION(byte_length_getter);
JS_DECLARE_NATIVE_FUNCTION(byte_offset_getter); JS_DECLARE_NATIVE_FUNCTION(byte_offset_getter);
JS_DECLARE_NATIVE_FUNCTION(to_string_tag_getter); JS_DECLARE_NATIVE_FUNCTION(length_getter);
JS_DECLARE_NATIVE_FUNCTION(at); JS_DECLARE_NATIVE_FUNCTION(at);
JS_DECLARE_NATIVE_FUNCTION(copy_within);
JS_DECLARE_NATIVE_FUNCTION(entries);
JS_DECLARE_NATIVE_FUNCTION(every); JS_DECLARE_NATIVE_FUNCTION(every);
JS_DECLARE_NATIVE_FUNCTION(fill); JS_DECLARE_NATIVE_FUNCTION(fill);
JS_DECLARE_NATIVE_FUNCTION(filter);
JS_DECLARE_NATIVE_FUNCTION(find); JS_DECLARE_NATIVE_FUNCTION(find);
JS_DECLARE_NATIVE_FUNCTION(find_index); JS_DECLARE_NATIVE_FUNCTION(find_index);
JS_DECLARE_NATIVE_FUNCTION(find_last); JS_DECLARE_NATIVE_FUNCTION(find_last);
@ -35,26 +38,24 @@ private:
JS_DECLARE_NATIVE_FUNCTION(for_each); JS_DECLARE_NATIVE_FUNCTION(for_each);
JS_DECLARE_NATIVE_FUNCTION(includes); JS_DECLARE_NATIVE_FUNCTION(includes);
JS_DECLARE_NATIVE_FUNCTION(index_of); JS_DECLARE_NATIVE_FUNCTION(index_of);
JS_DECLARE_NATIVE_FUNCTION(last_index_of);
JS_DECLARE_NATIVE_FUNCTION(reduce);
JS_DECLARE_NATIVE_FUNCTION(reduce_right);
JS_DECLARE_NATIVE_FUNCTION(some);
JS_DECLARE_NATIVE_FUNCTION(join); JS_DECLARE_NATIVE_FUNCTION(join);
JS_DECLARE_NATIVE_FUNCTION(keys); JS_DECLARE_NATIVE_FUNCTION(keys);
JS_DECLARE_NATIVE_FUNCTION(values); JS_DECLARE_NATIVE_FUNCTION(last_index_of);
JS_DECLARE_NATIVE_FUNCTION(entries); JS_DECLARE_NATIVE_FUNCTION(map);
JS_DECLARE_NATIVE_FUNCTION(reduce);
JS_DECLARE_NATIVE_FUNCTION(reduce_right);
JS_DECLARE_NATIVE_FUNCTION(reverse);
JS_DECLARE_NATIVE_FUNCTION(set); JS_DECLARE_NATIVE_FUNCTION(set);
JS_DECLARE_NATIVE_FUNCTION(slice); JS_DECLARE_NATIVE_FUNCTION(slice);
JS_DECLARE_NATIVE_FUNCTION(some);
JS_DECLARE_NATIVE_FUNCTION(sort); JS_DECLARE_NATIVE_FUNCTION(sort);
JS_DECLARE_NATIVE_FUNCTION(subarray); JS_DECLARE_NATIVE_FUNCTION(subarray);
JS_DECLARE_NATIVE_FUNCTION(reverse);
JS_DECLARE_NATIVE_FUNCTION(copy_within);
JS_DECLARE_NATIVE_FUNCTION(filter);
JS_DECLARE_NATIVE_FUNCTION(map);
JS_DECLARE_NATIVE_FUNCTION(to_locale_string); JS_DECLARE_NATIVE_FUNCTION(to_locale_string);
JS_DECLARE_NATIVE_FUNCTION(to_reversed); JS_DECLARE_NATIVE_FUNCTION(to_reversed);
JS_DECLARE_NATIVE_FUNCTION(to_sorted); JS_DECLARE_NATIVE_FUNCTION(to_sorted);
JS_DECLARE_NATIVE_FUNCTION(to_spliced); JS_DECLARE_NATIVE_FUNCTION(to_spliced);
JS_DECLARE_NATIVE_FUNCTION(values);
JS_DECLARE_NATIVE_FUNCTION(to_string_tag_getter);
}; };
} }