diff options
Diffstat (limited to 'Userland')
3 files changed, 124 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp index 123b79447b..5ee62d2ea2 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp @@ -28,6 +28,7 @@ void TypedArrayPrototype::initialize(GlobalObject& object) define_native_function(vm.names.at, at, 1, attr); define_native_function(vm.names.every, every, 1, attr); define_native_function(vm.names.find, find, 1, attr); + define_native_function(vm.names.findIndex, find_index, 1, attr); } TypedArrayPrototype::~TypedArrayPrototype() @@ -154,6 +155,20 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find) return result; } +// 23.2.3.11 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.findindex +JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_index) +{ + auto result_index = -1; + for_each_item(vm, global_object, "findIndex", [&](auto index, auto, auto callback_result) { + if (callback_result.to_boolean()) { + result_index = index; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + return Value(result_index); +} + // 23.2.3.1 get %TypedArray%.prototype.buffer, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.buffer JS_DEFINE_NATIVE_GETTER(TypedArrayPrototype::buffer_getter) { diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h index be4c44d8b8..3763841295 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.h @@ -27,6 +27,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(at); JS_DECLARE_NATIVE_FUNCTION(every); JS_DECLARE_NATIVE_FUNCTION(find); + JS_DECLARE_NATIVE_FUNCTION(find_index); }; } diff --git a/Userland/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.findIndex.js b/Userland/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.findIndex.js new file mode 100644 index 0000000000..fa6f8db626 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.findIndex.js @@ -0,0 +1,108 @@ +const TYPED_ARRAYS = [ + Uint8Array, + Uint16Array, + Uint32Array, + Int8Array, + Int16Array, + Int32Array, + Float32Array, + Float64Array, +]; + +const BIGINT_TYPED_ARRAYS = [BigUint64Array, BigInt64Array]; + +test("length is 1", () => { + TYPED_ARRAYS.forEach(T => { + expect(T.prototype.findIndex).toHaveLength(1); + }); + + BIGINT_TYPED_ARRAYS.forEach(T => { + expect(T.prototype.findIndex).toHaveLength(1); + }); +}); + +describe("errors", () => { + function errorTests(T) { + test(`requires at least one argument (${T.name})`, () => { + expect(() => { + new T().findIndex(); + }).toThrowWithMessage( + TypeError, + "TypedArray.prototype.findIndex() requires at least one argument" + ); + }); + + test(`callback must be a function (${T.name})`, () => { + expect(() => { + new T().findIndex(undefined); + }).toThrowWithMessage(TypeError, "undefined is not a function"); + }); + } + + TYPED_ARRAYS.forEach(T => errorTests(T)); + BIGINT_TYPED_ARRAYS.forEach(T => errorTests(T)); +}); + +describe("normal behaviour", () => { + test("basic functionality", () => { + TYPED_ARRAYS.forEach(T => { + const typedArray = new T([1, 2, 3]); + + expect(typedArray.findIndex(value => value === 1)).toBe(0); + expect(typedArray.findIndex(value => value === 2)).toBe(1); + expect(typedArray.findIndex(value => value === 3)).toBe(2); + expect(typedArray.findIndex((value, index) => index === 1)).toBe(1); + expect(typedArray.findIndex(value => value == "1")).toBe(0); + expect(typedArray.findIndex(value => value === 10)).toBe(-1); + }); + + BIGINT_TYPED_ARRAYS.forEach(T => { + const typedArray = new T([1n, 2n, 3n]); + + expect(typedArray.findIndex(value => value === 1n)).toBe(0); + expect(typedArray.findIndex(value => value === 2n)).toBe(1); + expect(typedArray.findIndex(value => value === 3n)).toBe(2); + expect(typedArray.findIndex((value, index) => index === 1)).toBe(1); + expect(typedArray.findIndex(value => value == 1)).toBe(0); + expect(typedArray.findIndex(value => value == "1")).toBe(0); + expect(typedArray.findIndex(value => value === 1)).toBe(-1); + }); + }); + + test("never calls callback with empty array", () => { + function emptyTest(T) { + var callbackCalled = 0; + expect( + new T().findIndex(() => { + callbackCalled++; + }) + ).toBe(-1); + expect(callbackCalled).toBe(0); + } + + TYPED_ARRAYS.forEach(T => emptyTest(T)); + BIGINT_TYPED_ARRAYS.forEach(T => emptyTest(T)); + }); + + test("calls callback once for every item", () => { + TYPED_ARRAYS.forEach(T => { + var callbackCalled = 0; + expect( + new T([1, 2, 3]).findIndex(() => { + callbackCalled++; + }) + ).toBe(-1); + expect(callbackCalled).toBe(3); + }); + + BIGINT_TYPED_ARRAYS.forEach(T => { + var callbackCalled = 0; + expect( + new T([1n, 2n, 3n]).findIndex(() => { + callbackCalled++; + }) + ).toBe(-1); + expect(callbackCalled).toBe(3); + }); + }); +}); |