diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-06-12 01:41:07 +0300 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-06-12 00:44:15 +0100 |
commit | 7f6d3818a2e296ccd50c493c97a156152dbbb0db (patch) | |
tree | 222dded1481e70c0e9fcda209f5e5d7f9c146ff6 /Userland/Libraries | |
parent | 9c5de113b1bda12ef41c3b7ab6398f7f0e1931f9 (diff) | |
download | serenity-7f6d3818a2e296ccd50c493c97a156152dbbb0db.zip |
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.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Object.cpp | 34 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Object.h | 1 |
2 files changed, 35 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index 7935cbf358..29df7bf2c3 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -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()); diff --git a/Userland/Libraries/LibJS/Runtime/Object.h b/Userland/Libraries/LibJS/Runtime/Object.h index fa40ef18d9..e69328b969 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.h +++ b/Userland/Libraries/LibJS/Runtime/Object.h @@ -95,6 +95,7 @@ public: bool define_native_function(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)>, i32 length = 0, PropertyAttributes attributes = default_attributes); bool define_native_property(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attributes = default_attributes); + bool define_native_accessor(StringOrSymbol const& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attributes = default_attributes); void define_properties(Value properties); |