diff options
author | Linus Groh <mail@linusgroh.de> | 2021-09-15 21:05:05 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-09-15 23:46:53 +0100 |
commit | 3d43eb0774c462eb4f0a570a1bd598d62f55c199 (patch) | |
tree | f1298cd4e6ec09f19ed569481119b6761e94682f | |
parent | c4c40f4cf3cc1c98682c248f68b7233be4f1edc2 (diff) | |
download | serenity-3d43eb0774c462eb4f0a570a1bd598d62f55c199.zip |
LibJS: Use ThrowCompletionOr in species_constructor()
Also add spec step comments to it as well as a missing exception check
while we're here.
6 files changed, 29 insertions, 28 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 57e837c819..b163f15118 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -97,25 +97,38 @@ ThrowCompletionOr<MarkedValueList> create_list_from_array_like(GlobalObject& glo } // 7.3.22 SpeciesConstructor ( O, defaultConstructor ), https://tc39.es/ecma262/#sec-speciesconstructor -FunctionObject* species_constructor(GlobalObject& global_object, Object const& object, FunctionObject& default_constructor) +ThrowCompletionOr<FunctionObject*> species_constructor(GlobalObject& global_object, Object const& object, FunctionObject& default_constructor) { auto& vm = global_object.vm(); + + // 1. Let C be ? Get(O, "constructor"). auto constructor = object.get(vm.names.constructor); - if (vm.exception()) - return nullptr; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + + // 2. If C is undefined, return defaultConstructor. if (constructor.is_undefined()) return &default_constructor; - if (!constructor.is_object()) { - vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects()); - return nullptr; - } + + // 3. If Type(C) is not Object, throw a TypeError exception. + if (!constructor.is_object()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects()); + + // 4. Let S be ? Get(C, @@species). auto species = constructor.as_object().get(*vm.well_known_symbol_species()); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + + // 5. If S is either undefined or null, return defaultConstructor. if (species.is_nullish()) return &default_constructor; + + // 6. If IsConstructor(S) is true, return S. if (species.is_constructor()) return &species.as_function(); - vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects()); - return nullptr; + + // 7. Throw a TypeError exception. + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects()); } // 7.3.24 GetFunctionRealm ( obj ), https://tc39.es/ecma262/#sec-getfunctionrealm diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index acdae60347..51c6541560 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -22,7 +22,7 @@ Reference make_super_property_reference(GlobalObject&, Value actual_this, String ThrowCompletionOr<Value> require_object_coercible(GlobalObject&, Value); size_t length_of_array_like(GlobalObject&, Object const&); ThrowCompletionOr<MarkedValueList> create_list_from_array_like(GlobalObject&, Value, Function<ThrowCompletionOr<void>(Value)> = {}); -FunctionObject* species_constructor(GlobalObject&, Object const&, FunctionObject& default_constructor); +ThrowCompletionOr<FunctionObject*> species_constructor(GlobalObject&, Object const&, FunctionObject& default_constructor); Realm* get_function_realm(GlobalObject&, FunctionObject const&); bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current); bool validate_and_apply_property_descriptor(Object*, PropertyName const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current); diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp index f426754539..cf75b6cac9 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp @@ -71,9 +71,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::slice) auto new_length = max(final - first, 0.0); - auto constructor = species_constructor(global_object, *array_buffer_object, *global_object.array_buffer_constructor()); - if (vm.exception()) - return {}; + auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *array_buffer_object, *global_object.array_buffer_constructor())); MarkedValueList arguments(vm.heap()); arguments.append(Value(new_length)); diff --git a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp index 3ea98179ee..8efcb6e85e 100644 --- a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp @@ -43,9 +43,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::then) return {}; auto on_fulfilled = vm.argument(0); auto on_rejected = vm.argument(1); - auto* constructor = species_constructor(global_object, *promise, *global_object.promise_constructor()); - if (vm.exception()) - return {}; + auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *promise, *global_object.promise_constructor())); auto result_capability = new_promise_capability(global_object, constructor); if (vm.exception()) return {}; @@ -66,9 +64,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally) auto* promise = vm.this_value(global_object).to_object(global_object); if (!promise) return {}; - auto* constructor = species_constructor(global_object, *promise, *global_object.promise_constructor()); - if (vm.exception()) - return {}; + auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *promise, *global_object.promise_constructor())); Value then_finally; Value catch_finally; auto on_finally = vm.argument(0); diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp index ffd505e528..9bf56c5025 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp @@ -515,9 +515,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match_all) if (vm.exception()) return {}; - auto* constructor = species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()); - if (vm.exception()) - return {}; + auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor())); auto flags_value = regexp_object->get(vm.names.flags); if (vm.exception()) @@ -784,9 +782,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split) return {}; auto string_view = string.view(); - auto* constructor = species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()); - if (vm.exception()) - return {}; + auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor())); auto flags_object = regexp_object->get(vm.names.flags); if (vm.exception()) diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp index 5efb49a60f..f2f4d9860b 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp @@ -175,9 +175,7 @@ static TypedArrayBase* typed_array_species_create(GlobalObject& global_object, T VERIFY(typed_array_default_constructor); - auto* constructor = species_constructor(global_object, exemplar, *typed_array_default_constructor); - if (vm.exception()) - return nullptr; + auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, exemplar, *typed_array_default_constructor)); auto* result = typed_array_create(global_object, *constructor, move(arguments)); if (vm.exception()) |