diff options
author | mattco98 <matthewcolsson@gmail.com> | 2020-04-28 19:19:31 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-29 18:47:03 +0200 |
commit | 95abcc3722af0ec0115d519504e19d05c9cb79a5 (patch) | |
tree | 7bfd09133c9c56d680e3a81fc3016142cd1b534d /Libraries/LibJS/Runtime | |
parent | 58f6f50de48965a6bf0113c7e9ba79889dba09ac (diff) | |
download | serenity-95abcc3722af0ec0115d519504e19d05c9cb79a5.zip |
LibJS: Implement correct object property ordering
This commit introduces a way to get an object's own properties in the
correct order. The "correct order" for JS object properties is first all
array-like index properties (numeric keys) sorted by insertion order,
followed by all string properties sorted by insertion order.
Objects also now print correctly in the repl! Before this commit:
courage ~/js-tests $ js
> ({ foo: 1, bar: 2, baz: 3 })
{ bar: 2, foo: 1, baz: 3 }
After:
courage ~/js-tests $ js
> ({ foo: 1, bar: 2, baz: 3 })
{ foo: 1, bar: 2, baz: 3 }
Diffstat (limited to 'Libraries/LibJS/Runtime')
-rw-r--r-- | Libraries/LibJS/Runtime/Cell.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Cell.h | 1 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Object.cpp | 1 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/ObjectConstructor.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Shape.cpp | 12 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Shape.h | 7 |
6 files changed, 27 insertions, 1 deletions
diff --git a/Libraries/LibJS/Runtime/Cell.cpp b/Libraries/LibJS/Runtime/Cell.cpp index c80b59e824..4c8cb69511 100644 --- a/Libraries/LibJS/Runtime/Cell.cpp +++ b/Libraries/LibJS/Runtime/Cell.cpp @@ -56,6 +56,11 @@ Interpreter& Cell::interpreter() return heap().interpreter(); } +Interpreter& Cell::interpreter() const +{ + return heap().interpreter(); +} + const LogStream& operator<<(const LogStream& stream, const Cell* cell) { if (!cell) diff --git a/Libraries/LibJS/Runtime/Cell.h b/Libraries/LibJS/Runtime/Cell.h index 9989618ed4..e08a31ac62 100644 --- a/Libraries/LibJS/Runtime/Cell.h +++ b/Libraries/LibJS/Runtime/Cell.h @@ -60,6 +60,7 @@ public: Heap& heap() const; Interpreter& interpreter(); + Interpreter& interpreter() const; protected: Cell() {} diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index 5144e75444..403c99f066 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -34,6 +34,7 @@ #include <LibJS/Runtime/NativeProperty.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/Shape.h> +#include <LibJS/Runtime/StringObject.h> #include <LibJS/Runtime/Value.h> namespace JS { diff --git a/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Libraries/LibJS/Runtime/ObjectConstructor.cpp index e7738ecfeb..475bbd56f4 100644 --- a/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -76,7 +76,7 @@ Value ObjectConstructor::get_own_property_names(Interpreter& interpreter) result->elements().append(js_string(interpreter, String::number(i))); } - for (auto& it : object->shape().property_table()) { + for (auto& it : object->shape().property_table_ordered()) { result->elements().append(js_string(interpreter, it.key)); } return result; diff --git a/Libraries/LibJS/Runtime/Shape.cpp b/Libraries/LibJS/Runtime/Shape.cpp index d03ad74a36..ef10ea8c51 100644 --- a/Libraries/LibJS/Runtime/Shape.cpp +++ b/Libraries/LibJS/Runtime/Shape.cpp @@ -117,6 +117,18 @@ size_t Shape::property_count() const return property_table().size(); } +Vector<Shape::Property> Shape::property_table_ordered() const +{ + auto vec = Vector<Shape::Property>(); + vec.resize(property_table().size()); + + for (auto& it : property_table()) { + vec[it.value.offset] = { it.key, it.value }; + } + + return vec; +} + void Shape::ensure_property_table() const { if (m_property_table) diff --git a/Libraries/LibJS/Runtime/Shape.h b/Libraries/LibJS/Runtime/Shape.h index 26c8eb574b..44cf3bdb43 100644 --- a/Libraries/LibJS/Runtime/Shape.h +++ b/Libraries/LibJS/Runtime/Shape.h @@ -88,6 +88,13 @@ public: const HashMap<FlyString, PropertyMetadata>& property_table() const; size_t property_count() const; + struct Property { + FlyString key; + PropertyMetadata value; + }; + + Vector<Property> property_table_ordered() const; + void set_prototype_without_transition(Object* new_prototype) { m_prototype = new_prototype; } void remove_property_from_unique_shape(const FlyString&, size_t offset); |