From bc540de0af35106a3adbd3671eda986d696df61c Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 10 Jun 2021 02:09:35 +0100 Subject: [PATCH] LibJS: Pass in actual_delete_count to removed array creation in splice More specifically, Array.prototype.splice. Additionally adds a missing exception check to the array creation and a link to the spec. Fixes create-non-array-invalid-len.js in the splice tests in test262. This test timed out instead of throwing an "Invalid array length" exception. --- .../Libraries/LibJS/Runtime/ArrayPrototype.cpp | 6 +++++- .../builtins/Array/Array.prototype.splice.js | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp index 94f9001c54..9e7d6dc48f 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -856,6 +856,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every) return Value(result); } +// 23.1.3.28 Array.prototype.splice, https://tc39.es/ecma262#sec-array.prototype.splice JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice) { auto* this_object = vm.this_value(global_object).to_object(global_object); @@ -898,7 +899,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice) return {}; } - auto removed_elements = Array::create(global_object); + // FIXME: Use ArraySpeciesCreate. + auto removed_elements = Array::create(global_object, actual_delete_count); + if (vm.exception()) + return {}; for (size_t i = 0; i < actual_delete_count; ++i) { auto value = this_object->get(actual_start + i); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Array/Array.prototype.splice.js b/Userland/Libraries/LibJS/Tests/builtins/Array/Array.prototype.splice.js index 245648760a..7be866f045 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Array/Array.prototype.splice.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Array/Array.prototype.splice.js @@ -47,3 +47,18 @@ test("basic functionality", () => { expect(array).toEqual([]); expect(removed).toEqual(["foo", "bar", "baz"]); }); + +// FIXME: These tests are currently skipped because an invalid array length in this case is 2**32 or above. +// The codebase currently uses size_t for lengths, which is currently the same as u32 when building for Serenity. +// This means these lengths wrap around to 0, making the test not work correctly. +test.skip("Invalid lengths", () => { + var length = Math.pow(2, 32); + + var obj = { + length: length, + }; + + expect(() => { + Array.prototype.splice.call(obj, 0); + }).toThrowWithMessage(RangeError, "Invalid array length"); +});