Jelajahi Sumber

LibJS: Remove fast array paths in ArrayPrototype::{pop, push}

Unfortunately this fast path leads to problems if Array.prototype is
changed. We probably need to find out some way to optimize these methods
by detecting changes to the prototype or other mechanisms.
davidot 4 tahun lalu
induk
melakukan
7310713d11

+ 0 - 16
Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -348,14 +348,6 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::push)
     auto* this_object = vm.this_value(global_object).to_object(global_object);
     if (!this_object)
         return {};
-    if (is<Array>(this_object)) {
-        auto* array = static_cast<Array*>(this_object);
-        if (array->length_is_writable()) {
-            for (size_t i = 0; i < vm.argument_count(); ++i)
-                array->indexed_properties().append(vm.argument(i));
-            return Value(static_cast<i32>(array->indexed_properties().array_like_size()));
-        }
-    }
     auto length = length_of_array_like(global_object, *this_object);
     if (vm.exception())
         return {};
@@ -434,14 +426,6 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
     auto* this_object = vm.this_value(global_object).to_object(global_object);
     if (!this_object)
         return {};
-    if (is<Array>(this_object)) {
-        auto* array = static_cast<Array*>(this_object);
-        if (array->length_is_writable()) {
-            if (array->indexed_properties().is_empty())
-                return js_undefined();
-            return array->indexed_properties().take_last(array).value.value_or(js_undefined());
-        }
-    }
     auto length = length_of_array_like(global_object, *this_object);
     if (vm.exception())
         return {};

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

@@ -26,4 +26,19 @@ describe("normal behavior", () => {
         expect(a.pop()).toBeUndefined();
         expect(a).toEqual([]);
     });
+
+    test("array with prototype indexed value", () => {
+        Array.prototype[1] = 1;
+
+        var a = [0];
+        a.length = 2;
+        expect(a[1]).toEqual(1);
+        expect(a.pop()).toEqual(1);
+
+        expect(a.length).toEqual(1);
+        expect(a).toEqual([0]);
+        expect(a[1]).toEqual(1);
+
+        delete Array.prototype[1];
+    });
 });