mirror of
https://github.com/RGBCube/serenity
synced 2025-07-19 18:57:40 +00:00
LibJS: Add Object::define_accessor()
This is a helper function based on the getter/setter definition logic from ObjectExpression::execute() to look up an Accessor property if it already exists, define a new Accessor property if it doesn't exist, and set the getter or setter function on the Accessor.
This commit is contained in:
parent
949bffdc93
commit
a535d58cac
3 changed files with 29 additions and 17 deletions
|
@ -1364,23 +1364,9 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
|
||||||
|
|
||||||
if (property.type() == ObjectProperty::Type::Getter || property.type() == ObjectProperty::Type::Setter) {
|
if (property.type() == ObjectProperty::Type::Getter || property.type() == ObjectProperty::Type::Setter) {
|
||||||
ASSERT(value.is_function());
|
ASSERT(value.is_function());
|
||||||
Accessor* accessor { nullptr };
|
object->define_accessor(key, value.as_function(), property.type() == ObjectProperty::Type::Getter, Attribute::Configurable | Attribute::Enumerable);
|
||||||
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())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
}
|
|
||||||
if (property.type() == ObjectProperty::Type::Getter)
|
|
||||||
accessor->set_getter(&value.as_function());
|
|
||||||
else
|
|
||||||
accessor->set_setter(&value.as_function());
|
|
||||||
} else {
|
} else {
|
||||||
object->define_property(key, value);
|
object->define_property(key, value);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
|
|
|
@ -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);
|
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)
|
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()));
|
ASSERT(!(mode == PutOwnPropertyMode::Put && value.is_accessor()));
|
||||||
|
|
|
@ -98,6 +98,7 @@ public:
|
||||||
|
|
||||||
virtual bool define_property(const FlyString& property_name, const Object& descriptor, bool throw_exceptions = true);
|
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_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<Value(Interpreter&, GlobalObject&)>, i32 length = 0, PropertyAttributes attributes = default_attributes);
|
bool define_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&, GlobalObject&)>, i32 length = 0, PropertyAttributes attributes = default_attributes);
|
||||||
bool define_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter, PropertyAttributes attributes = default_attributes);
|
bool define_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter, PropertyAttributes attributes = default_attributes);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue