LibJS: Add %TypedArray%.prototype.subarray

This commit is contained in:
Idan Horowitz 2021-07-09 17:17:10 +03:00 committed by Linus Groh
parent ff052a3241
commit f98a98506f
Notes: sideshowbarker 2024-07-18 09:59:59 +09:00
4 changed files with 103 additions and 0 deletions

View File

@ -303,6 +303,7 @@ namespace JS {
P(strike) \
P(stringify) \
P(sub) \
P(subarray) \
P(substr) \
P(substring) \
P(sup) \

View File

@ -46,6 +46,7 @@ void TypedArrayPrototype::initialize(GlobalObject& object)
define_native_function(vm.names.entries, entries, 0, attr);
define_native_function(vm.names.set, set, 1, attr);
define_native_function(vm.names.slice, slice, 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);
@ -907,6 +908,61 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::slice)
return new_array;
}
// 23.2.3.27 %TypedArray%.prototype.subarray ( begin, end ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::subarray)
{
auto* typed_array = typed_array_from(global_object);
if (!typed_array)
return {};
auto length = typed_array->array_length();
auto relative_begin = vm.argument(0).to_integer_or_infinity(global_object);
if (vm.exception())
return {};
i32 begin_index;
if (Value(relative_begin).is_negative_infinity())
begin_index = 0;
else if (relative_begin < 0)
begin_index = max(length + relative_begin, 0);
else
begin_index = min(relative_begin, length);
double relative_end;
if (vm.argument(1).is_undefined()) {
relative_end = length;
} else {
relative_end = vm.argument(1).to_integer_or_infinity(global_object);
if (vm.exception())
return {};
}
i32 end_index;
if (Value(relative_end).is_negative_infinity())
end_index = 0;
else if (relative_end < 0)
end_index = max(length + relative_end, 0);
else
end_index = min(relative_end, length);
auto new_length = max(end_index - begin_index, 0);
Checked<u32> begin_byte_offset = begin_index;
begin_byte_offset *= typed_array->element_size();
begin_byte_offset += typed_array->byte_offset();
if (begin_byte_offset.has_overflow()) {
dbgln("TypedArrayPrototype::begin_byte_offset: limit overflowed, returning as if succeeded.");
return typed_array;
}
MarkedValueList arguments(vm.heap());
arguments.empend(typed_array->viewed_array_buffer());
arguments.empend(begin_byte_offset.value());
arguments.empend(new_length);
return typed_array_species_create(global_object, *typed_array, move(arguments));
}
// 23.2.3.22 %TypedArray%.prototype.reverse ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reverse)
{

View File

@ -43,6 +43,7 @@ private:
JS_DECLARE_NATIVE_FUNCTION(entries);
JS_DECLARE_NATIVE_FUNCTION(set);
JS_DECLARE_NATIVE_FUNCTION(slice);
JS_DECLARE_NATIVE_FUNCTION(subarray);
JS_DECLARE_NATIVE_FUNCTION(reverse);
JS_DECLARE_NATIVE_FUNCTION(copy_within);
JS_DECLARE_NATIVE_FUNCTION(filter);

View File

@ -0,0 +1,45 @@
const TYPED_ARRAYS = [
Uint8Array,
Uint8ClampedArray,
Uint16Array,
Uint32Array,
Int8Array,
Int16Array,
Int32Array,
Float32Array,
Float64Array,
];
const BIGINT_TYPED_ARRAYS = [BigUint64Array, BigInt64Array];
test("basic functionality", () => {
TYPED_ARRAYS.forEach(T => {
expect(T.prototype.subarray).toHaveLength(2);
const typedArray = new T(3);
typedArray[0] = 1;
typedArray[1] = 2;
typedArray[2] = 3;
const subarray = typedArray.subarray(1, 2);
expect(subarray).toHaveLength(1);
expect(subarray[0]).toBe(2);
subarray[0] = 4;
expect(typedArray[1]).toBe(4);
});
BIGINT_TYPED_ARRAYS.forEach(T => {
expect(T.prototype.subarray).toHaveLength(2);
const typedArray = new T(3);
typedArray[0] = 1n;
typedArray[1] = 2n;
typedArray[2] = 3n;
const subarray = typedArray.subarray(1, 2);
expect(subarray).toHaveLength(1);
expect(subarray[0]).toBe(2n);
subarray[0] = 4n;
expect(typedArray[1]).toBe(4n);
});
});