mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:32:46 +00:00 
			
		
		
		
	LibJS: Convert internal_get_prototype_of() to ThrowCompletionOr
This commit is contained in:
		
							parent
							
								
									c8bf7f9c41
								
							
						
					
					
						commit
						5148150e1c
					
				
					 14 changed files with 48 additions and 70 deletions
				
			
		|  | @ -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.
 | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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(); | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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__
 | ||||
|  |  | |||
|  | @ -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)) { | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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)) | ||||
|  |  | |||
|  | @ -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(); | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Linus Groh
						Linus Groh