Selaa lähdekoodia

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.
Jack Karamanian 5 vuotta sitten
vanhempi
commit
a535d58cac
3 muutettua tiedostoa jossa 29 lisäystä ja 17 poistoa
  1. 3 17
      Libraries/LibJS/AST.cpp
  2. 25 0
      Libraries/LibJS/Runtime/Object.cpp
  3. 1 0
      Libraries/LibJS/Runtime/Object.h

+ 3 - 17
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())

+ 25 - 0
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()));

+ 1 - 0
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<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);