mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:07:36 +00:00
LibJS: Use ThrowCompletionOr in create_list_from_array_like()
Also add spec step comments to it while we're here.
This commit is contained in:
parent
568296d0cc
commit
c4c40f4cf3
5 changed files with 42 additions and 29 deletions
|
@ -52,31 +52,47 @@ size_t length_of_array_like(GlobalObject& global_object, Object const& object)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
|
// 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
|
||||||
MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value value, Function<void(Value)> check_value)
|
ThrowCompletionOr<MarkedValueList> create_list_from_array_like(GlobalObject& global_object, Value value, Function<ThrowCompletionOr<void>(Value)> check_value)
|
||||||
{
|
{
|
||||||
auto& vm = global_object.vm();
|
auto& vm = global_object.vm();
|
||||||
auto& heap = global_object.heap();
|
auto& heap = global_object.heap();
|
||||||
if (!value.is_object()) {
|
|
||||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
|
// 1. If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object ».
|
||||||
return MarkedValueList { heap };
|
|
||||||
}
|
// 2. If Type(obj) is not Object, throw a TypeError exception.
|
||||||
|
if (!value.is_object())
|
||||||
|
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
|
||||||
|
|
||||||
auto& array_like = value.as_object();
|
auto& array_like = value.as_object();
|
||||||
|
|
||||||
|
// 3. Let len be ? LengthOfArrayLike(obj).
|
||||||
auto length = length_of_array_like(global_object, array_like);
|
auto length = length_of_array_like(global_object, array_like);
|
||||||
if (vm.exception())
|
if (auto* exception = vm.exception())
|
||||||
return MarkedValueList { heap };
|
return throw_completion(exception->value());
|
||||||
|
|
||||||
|
// 4. Let list be a new empty List.
|
||||||
auto list = MarkedValueList { heap };
|
auto list = MarkedValueList { heap };
|
||||||
|
|
||||||
|
// 5. Let index be 0.
|
||||||
|
// 6. Repeat, while index < len,
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
|
// a. Let indexName be ! ToString(𝔽(index)).
|
||||||
auto index_name = String::number(i);
|
auto index_name = String::number(i);
|
||||||
|
|
||||||
|
// b. Let next be ? Get(obj, indexName).
|
||||||
auto next = array_like.get(index_name);
|
auto next = array_like.get(index_name);
|
||||||
if (vm.exception())
|
if (auto* exception = vm.exception())
|
||||||
return MarkedValueList { heap };
|
return throw_completion(exception->value());
|
||||||
if (check_value) {
|
|
||||||
check_value(next);
|
// c. If Type(next) is not an element of elementTypes, throw a TypeError exception.
|
||||||
if (vm.exception())
|
if (check_value)
|
||||||
return MarkedValueList { heap };
|
TRY(check_value(next));
|
||||||
}
|
|
||||||
|
// d. Append next as the last element of list.
|
||||||
list.append(next);
|
list.append(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 7. Return list.
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ Object* get_super_constructor(VM&);
|
||||||
Reference make_super_property_reference(GlobalObject&, Value actual_this, StringOrSymbol const& property_key, bool strict);
|
Reference make_super_property_reference(GlobalObject&, Value actual_this, StringOrSymbol const& property_key, bool strict);
|
||||||
ThrowCompletionOr<Value> require_object_coercible(GlobalObject&, Value);
|
ThrowCompletionOr<Value> require_object_coercible(GlobalObject&, Value);
|
||||||
size_t length_of_array_like(GlobalObject&, Object const&);
|
size_t length_of_array_like(GlobalObject&, Object const&);
|
||||||
MarkedValueList create_list_from_array_like(GlobalObject&, Value, Function<void(Value)> = {});
|
ThrowCompletionOr<MarkedValueList> create_list_from_array_like(GlobalObject&, Value, Function<ThrowCompletionOr<void>(Value)> = {});
|
||||||
FunctionObject* species_constructor(GlobalObject&, Object const&, FunctionObject& default_constructor);
|
FunctionObject* species_constructor(GlobalObject&, Object const&, FunctionObject& default_constructor);
|
||||||
Realm* get_function_realm(GlobalObject&, FunctionObject const&);
|
Realm* get_function_realm(GlobalObject&, FunctionObject const&);
|
||||||
bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
|
bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
|
||||||
|
|
|
@ -57,9 +57,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply)
|
||||||
auto arg_array = vm.argument(1);
|
auto arg_array = vm.argument(1);
|
||||||
if (arg_array.is_nullish())
|
if (arg_array.is_nullish())
|
||||||
return vm.call(function, this_arg);
|
return vm.call(function, this_arg);
|
||||||
auto arguments = create_list_from_array_like(global_object, arg_array);
|
auto arguments = TRY_OR_DISCARD(create_list_from_array_like(global_object, arg_array));
|
||||||
if (vm.exception())
|
|
||||||
return {};
|
|
||||||
return vm.call(function, this_arg, move(arguments));
|
return vm.call(function, this_arg, move(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -817,16 +817,19 @@ MarkedValueList ProxyObject::internal_own_property_keys() const
|
||||||
|
|
||||||
// 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, « String, Symbol »).
|
// 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, « String, Symbol »).
|
||||||
HashTable<StringOrSymbol> unique_keys;
|
HashTable<StringOrSymbol> unique_keys;
|
||||||
auto trap_result = create_list_from_array_like(global_object, trap_result_array, [&](auto value) {
|
auto throw_completion_or_trap_result = create_list_from_array_like(global_object, trap_result_array, [&](auto value) -> ThrowCompletionOr<void> {
|
||||||
auto& vm = global_object.vm();
|
auto& vm = global_object.vm();
|
||||||
if (!value.is_string() && !value.is_symbol()) {
|
if (!value.is_string() && !value.is_symbol())
|
||||||
vm.throw_exception<TypeError>(global_object, ErrorType::ProxyOwnPropertyKeysNotStringOrSymbol);
|
return vm.throw_completion<TypeError>(global_object, ErrorType::ProxyOwnPropertyKeysNotStringOrSymbol);
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto property_key = value.to_property_key(global_object);
|
auto property_key = value.to_property_key(global_object);
|
||||||
VERIFY(!vm.exception());
|
VERIFY(!vm.exception());
|
||||||
unique_keys.set(property_key, AK::HashSetExistingEntryBehavior::Keep);
|
unique_keys.set(property_key, AK::HashSetExistingEntryBehavior::Keep);
|
||||||
|
return {};
|
||||||
});
|
});
|
||||||
|
// TODO: This becomes a lot nicer once this function returns a ThrowCompletionOr as well.
|
||||||
|
if (throw_completion_or_trap_result.is_throw_completion())
|
||||||
|
return MarkedValueList { heap() };
|
||||||
|
auto trap_result = throw_completion_or_trap_result.release_value();
|
||||||
|
|
||||||
// 9. If trapResult contains any duplicate entries, throw a TypeError exception.
|
// 9. If trapResult contains any duplicate entries, throw a TypeError exception.
|
||||||
if (unique_keys.size() != trap_result.size()) {
|
if (unique_keys.size() != trap_result.size()) {
|
||||||
|
|
|
@ -61,9 +61,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::apply)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Let args be ? CreateListFromArrayLike(argumentsList).
|
// 2. Let args be ? CreateListFromArrayLike(argumentsList).
|
||||||
auto args = create_list_from_array_like(global_object, arguments_list);
|
auto args = TRY_OR_DISCARD(create_list_from_array_like(global_object, arguments_list));
|
||||||
if (vm.exception())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
// 3. Perform PrepareForTailCall().
|
// 3. Perform PrepareForTailCall().
|
||||||
// 4. Return ? Call(target, thisArgument, args).
|
// 4. Return ? Call(target, thisArgument, args).
|
||||||
|
@ -94,9 +92,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::construct)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Let args be ? CreateListFromArrayLike(argumentsList).
|
// 4. Let args be ? CreateListFromArrayLike(argumentsList).
|
||||||
auto args = create_list_from_array_like(global_object, arguments_list);
|
auto args = TRY_OR_DISCARD(create_list_from_array_like(global_object, arguments_list));
|
||||||
if (vm.exception())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
// 5. Return ? Construct(target, args, newTarget).
|
// 5. Return ? Construct(target, args, newTarget).
|
||||||
return vm.construct(target.as_function(), new_target.as_function(), move(args));
|
return vm.construct(target.as_function(), new_target.as_function(), move(args));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue