From 5148150e1ccdce78c84d848dd873bc31b247c781 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Tue, 28 Sep 2021 23:30:17 +0100 Subject: [PATCH] LibJS: Convert internal_get_prototype_of() to ThrowCompletionOr --- .../LibWeb/WrapperGenerator.cpp | 8 +--- Userland/Libraries/LibJS/AST.cpp | 4 +- .../LibJS/Runtime/AbstractOperations.cpp | 11 +++++- .../LibJS/Runtime/FunctionEnvironment.cpp | 2 +- Userland/Libraries/LibJS/Runtime/Object.cpp | 20 +++------- Userland/Libraries/LibJS/Runtime/Object.h | 3 +- .../LibJS/Runtime/ObjectConstructor.cpp | 2 +- .../LibJS/Runtime/ObjectPrototype.cpp | 15 ++------ .../Libraries/LibJS/Runtime/ProxyObject.cpp | 38 +++++++------------ .../Libraries/LibJS/Runtime/ProxyObject.h | 3 +- .../Libraries/LibJS/Runtime/ReflectObject.cpp | 2 +- Userland/Libraries/LibJS/Runtime/Value.cpp | 4 +- .../WebContent/ConsoleGlobalObject.cpp | 3 +- .../Services/WebContent/ConsoleGlobalObject.h | 3 +- 14 files changed, 48 insertions(+), 70 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp index 21ddf8fd0e2..61b0c9a04f6 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp @@ -1654,9 +1654,7 @@ bool @class_name@::is_named_property_exposed_on_object(JS::PropertyName const& p scoped_generator.append(R"~~~( // NOTE: Step 3 is not here as the interface doesn't have the LegacyOverrideBuiltIns extended attribute. // 4. Let prototype be O.[[GetPrototypeOf]](). - auto* prototype = internal_get_prototype_of(); - if (vm.exception()) - return {}; + auto* prototype = TRY_OR_DISCARD(internal_get_prototype_of()); // 5. While prototype is not null: while (prototype) { @@ -1670,9 +1668,7 @@ bool @class_name@::is_named_property_exposed_on_object(JS::PropertyName const& p return false; // 2. Set prototype to prototype.[[GetPrototypeOf]](). - prototype = prototype->internal_get_prototype_of(); - if (vm.exception()) - return {}; + prototype = TRY_OR_DISCARD(prototype->internal_get_prototype_of()); } // 6. Return true. diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index b69a2863703..c49f6cc5c35 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -580,9 +580,7 @@ Value ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_obj } } } - object = object->internal_get_prototype_of(); - if (interpreter.exception()) - return {}; + object = TRY_OR_DISCARD(object->internal_get_prototype_of()); } return last_value; } diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 332f76d6e61..3b42b4cf57d 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -383,9 +383,18 @@ Environment& get_this_environment(VM& vm) // 13.3.7.2 GetSuperConstructor ( ), https://tc39.es/ecma262/#sec-getsuperconstructor Object* get_super_constructor(VM& vm) { + // 1. Let envRec be GetThisEnvironment(). auto& env = get_this_environment(vm); + + // 2. Assert: envRec is a function Environment Record. + // 3. Let activeFunction be envRec.[[FunctionObject]]. + // 4. Assert: activeFunction is an ECMAScript function object. auto& active_function = verify_cast(env).function_object(); - auto* super_constructor = active_function.internal_get_prototype_of(); + + // 5. Let superConstructor be ! activeFunction.[[GetPrototypeOf]](). + auto* super_constructor = active_function.internal_get_prototype_of().release_value(); + + // 6. Return superConstructor. return super_constructor; } diff --git a/Userland/Libraries/LibJS/Runtime/FunctionEnvironment.cpp b/Userland/Libraries/LibJS/Runtime/FunctionEnvironment.cpp index 9aec5f431ae..1bb8e7252fd 100644 --- a/Userland/Libraries/LibJS/Runtime/FunctionEnvironment.cpp +++ b/Userland/Libraries/LibJS/Runtime/FunctionEnvironment.cpp @@ -35,7 +35,7 @@ Value FunctionEnvironment::get_super_base() const auto home_object = m_function_object->home_object(); if (!home_object) return js_undefined(); - return home_object->internal_get_prototype_of(); + return TRY_OR_DISCARD(home_object->internal_get_prototype_of()); } // 9.1.1.3.2 HasThisBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-hasthisbinding diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index 35bc15fe6c7..b05ad6ba132 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -489,7 +489,7 @@ MarkedValueList Object::enumerable_own_property_names(PropertyKind kind) const // 10.1 Ordinary Object Internal Methods and Internal Slots, https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots // 10.1.1 [[GetPrototypeOf]] ( ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof -Object* Object::internal_get_prototype_of() const +ThrowCompletionOr Object::internal_get_prototype_of() const { // 1. Return O.[[Prototype]]. return const_cast(prototype()); @@ -645,9 +645,7 @@ bool Object::internal_has_property(PropertyName const& property_name) const return true; // 4. Let parent be ? O.[[GetPrototypeOf]](). - auto parent = internal_get_prototype_of(); - if (vm.exception()) - return {}; + auto* parent = TRY_OR_DISCARD(internal_get_prototype_of()); // 5. If parent is not null, then if (parent) { @@ -676,9 +674,7 @@ Value Object::internal_get(PropertyName const& property_name, Value receiver) co // 3. If desc is undefined, then if (!descriptor.has_value()) { // a. Let parent be ? O.[[GetPrototypeOf]](). - auto parent = internal_get_prototype_of(); - if (vm.exception()) - return {}; + auto* parent = TRY_OR_DISCARD(internal_get_prototype_of()); // b. If parent is null, return undefined. if (!parent) @@ -736,9 +732,7 @@ bool Object::ordinary_set_with_own_descriptor(PropertyName const& property_name, // 2. If ownDesc is undefined, then if (!own_descriptor.has_value()) { // a. Let parent be ? O.[[GetPrototypeOf]](). - auto parent = internal_get_prototype_of(); - if (vm.exception()) - return {}; + auto* parent = TRY_OR_DISCARD(internal_get_prototype_of()); // b. If parent is not null, then if (parent) { @@ -882,14 +876,10 @@ MarkedValueList Object::internal_own_property_keys() const // 10.4.7.2 SetImmutablePrototype ( O, V ), https://tc39.es/ecma262/#sec-set-immutable-prototype bool Object::set_immutable_prototype(Object* prototype) { - auto& vm = this->vm(); - // 1. Assert: Either Type(V) is Object or Type(V) is Null. // 2. Let current be ? O.[[GetPrototypeOf]](). - auto* current = internal_get_prototype_of(); - if (vm.exception()) - return {}; + auto* current = TRY_OR_DISCARD(internal_get_prototype_of()); // 3. If SameValue(V, current) is true, return true. if (prototype == current) diff --git a/Userland/Libraries/LibJS/Runtime/Object.h b/Userland/Libraries/LibJS/Runtime/Object.h index eb934142113..d46ca392b96 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.h +++ b/Userland/Libraries/LibJS/Runtime/Object.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,7 @@ public: // 10.1 Ordinary Object Internal Methods and Internal Slots, https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots - virtual Object* internal_get_prototype_of() const; + virtual ThrowCompletionOr internal_get_prototype_of() const; virtual bool internal_set_prototype_of(Object* prototype); virtual bool internal_is_extensible() const; virtual bool internal_prevent_extensions(); diff --git a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp index 96fc7b3bca8..5c489a3ec43 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -140,7 +140,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_prototype_of) return {}; // 2. Return ? obj.[[GetPrototypeOf]](). - return object->internal_get_prototype_of(); + return TRY_OR_DISCARD(object->internal_get_prototype_of()); } // 20.1.2.21 Object.setPrototypeOf ( O, proto ), https://tc39.es/ecma262/#sec-object.setprototypeof diff --git a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp index b1547f138dd..e32f5a79205 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp @@ -187,7 +187,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::is_prototype_of) return {}; for (;;) { - object = object->internal_get_prototype_of(); + object = TRY_OR_DISCARD(object->internal_get_prototype_of()); if (!object) return Value(false); if (same_value(this_object, object)) @@ -267,9 +267,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::lookup_getter) return *desc->get ?: js_undefined(); return js_undefined(); } - object = object->internal_get_prototype_of(); - if (vm.exception()) - return {}; + object = TRY_OR_DISCARD(object->internal_get_prototype_of()); } return js_undefined(); @@ -295,9 +293,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::lookup_setter) return *desc->set ?: js_undefined(); return js_undefined(); } - object = object->internal_get_prototype_of(); - if (vm.exception()) - return {}; + object = TRY_OR_DISCARD(object->internal_get_prototype_of()); } return js_undefined(); @@ -309,10 +305,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::proto_getter) auto object = vm.this_value(global_object).to_object(global_object); if (vm.exception()) return {}; - auto proto = object->internal_get_prototype_of(); - if (vm.exception()) - return {}; - return proto; + return TRY_OR_DISCARD(object->internal_get_prototype_of()); } // B.2.2.1.2 set Object.prototype.__proto__, https://tc39.es/ecma262/#sec-set-object.prototype.__proto__ diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp index 37f0db4d5a7..8f4dae9ca06 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -45,7 +45,7 @@ static Value property_name_to_value(VM& vm, PropertyName const& name) } // 10.5.1 [[GetPrototypeOf]] ( ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof -Object* ProxyObject::internal_get_prototype_of() const +ThrowCompletionOr ProxyObject::internal_get_prototype_of() const { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -53,51 +53,43 @@ Object* ProxyObject::internal_get_prototype_of() const // 1. Let handler be O.[[ProxyHandler]]. // 2. If handler is null, throw a TypeError exception. - if (m_is_revoked) { - vm.throw_exception(global_object, ErrorType::ProxyRevoked); - return {}; - } + if (m_is_revoked) + return vm.throw_completion(global_object, ErrorType::ProxyRevoked); // 3. Assert: Type(handler) is Object. // 4. Let target be O.[[ProxyTarget]]. // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). - auto trap = TRY_OR_DISCARD(Value(&m_handler).get_method(global_object, vm.names.getPrototypeOf)); + auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.getPrototypeOf)); // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[GetPrototypeOf]](). - return m_target.internal_get_prototype_of(); + return TRY(m_target.internal_get_prototype_of()); } // 7. Let handlerProto be ? Call(trap, handler, « target »). - auto handler_proto = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target)); + auto handler_proto = TRY(vm.call(*trap, &m_handler, &m_target)); // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception. - if (!handler_proto.is_object() && !handler_proto.is_null()) { - vm.throw_exception(global_object, ErrorType::ProxyGetPrototypeOfReturn); - return {}; - } + if (!handler_proto.is_object() && !handler_proto.is_null()) + return vm.throw_completion(global_object, ErrorType::ProxyGetPrototypeOfReturn); // 9. Let extensibleTarget be ? IsExtensible(target). auto extensible_target = m_target.is_extensible(); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); // 10. If extensibleTarget is true, return handlerProto. if (extensible_target) return handler_proto.is_null() ? nullptr : &handler_proto.as_object(); // 11. Let targetProto be ? target.[[GetPrototypeOf]](). - auto target_proto = m_target.internal_get_prototype_of(); - if (vm.exception()) - return {}; + auto* target_proto = TRY(m_target.internal_get_prototype_of()); // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception. - if (!same_value(handler_proto, target_proto)) { - vm.throw_exception(global_object, ErrorType::ProxyGetPrototypeOfNonExtensible); - return {}; - } + if (!same_value(handler_proto, target_proto)) + return vm.throw_completion(global_object, ErrorType::ProxyGetPrototypeOfNonExtensible); // 13. Return handlerProto. return handler_proto.is_null() ? nullptr : &handler_proto.as_object(); @@ -147,9 +139,7 @@ bool ProxyObject::internal_set_prototype_of(Object* prototype) return true; // 12. Let targetProto be ? target.[[GetPrototypeOf]](). - auto* target_proto = m_target.internal_get_prototype_of(); - if (vm.exception()) - return {}; + auto* target_proto = TRY_OR_DISCARD(m_target.internal_get_prototype_of()); // 13. If SameValue(V, targetProto) is false, throw a TypeError exception. if (!same_value(prototype, target_proto)) { diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.h b/Userland/Libraries/LibJS/Runtime/ProxyObject.h index 0a2397c80c0..a60557ae8ae 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyObject.h +++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.h @@ -7,6 +7,7 @@ #pragma once +#include #include namespace JS { @@ -34,7 +35,7 @@ public: // 10.5 Proxy Object Internal Methods and Internal Slots, https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots - virtual Object* internal_get_prototype_of() const override; + virtual ThrowCompletionOr internal_get_prototype_of() const override; virtual bool internal_set_prototype_of(Object* prototype) override; virtual bool internal_is_extensible() const override; virtual bool internal_prevent_extensions() override; diff --git a/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp b/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp index ed2694fdee3..990bd27f65c 100644 --- a/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp @@ -212,7 +212,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::get_prototype_of) } // 2. Return ? target.[[GetPrototypeOf]](). - return target.as_object().internal_get_prototype_of(); + return TRY_OR_DISCARD(target.as_object().internal_get_prototype_of()); } // 28.1.8 Reflect.has ( target, propertyKey ), https://tc39.es/ecma262/#sec-reflect.has diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index 6644c2d4be9..138513a3f6b 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/Userland/Libraries/LibJS/Runtime/Value.cpp @@ -1334,9 +1334,7 @@ Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs) return {}; } while (true) { - lhs_object = lhs_object->internal_get_prototype_of(); - if (vm.exception()) - return {}; + lhs_object = TRY_OR_DISCARD(lhs_object->internal_get_prototype_of()); if (!lhs_object) return Value(false); if (same_value(rhs_prototype, lhs_object)) diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.cpp b/Userland/Services/WebContent/ConsoleGlobalObject.cpp index 2452185168c..db79202572b 100644 --- a/Userland/Services/WebContent/ConsoleGlobalObject.cpp +++ b/Userland/Services/WebContent/ConsoleGlobalObject.cpp @@ -5,6 +5,7 @@ */ #include "ConsoleGlobalObject.h" +#include #include #include #include @@ -36,7 +37,7 @@ void ConsoleGlobalObject::visit_edges(Visitor& visitor) visitor.visit(m_window_object); } -JS::Object* ConsoleGlobalObject::internal_get_prototype_of() const +JS::ThrowCompletionOr ConsoleGlobalObject::internal_get_prototype_of() const { return m_window_object->internal_get_prototype_of(); } diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.h b/Userland/Services/WebContent/ConsoleGlobalObject.h index 3ef87afbf77..c33f9f5f26a 100644 --- a/Userland/Services/WebContent/ConsoleGlobalObject.h +++ b/Userland/Services/WebContent/ConsoleGlobalObject.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include namespace Web::Bindings { @@ -22,7 +23,7 @@ public: ConsoleGlobalObject(Web::Bindings::WindowObject&); virtual ~ConsoleGlobalObject() override; - virtual Object* internal_get_prototype_of() const override; + virtual JS::ThrowCompletionOr internal_get_prototype_of() const override; virtual bool internal_set_prototype_of(Object* prototype) override; virtual bool internal_is_extensible() const override; virtual bool internal_prevent_extensions() override;