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

LibJS: Bring FlattenIntoArray closer to the specification

This fixes the incorrect exception order and missing exception checks
that were caused by the implementation not conforming exactly to the
specification.
This commit is contained in:
Idan Horowitz 2021-06-18 22:35:53 +03:00 committed by Linus Groh
parent 597cf88c08
commit 271eeadf25

View file

@ -1303,12 +1303,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::keys)
}
// 23.1.3.10.1 FlattenIntoArray ( target, source, sourceLen, start, depth [ , mapperFunction [ , thisArg ] ] ), https://tc39.es/ecma262/#sec-flattenintoarray
static size_t flatten_into_array(VM& vm, GlobalObject& global_object, Array& new_array, Object& array, size_t target_index, double depth, Function* mapper_func = {}, Value this_arg = {})
static size_t flatten_into_array(GlobalObject& global_object, Object& new_array, Object& array, size_t array_length, size_t target_index, double depth, Function* mapper_func = {}, Value this_arg = {})
{
VERIFY(!mapper_func || (!this_arg.is_empty() && depth == 1));
auto array_length = length_of_array_like(global_object, array);
if (vm.exception())
return {};
auto& vm = global_object.vm();
for (size_t j = 0; j < array_length; ++j) {
auto value_exists = array.has_property(j);
@ -1328,20 +1326,25 @@ static size_t flatten_into_array(VM& vm, GlobalObject& global_object, Array& new
}
if (depth > 0 && value.is_array(global_object)) {
target_index = flatten_into_array(vm, global_object, new_array, value.as_array(), target_index, depth - 1);
auto length = length_of_array_like(global_object, value.as_array());
if (vm.exception())
return {};
target_index = flatten_into_array(global_object, new_array, value.as_array(), length, target_index, depth - 1);
if (vm.exception())
return {};
continue;
}
if (target_index >= MAX_ARRAY_LIKE_INDEX) {
vm.throw_exception<TypeError>(global_object, ErrorType::InvalidIndex);
return {};
}
new_array.put(target_index, value);
if (vm.exception())
return {};
if (!value.is_empty()) {
new_array.put(target_index, value);
if (vm.exception())
return {};
++target_index;
}
++target_index;
}
return target_index;
}
@ -1353,20 +1356,21 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::flat)
if (!this_object)
return {};
auto* new_array = Array::create(global_object);
auto length = length_of_array_like(global_object, *this_object);
if (vm.exception())
return {};
double depth = 1;
if (vm.argument_count() > 0) {
auto depth_argument = vm.argument(0);
if (!depth_argument.is_undefined()) {
auto depth_num = depth_argument.to_integer_or_infinity(global_object);
if (vm.exception())
return {};
depth = max(depth_num, 0.0);
}
if (!vm.argument(0).is_undefined()) {
auto depth_num = vm.argument(0).to_integer_or_infinity(global_object);
if (vm.exception())
return {};
depth = max(depth_num, 0.0);
}
flatten_into_array(vm, global_object, *new_array, *this_object, 0, depth);
auto* new_array = Array::create(global_object);
flatten_into_array(global_object, *new_array, *this_object, length, 0, depth);
if (vm.exception())
return {};
return new_array;
@ -1379,6 +1383,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::flat_map)
if (!this_object)
return {};
auto length = length_of_array_like(global_object, *this_object);
if (vm.exception())
return {};
auto* mapper_function = callback_from_args(global_object, "flatMap");
if (!mapper_function)
return {};
@ -1388,7 +1396,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::flat_map)
// FIXME: Use ArraySpeciesCreate.
auto new_array = Array::create(global_object);
flatten_into_array(vm, global_object, *new_array, *this_object, 0, 1, mapper_function, this_argument);
flatten_into_array(global_object, *new_array, *this_object, length, 0, 1, mapper_function, this_argument);
if (vm.exception())
return {};