浏览代码

LibJS: Make Array.prototype.pop() generic

Linus Groh 5 年之前
父节点
当前提交
e9ee06b19e
共有 2 个文件被更改,包括 34 次插入4 次删除
  1. 21 4
      Libraries/LibJS/Runtime/ArrayPrototype.cpp
  2. 13 0
      Libraries/LibJS/Tests/Array.prototype-generic-functions.js

+ 21 - 4
Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -205,12 +205,29 @@ Value ArrayPrototype::unshift(Interpreter& interpreter)
 
 
 Value ArrayPrototype::pop(Interpreter& interpreter)
 Value ArrayPrototype::pop(Interpreter& interpreter)
 {
 {
-    auto* array = array_from(interpreter);
-    if (!array)
+    auto* this_object = interpreter.this_value().to_object(interpreter);
+    if (!this_object)
         return {};
         return {};
-    if (array->elements().is_empty())
+    if (this_object->is_array()) {
+        auto* array = static_cast<Array*>(this_object);
+        if (array->elements().is_empty())
+            return js_undefined();
+        return array->elements().take_last().value_or(js_undefined());
+    }
+    auto length = get_length(interpreter, *this_object);
+    if (length == 0) {
+        this_object->put("length", Value(0));
         return js_undefined();
         return js_undefined();
-    return array->elements().take_last().value_or(js_undefined());
+    }
+    auto index = length - 1;
+    auto element = this_object->get_by_index(index).value_or(js_undefined());
+    if (interpreter.exception())
+        return {};
+    this_object->delete_property(PropertyName(index));
+    this_object->put("length", Value((i32)index));
+    if (interpreter.exception())
+        return {};
+    return element;
 }
 }
 
 
 Value ArrayPrototype::shift(Interpreter& interpreter)
 Value ArrayPrototype::shift(Interpreter& interpreter)

+ 13 - 0
Libraries/LibJS/Tests/Array.prototype-generic-functions.js

@@ -12,6 +12,19 @@ try {
         assert(o[0] === "foo");
         assert(o[0] === "foo");
         assert(o[1] === "bar");
         assert(o[1] === "bar");
         assert(o[2] === "baz");
         assert(o[2] === "baz");
+
+        assert(Array.prototype.pop.call(o) === "baz");
+        assert(o.length === 2);
+        assert(Array.prototype.pop.call(o) === "bar");
+        assert(o.length === 1);
+        assert(Array.prototype.pop.call(o) === "foo");
+        assert(o.length === 0);
+        assert(Array.prototype.pop.call(o) === undefined);
+        assert(o.length === 0);
+
+        o.length = length;
+        assert(Array.prototype.pop.call(o) === undefined);
+        assert(o.length === 0);
     });
     });
 
 
     const o = { length: 5, 0: "foo", 1: "bar", 3: "baz" };
     const o = { length: 5, 0: "foo", 1: "bar", 3: "baz" };