diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 308c951914..4d86f628c2 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -1364,23 +1364,9 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o if (property.type() == ObjectProperty::Type::Getter || property.type() == ObjectProperty::Type::Setter) { ASSERT(value.is_function()); - Accessor* accessor { nullptr }; - auto property_metadata = object->shape().lookup(key); - if (property_metadata.has_value()) { - auto existing_property = object->get_direct(property_metadata.value().offset); - if (existing_property.is_accessor()) - accessor = &existing_property.as_accessor(); - } - if (!accessor) { - accessor = Accessor::create(interpreter, global_object, nullptr, nullptr); - object->define_property(key, accessor, Attribute::Configurable | Attribute::Enumerable); - if (interpreter.exception()) - return {}; - } - if (property.type() == ObjectProperty::Type::Getter) - accessor->set_getter(&value.as_function()); - else - accessor->set_setter(&value.as_function()); + object->define_accessor(key, value.as_function(), property.type() == ObjectProperty::Type::Getter, Attribute::Configurable | Attribute::Enumerable); + if (interpreter.exception()) + return {}; } else { object->define_property(key, value); if (interpreter.exception()) diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index 0b87bc57fd..2d1feb8ebd 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -427,6 +427,31 @@ bool Object::define_property(PropertyName property_name, Value value, PropertyAt return put_own_property(*this, property_name.as_string(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions); } +bool Object::define_accessor(PropertyName property_name, Function& getter_or_setter, bool is_getter, PropertyAttributes attributes, bool throw_exceptions) +{ + Accessor* accessor { nullptr }; + auto property_metadata = shape().lookup(property_name.as_string()); + if (property_metadata.has_value()) { + auto existing_property = get_direct(property_metadata.value().offset); + if (existing_property.is_accessor()) + accessor = &existing_property.as_accessor(); + } + if (!accessor) { + accessor = Accessor::create(interpreter(), nullptr, nullptr); + bool definition_success = define_property(property_name, accessor, attributes, throw_exceptions); + if (interpreter().exception()) + return {}; + if (!definition_success) + return false; + } + if (is_getter) + accessor->set_getter(&getter_or_setter); + else + accessor->set_setter(&getter_or_setter); + + return true; +} + bool Object::put_own_property(Object& this_object, const FlyString& property_name, Value value, PropertyAttributes attributes, PutOwnPropertyMode mode, bool throw_exceptions) { ASSERT(!(mode == PutOwnPropertyMode::Put && value.is_accessor())); diff --git a/Libraries/LibJS/Runtime/Object.h b/Libraries/LibJS/Runtime/Object.h index 4cf78f822d..3723560e27 100644 --- a/Libraries/LibJS/Runtime/Object.h +++ b/Libraries/LibJS/Runtime/Object.h @@ -98,6 +98,7 @@ public: virtual bool define_property(const FlyString& property_name, const Object& descriptor, bool throw_exceptions = true); bool define_property(PropertyName, Value value, PropertyAttributes attributes = default_attributes, bool throw_exceptions = true); + bool define_accessor(PropertyName, Function& getter_or_setter, bool is_getter, PropertyAttributes attributes = default_attributes, bool throw_exceptions = true); bool define_native_function(const FlyString& property_name, AK::Function, i32 length = 0, PropertyAttributes attributes = default_attributes); bool define_native_property(const FlyString& property_name, AK::Function getter, AK::Function setter, PropertyAttributes attributes = default_attributes);