diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index d1c72bbb11..2d0effb398 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -331,16 +331,27 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyName const& } // 10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ), https://tc39.es/ecma262/#sec-getprototypefromconstructor -Object* get_prototype_from_constructor(GlobalObject& global_object, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)()) +ThrowCompletionOr get_prototype_from_constructor(GlobalObject& global_object, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)()) { auto& vm = global_object.vm(); + + // 1. Assert: intrinsicDefaultProto is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object. + + // 2. Let proto be ? Get(constructor, "prototype"). auto prototype = constructor.get(vm.names.prototype); - if (vm.exception()) - return nullptr; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + + // 3. If Type(proto) is not Object, then if (!prototype.is_object()) { - auto* realm = TRY_OR_DISCARD(get_function_realm(global_object, constructor)); + // a. Let realm be ? GetFunctionRealm(constructor). + auto* realm = TRY(get_function_realm(global_object, constructor)); + + // b. Set proto to realm's intrinsic object named intrinsicDefaultProto. prototype = (realm->global_object().*intrinsic_default_prototype)(); } + + // 4. Return proto. return &prototype.as_object(); } diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index f96f8600aa..ec30839a69 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -26,7 +26,7 @@ ThrowCompletionOr species_constructor(GlobalObject&, Object con ThrowCompletionOr get_function_realm(GlobalObject&, FunctionObject const&); bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional const& current); bool validate_and_apply_property_descriptor(Object*, PropertyName const&, bool extensible, PropertyDescriptor const&, Optional const& current); -Object* get_prototype_from_constructor(GlobalObject&, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)()); +ThrowCompletionOr get_prototype_from_constructor(GlobalObject&, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)()); Object* create_unmapped_arguments_object(GlobalObject&, Span arguments); Object* create_mapped_arguments_object(GlobalObject&, FunctionObject&, Vector const&, Span arguments, Environment&); Value canonical_numeric_index_string(GlobalObject&, PropertyName const&); @@ -46,10 +46,7 @@ Value perform_eval(Value, GlobalObject&, CallerMode, EvalMode); template T* ordinary_create_from_constructor(GlobalObject& global_object, FunctionObject const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)(), Args&&... args) { - auto& vm = global_object.vm(); - auto* prototype = get_prototype_from_constructor(global_object, constructor, intrinsic_default_prototype); - if (vm.exception()) - return nullptr; + auto* prototype = TRY_OR_DISCARD(get_prototype_from_constructor(global_object, constructor, intrinsic_default_prototype)); return global_object.heap().allocate(global_object, forward(args)..., *prototype); } diff --git a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp index 3b8672ff4d..dc381a93ab 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -55,9 +55,7 @@ Value ArrayConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); - auto* proto = get_prototype_from_constructor(global_object(), new_target, &GlobalObject::array_prototype); - if (vm.exception()) - return {}; + auto* proto = TRY_OR_DISCARD(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::array_prototype)); if (vm.argument_count() == 0) return Array::create(global_object(), 0, proto); diff --git a/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp b/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp index 1273bb92ea..908e55e9b8 100644 --- a/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp @@ -67,9 +67,7 @@ Value StringConstructor::construct(FunctionObject& new_target) primitive_string = vm.argument(0).to_primitive_string(global_object()); if (!primitive_string) return {}; - auto* prototype = get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype); - if (vm.exception()) - return {}; + auto* prototype = TRY_OR_DISCARD(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype)); return StringObject::create(global_object(), *primitive_string, *prototype); } diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp index 4d3bc4ffb4..c19c5f711b 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp @@ -270,10 +270,8 @@ void TypedArrayBase::visit_edges(Visitor& visitor) #define JS_DEFINE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ ClassName* ClassName::create(GlobalObject& global_object, u32 length, FunctionObject& new_target) \ { \ - auto& vm = global_object.vm(); \ - auto* prototype = get_prototype_from_constructor(global_object, new_target, &GlobalObject::snake_name##_prototype); \ - if (vm.exception()) \ - return {}; \ + auto* prototype = TRY_OR_DISCARD(get_prototype_from_constructor( \ + global_object, new_target, &GlobalObject::snake_name##_prototype)); \ return global_object.heap().allocate(global_object, length, *prototype); \ } \ \