From 686213c2b81f408addca928ef1508e2af0354f9c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 19 Jun 2021 11:34:19 +0200 Subject: [PATCH] LibJS: Make Object.getOwnPropertyDescriptor() work on String subscripts String objects are a bit special since the indexed properties are overridden by the contents of the underlying PrimitiveString. getOwnPropertyDescriptor() was not taking this into account, and would instead return undefined when asked about an indexed property in a String object. --- Userland/Libraries/LibJS/Runtime/StringObject.cpp | 14 ++++++++++++++ Userland/Libraries/LibJS/Runtime/StringObject.h | 1 + .../Object/Object.getOwnPropertyDescriptor.js | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/Userland/Libraries/LibJS/Runtime/StringObject.cpp b/Userland/Libraries/LibJS/Runtime/StringObject.cpp index d73d8bad43..b23015ef12 100644 --- a/Userland/Libraries/LibJS/Runtime/StringObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringObject.cpp @@ -39,4 +39,18 @@ void StringObject::visit_edges(Cell::Visitor& visitor) visitor.visit(&m_string); } +Optional StringObject::get_own_property_descriptor(PropertyName const& property_name) const +{ + if (!property_name.is_number() || property_name.as_number() >= m_string.string().length()) + return Base::get_own_property_descriptor(property_name); + + PropertyDescriptor descriptor; + descriptor.value = js_string(heap(), m_string.string().substring(property_name.as_number(), 1)); + descriptor.attributes.set_has_configurable(); + descriptor.attributes.set_has_enumerable(); + descriptor.attributes.set_has_writable(); + descriptor.attributes.set_enumerable(); + return descriptor; +} + } diff --git a/Userland/Libraries/LibJS/Runtime/StringObject.h b/Userland/Libraries/LibJS/Runtime/StringObject.h index 8c7ee5cc94..3f74ec8769 100644 --- a/Userland/Libraries/LibJS/Runtime/StringObject.h +++ b/Userland/Libraries/LibJS/Runtime/StringObject.h @@ -29,6 +29,7 @@ public: private: virtual bool is_string_object() const final { return true; } virtual void visit_edges(Visitor&) override; + virtual Optional get_own_property_descriptor(PropertyName const&) const override; PrimitiveString& m_string; }; diff --git a/Userland/Libraries/LibJS/Tests/builtins/Object/Object.getOwnPropertyDescriptor.js b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.getOwnPropertyDescriptor.js index ee1fcef2fb..ec12161d33 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Object/Object.getOwnPropertyDescriptor.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.getOwnPropertyDescriptor.js @@ -86,3 +86,12 @@ test("defined property", () => { expect(o).not.toHaveGetterProperty(1); expect(o).not.toHaveSetterProperty(1); }); + +test("String object indexed properties", () => { + expect("foo").toHaveValueProperty(0, "f"); + expect("foo").toHaveEnumerableProperty(0); + expect("foo").not.toHaveConfigurableProperty(0); + expect("foo").not.toHaveWritableProperty(0); + + expect("foo").toHaveValueProperty(1, "o"); +});