Bladeren bron

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.
Luke 4 jaren geleden
bovenliggende
commit
bc540de0af

+ 5 - 1
Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -856,6 +856,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every)
     return Value(result);
     return Value(result);
 }
 }
 
 
+// 23.1.3.28 Array.prototype.splice, https://tc39.es/ecma262#sec-array.prototype.splice
 JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
 JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
 {
 {
     auto* this_object = vm.this_value(global_object).to_object(global_object);
     auto* this_object = vm.this_value(global_object).to_object(global_object);
@@ -898,7 +899,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
         return {};
         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) {
     for (size_t i = 0; i < actual_delete_count; ++i) {
         auto value = this_object->get(actual_start + i);
         auto value = this_object->get(actual_start + i);

+ 15 - 0
Userland/Libraries/LibJS/Tests/builtins/Array/Array.prototype.splice.js

@@ -47,3 +47,18 @@ test("basic functionality", () => {
     expect(array).toEqual([]);
     expect(array).toEqual([]);
     expect(removed).toEqual(["foo", "bar", "baz"]);
     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");
+});