summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-06-12 01:41:07 +0300
committerLinus Groh <mail@linusgroh.de>2021-06-12 00:44:15 +0100
commit7f6d3818a2e296ccd50c493c97a156152dbbb0db (patch)
tree222dded1481e70c0e9fcda209f5e5d7f9c146ff6 /Userland/Libraries
parent9c5de113b1bda12ef41c3b7ab6398f7f0e1931f9 (diff)
downloadserenity-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.cpp34
-rw-r--r--Userland/Libraries/LibJS/Runtime/Object.h1
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);