diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp index 6245afec7b..b2cbaacab5 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp @@ -30,6 +30,7 @@ void TypedArrayPrototype::initialize(GlobalObject& object) define_native_accessor(vm.names.byteOffset, byte_offset_getter, nullptr, Attribute::Configurable); define_native_function(vm.names.at, at, 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.find, find, 1, attr); define_native_function(vm.names.findIndex, find_index, 1, attr); define_native_function(vm.names.forEach, for_each, 1, attr); @@ -163,6 +164,69 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::every) return Value(result); } +// 23.2.3.8 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill +JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::fill) +{ + auto typed_array = typed_array_from(vm, global_object); + if (!typed_array) + return {}; + + auto length = typed_array->array_length(); + + Value value; + if (typed_array->content_type() == TypedArrayBase::ContentType::BigInt) { + value = vm.argument(0).to_bigint(global_object); + if (vm.exception()) + return {}; + } else { + value = vm.argument(0).to_number(global_object); + if (vm.exception()) + return {}; + } + + auto relative_start = vm.argument(1).to_integer_or_infinity(global_object); + if (vm.exception()) + return {}; + + u32 k; + if (Value(relative_start).is_negative_infinity()) + k = 0; + else if (relative_start < 0) + k = max(length + relative_start, 0); + else + k = min(relative_start, length); + + double relative_end; + if (vm.argument(2).is_undefined()) { + relative_end = length; + } else { + relative_end = vm.argument(2).to_integer_or_infinity(global_object); + if (vm.exception()) + return {}; + } + + u32 final; + if (Value(relative_end).is_negative_infinity()) + final = 0; + else if (relative_end < 0) + final = max(length + relative_end, 0); + else + final = min(relative_end, length); + + if (typed_array->viewed_array_buffer()->is_detached()) { + vm.throw_exception(global_object, ErrorType::DetachedArrayBuffer); + return {}; + } + + for (; k < final; ++k) { + typed_array->set(k, value, true); + if (vm.exception()) + return {}; + } + + return typed_array; +} + // 23.2.3.10 %TypedArray%.prototype.find ( predicate [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.find JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find) { diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h index 1344a7d19c..a5cdae86df 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h @@ -27,6 +27,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(to_string_tag_getter); JS_DECLARE_NATIVE_FUNCTION(at); JS_DECLARE_NATIVE_FUNCTION(every); + JS_DECLARE_NATIVE_FUNCTION(fill); JS_DECLARE_NATIVE_FUNCTION(find); JS_DECLARE_NATIVE_FUNCTION(find_index); JS_DECLARE_NATIVE_FUNCTION(for_each); diff --git a/Userland/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.fill.js b/Userland/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.fill.js new file mode 100644 index 0000000000..4260cc45e8 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.fill.js @@ -0,0 +1,57 @@ +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.fill).toHaveLength(1); + + const typedArray = new T(3); + typedArray[0] = 1; + typedArray[1] = 2; + typedArray[2] = 3; + + expect(typedArray.fill(0)).toBe(typedArray); + + expect(typedArray[0]).toBe(0); + expect(typedArray[1]).toBe(0); + expect(typedArray[2]).toBe(0); + + expect(typedArray.fill(5, 1, 2)).toBe(typedArray); + + expect(typedArray[0]).toBe(0); + expect(typedArray[1]).toBe(5); + expect(typedArray[2]).toBe(0); + }); + + BIGINT_TYPED_ARRAYS.forEach(T => { + expect(T.prototype.fill).toHaveLength(1); + + const typedArray = new T(3); + typedArray[0] = 1n; + typedArray[1] = 2n; + typedArray[2] = 3n; + + expect(typedArray.fill(0n)).toBe(typedArray); + + expect(typedArray[0]).toBe(0n); + expect(typedArray[1]).toBe(0n); + expect(typedArray[2]).toBe(0n); + + expect(typedArray.fill(5n, 1, 2)).toBe(typedArray); + + expect(typedArray[0]).toBe(0n); + expect(typedArray[1]).toBe(5n); + expect(typedArray[2]).toBe(0n); + }); +});