1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 00:47:45 +00:00

LibJS: Make Array.prototype.reverse generic

This commit is contained in:
davidot 2021-06-12 23:20:01 +02:00 committed by Linus Groh
parent 516f6240e8
commit 2ef9df989f
2 changed files with 64 additions and 13 deletions

View file

@ -680,26 +680,62 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
// 23.1.3.23 Array.prototype.reverse ( ), https://tc39.es/ecma262/#sec-array.prototype.reverse // 23.1.3.23 Array.prototype.reverse ( ), https://tc39.es/ecma262/#sec-array.prototype.reverse
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reverse) JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reverse)
{ {
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 {};
auto length = length_of_array_like(global_object, *this_object);
if (vm.exception())
return {}; return {};
if (array->indexed_properties().is_empty()) auto middle = length / 2;
return array; for (size_t lower = 0; lower < middle; ++lower) {
auto upper = length - lower - 1;
MarkedValueList array_reverse(vm.heap()); auto lower_exists = this_object->has_property(lower);
auto size = array->indexed_properties().array_like_size(); if (vm.exception())
array_reverse.ensure_capacity(size); return {};
Value lower_value;
for (ssize_t i = size - 1; i >= 0; --i) { if (lower_exists) {
array_reverse.append(array->get(i)); lower_value = this_object->get(lower).value_or(js_undefined());
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
array->set_indexed_property_elements(move(array_reverse)); auto upper_exists = this_object->has_property(upper);
if (vm.exception())
return {};
Value upper_value;
if (upper_exists) {
upper_value = this_object->get(upper).value_or(js_undefined());
if (vm.exception())
return {};
}
return array; if (lower_exists && upper_exists) {
this_object->put(lower, upper_value);
if (vm.exception())
return {};
this_object->put(upper, lower_value);
if (vm.exception())
return {};
} else if (!lower_exists && upper_exists) {
this_object->put(lower, upper_value);
if (vm.exception())
return {};
this_object->delete_property(upper);
if (vm.exception())
return {};
} else if (lower_exists && !upper_exists) {
this_object->delete_property(lower);
if (vm.exception())
return {};
this_object->put(upper, lower_value);
if (vm.exception())
return {};
}
}
return this_object;
} }
static void array_merge_sort(VM& vm, GlobalObject& global_object, Function* compare_func, MarkedValueList& arr_to_sort) static void array_merge_sort(VM& vm, GlobalObject& global_object, Function* compare_func, MarkedValueList& arr_to_sort)

View file

@ -188,4 +188,19 @@ describe("ability to work with generic non-array objects", () => {
); );
expect(visited).toEqual(["baz", "bar", "foo"]); expect(visited).toEqual(["baz", "bar", "foo"]);
}); });
test("reverse", () => {
expect(Array.prototype.reverse.call(o)).toEqual({
length: 5,
4: "foo",
3: "bar",
1: "baz",
});
expect(Array.prototype.reverse.call({})).toEqual({});
expect(Array.prototype.reverse.call({ length: 10 })).toEqual({ length: 10 });
expect(Array.prototype.reverse.call({ length: 1, 0: "foo" })).toEqual({
length: 1,
0: "foo",
});
});
}); });