diff --git a/Libraries/LibJS/Runtime/Array.cpp b/Libraries/LibJS/Runtime/Array.cpp index db94e190290..e8cfb28f1b8 100644 --- a/Libraries/LibJS/Runtime/Array.cpp +++ b/Libraries/LibJS/Runtime/Array.cpp @@ -59,4 +59,28 @@ void Array::visit_children(Cell::Visitor& visitor) visitor.visit(element); } +Optional Array::get_own_property(const String& property_name) const +{ + bool ok; + i32 index = property_name.to_int(ok); + if (ok) { + if (index >= 0 && index < length()) + return m_elements[index]; + } + return Object::get_own_property(property_name); +} + +bool Array::put_own_property(const String& property_name, Value value) +{ + bool ok; + i32 index = property_name.to_int(ok); + if (ok && index >= 0) { + if (index >= length()) + m_elements.resize(index + 1); + m_elements[index] = value; + return true; + } + return Object::put_own_property(property_name, value); +} + } diff --git a/Libraries/LibJS/Runtime/Array.h b/Libraries/LibJS/Runtime/Array.h index d99873544fa..828b70c33f7 100644 --- a/Libraries/LibJS/Runtime/Array.h +++ b/Libraries/LibJS/Runtime/Array.h @@ -45,6 +45,8 @@ private: virtual const char* class_name() const override { return "Array"; } virtual void visit_children(Cell::Visitor&) override; virtual bool is_array() const override { return true; } + virtual Optional get_own_property(const String& property_name) const override; + virtual bool put_own_property(const String& property_name, Value) override; Vector m_elements; }; diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index 01fe5bff80c..2cf1f7cc0a7 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -44,54 +44,53 @@ Object::~Object() { } -Value Object::get(String property_name) const +Optional Object::get_own_property(const String& property_name) const +{ + auto value_here = m_properties.get(property_name); + if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object()->is_native_property()) + return static_cast(value_here.value().as_object())->get(const_cast(this)); + return value_here; +} + +bool Object::put_own_property(const String& property_name, Value value) +{ + auto value_here = m_properties.get(property_name); + if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object()->is_native_property()) { + static_cast(value_here.value().as_object())->set(const_cast(this), value); + } else { + m_properties.set(property_name, value); + } + return true; +} + +Value Object::get(const String& property_name) const { const Object* object = this; while (object) { - if (object->is_array()) { - auto* array = static_cast(object); - bool ok; - i32 index = property_name.to_int(ok); - if (ok) { - if (index >= 0 && index < array->length()) - return array->elements()[index]; - } - } - auto value = object->m_properties.get(property_name); - if (value.has_value()) { - if (value.value().is_object() && value.value().as_object()->is_native_property()) - return static_cast(value.value().as_object())->get(const_cast(this)); + auto value = object->get_own_property(property_name); + if (value.has_value()) return value.value(); - } object = object->prototype(); } return js_undefined(); } -void Object::put(String property_name, Value value) +void Object::put(const String& property_name, Value value) { Object* object = this; while (object) { - if (object->is_array()) { - auto* array = static_cast(object); - bool ok; - i32 index = property_name.to_int(ok); - if (ok && index >= 0) { - if (index >= array->length()) - array->elements().resize(index + 1); - array->elements()[index] = value; - } - } auto value_here = object->m_properties.get(property_name); if (value_here.has_value()) { if (value_here.value().is_object() && value_here.value().as_object()->is_native_property()) { static_cast(value_here.value().as_object())->set(const_cast(this), value); return; } + if (object->put_own_property(property_name, value)) + return; } object = object->prototype(); } - m_properties.set(property_name, move(value)); + put_own_property(property_name, value); } void Object::put_native_function(String property_name, AK::Function)> native_function) @@ -147,5 +146,4 @@ Value Object::to_string() const { return js_string(heap(), String::format("[object %s]", class_name())); } - } diff --git a/Libraries/LibJS/Runtime/Object.h b/Libraries/LibJS/Runtime/Object.h index 631f87801b7..9e61676c516 100644 --- a/Libraries/LibJS/Runtime/Object.h +++ b/Libraries/LibJS/Runtime/Object.h @@ -40,8 +40,11 @@ public: Object(); virtual ~Object(); - Value get(String property_name) const; - void put(String property_name, Value); + Value get(const String& property_name) const; + void put(const String& property_name, Value); + + virtual Optional get_own_property(const String& property_name) const; + virtual bool put_own_property(const String& property_name, Value); void put_native_function(String property_name, AK::Function)>); void put_native_property(String property_name, AK::Function getter, AK::Function setter);