1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 05:57:44 +00:00

LibJS: Add the Object::define_native_accessor method

This is very similar to Object::define_native_property, but here the
native functions are exported as standalone JS getter and setter
functions, instead of being transparently called by interactions with
the property.
This commit is contained in:
Idan Horowitz 2021-06-12 01:41:07 +03:00 committed by Linus Groh
parent 9c5de113b1
commit 7f6d3818a2
2 changed files with 35 additions and 0 deletions

View file

@ -543,6 +543,40 @@ bool Object::define_property(const PropertyName& property_name, Value value, Pro
return put_own_property(property_name.to_string_or_symbol(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
}
bool Object::define_native_accessor(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attribute)
{
auto& vm = this->vm();
String formatted_property_name;
if (property_name.is_string()) {
formatted_property_name = property_name.as_string();
} else {
formatted_property_name = String::formatted("[{}]", property_name.as_symbol()->description());
}
Function* getter_function = nullptr;
if (getter) {
auto name = String::formatted("get {}", formatted_property_name);
getter_function = NativeFunction::create(global_object(), name, move(getter));
getter_function->define_property_without_transition(vm.names.length, Value(0), Attribute::Configurable);
if (vm.exception())
return {};
getter_function->define_property_without_transition(vm.names.name, js_string(vm.heap(), name), Attribute::Configurable);
if (vm.exception())
return {};
}
Function* setter_function = nullptr;
if (setter) {
auto name = String::formatted("set {}", formatted_property_name);
setter_function = NativeFunction::create(global_object(), name, move(setter));
setter_function->define_property_without_transition(vm.names.length, Value(1), Attribute::Configurable);
if (vm.exception())
return {};
setter_function->define_property_without_transition(vm.names.name, js_string(vm.heap(), name), Attribute::Configurable);
if (vm.exception())
return {};
}
return define_accessor(property_name, getter_function, setter_function, attribute);
}
bool Object::define_accessor(const PropertyName& property_name, Function* getter, Function* setter, PropertyAttributes attributes, bool throw_exceptions)
{
VERIFY(property_name.is_valid());