LibJS: Convert internal_get_prototype_of() to ThrowCompletionOr

This commit is contained in:
Linus Groh 2021-09-28 23:30:17 +01:00
parent c8bf7f9c41
commit 5148150e1c
Notes: sideshowbarker 2024-07-18 03:19:38 +09:00
14 changed files with 48 additions and 70 deletions

View file

@ -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.

View file

@ -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;
}

View file

@ -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<FunctionEnvironment>(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;
}

View file

@ -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

View file

@ -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*> Object::internal_get_prototype_of() const
{
// 1. Return O.[[Prototype]].
return const_cast<Object*>(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)

View file

@ -12,6 +12,7 @@
#include <AK/String.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/IndexedProperties.h>
#include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/PrimitiveString.h>
@ -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<Object*> internal_get_prototype_of() const;
virtual bool internal_set_prototype_of(Object* prototype);
virtual bool internal_is_extensible() const;
virtual bool internal_prevent_extensions();

View file

@ -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

View file

@ -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__

View file

@ -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<Object*> 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<TypeError>(global_object, ErrorType::ProxyRevoked);
return {};
}
if (m_is_revoked)
return vm.throw_completion<TypeError>(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<TypeError>(global_object, ErrorType::ProxyGetPrototypeOfReturn);
return {};
}
if (!handler_proto.is_object() && !handler_proto.is_null())
return vm.throw_completion<TypeError>(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<TypeError>(global_object, ErrorType::ProxyGetPrototypeOfNonExtensible);
return {};
}
if (!same_value(handler_proto, target_proto))
return vm.throw_completion<TypeError>(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)) {

View file

@ -7,6 +7,7 @@
#pragma once
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/FunctionObject.h>
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<Object*> 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;

View file

@ -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

View file

@ -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))

View file

@ -5,6 +5,7 @@
*/
#include "ConsoleGlobalObject.h"
#include <LibJS/Runtime/Completion.h>
#include <LibWeb/Bindings/NodeWrapper.h>
#include <LibWeb/Bindings/NodeWrapperFactory.h>
#include <LibWeb/Bindings/WindowObject.h>
@ -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<JS::Object*> ConsoleGlobalObject::internal_get_prototype_of() const
{
return m_window_object->internal_get_prototype_of();
}

View file

@ -7,6 +7,7 @@
#pragma once
#include <LibJS/Forward.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/GlobalObject.h>
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<Object*> 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;