mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 14:57:35 +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:
parent
f19c4ab693
commit
999ad734ec
2 changed files with 444 additions and 442 deletions
|
@ -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));
|
||||||
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;
|
// 3. Let len be O.[[ArrayLength]].
|
||||||
for (size_t i = 0; i < length; ++i) {
|
auto length = typed_array->array_length();
|
||||||
if (i > 0)
|
|
||||||
builder.append(separator);
|
// 4. Let middle be floor(len / 2).
|
||||||
auto value = TRY(typed_array->get(i));
|
auto middle = length / 2;
|
||||||
if (value.is_nullish())
|
|
||||||
continue;
|
// 5. Let lower be 0.
|
||||||
auto string = TRY(value.to_string(global_object));
|
// 6. Repeat, while lower ≠ middle,
|
||||||
builder.append(string);
|
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.
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue