mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 03:47:35 +00:00
LibJS: Make Array.prototype.unshift generic
This commit is contained in:
parent
7c1e2adf8a
commit
d723c01af7
2 changed files with 65 additions and 5 deletions
|
@ -203,12 +203,52 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::push)
|
||||||
// 23.1.3.31 Array.prototype.unshift ( ...items ), https://tc39.es/ecma262/#sec-array.prototype.unshift
|
// 23.1.3.31 Array.prototype.unshift ( ...items ), https://tc39.es/ecma262/#sec-array.prototype.unshift
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::unshift)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::unshift)
|
||||||
{
|
{
|
||||||
auto* array = Array::typed_this(vm, global_object);
|
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||||
if (!array)
|
if (!this_object)
|
||||||
return {};
|
return {};
|
||||||
for (size_t i = 0; i < vm.argument_count(); ++i)
|
auto length = length_of_array_like(global_object, *this_object);
|
||||||
array->indexed_properties().insert(i, vm.argument(i));
|
if (vm.exception())
|
||||||
return Value(static_cast<i32>(array->indexed_properties().array_like_size()));
|
return {};
|
||||||
|
auto arg_count = vm.argument_count();
|
||||||
|
size_t new_length = length + arg_count;
|
||||||
|
if (arg_count > 0) {
|
||||||
|
if (new_length > MAX_ARRAY_LIKE_INDEX) {
|
||||||
|
vm.throw_exception<TypeError>(global_object, ErrorType::ArrayMaxSize);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t k = length; k > 0; --k) {
|
||||||
|
auto from = k - 1;
|
||||||
|
auto to = k + arg_count - 1;
|
||||||
|
|
||||||
|
bool from_present = this_object->has_property(from);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
if (from_present) {
|
||||||
|
auto from_value = this_object->get(from).value_or(js_undefined());
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
this_object->put(to, from_value);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
} else {
|
||||||
|
this_object->delete_property(to);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < arg_count; j++) {
|
||||||
|
this_object->put(j, vm.argument(j));
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this_object->put(vm.names.length, Value(new_length));
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
return Value(new_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.1.3.19 Array.prototype.pop ( ), https://tc39.es/ecma262/#sec-array.prototype.pop
|
// 23.1.3.19 Array.prototype.pop ( ), https://tc39.es/ecma262/#sec-array.prototype.pop
|
||||||
|
|
|
@ -110,6 +110,26 @@ describe("ability to work with generic non-array objects", () => {
|
||||||
expect(o).toEqual({ length: 4, 0: "b", 2: "c" });
|
expect(o).toEqual({ length: 4, 0: "b", 2: "c" });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("unshift", () => {
|
||||||
|
{
|
||||||
|
const o = { length: 5, 0: "a", 1: "b", 3: "c" };
|
||||||
|
const front = "z";
|
||||||
|
Array.prototype.unshift.call(o, front);
|
||||||
|
expect(o[0]).toEqual(front);
|
||||||
|
expect(o[1]).toEqual("a");
|
||||||
|
expect(o.length).toEqual(6);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const o = { length: 5, 0: "a", 1: "b", 3: "c" };
|
||||||
|
const front = "z";
|
||||||
|
Array.prototype.unshift.call(o, front, front);
|
||||||
|
expect(o[0]).toEqual(front);
|
||||||
|
expect(o[1]).toEqual(front);
|
||||||
|
expect(o[2]).toEqual("a");
|
||||||
|
expect(o.length).toEqual(7);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const o = { length: 5, 0: "foo", 1: "bar", 3: "baz" };
|
const o = { length: 5, 0: "foo", 1: "bar", 3: "baz" };
|
||||||
|
|
||||||
test("every", () => {
|
test("every", () => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue