diff --git a/Userland/Libraries/LibJS/Runtime/IndexedProperties.cpp b/Userland/Libraries/LibJS/Runtime/IndexedProperties.cpp index 1d7bd301e5..bae17bbd2b 100644 --- a/Userland/Libraries/LibJS/Runtime/IndexedProperties.cpp +++ b/Userland/Libraries/LibJS/Runtime/IndexedProperties.cpp @@ -77,6 +77,10 @@ bool SimpleIndexedPropertyStorage::set_array_like_size(size_t new_size) return true; } +GenericIndexedPropertyStorage::GenericIndexedPropertyStorage() +{ +} + GenericIndexedPropertyStorage::GenericIndexedPropertyStorage(SimpleIndexedPropertyStorage&& storage) { m_array_size = storage.array_like_size(); @@ -216,11 +220,14 @@ void IndexedPropertyIterator::skip_empty_indices() Optional IndexedProperties::get(u32 index) const { + if (!m_storage) + return {}; return m_storage->get(index); } void IndexedProperties::put(u32 index, Value value, PropertyAttributes attributes) { + ensure_storage(); if (m_storage->is_simple_storage() && (attributes != default_attributes || index > (array_like_size() + SPARSE_ARRAY_HOLE_THRESHOLD))) { switch_to_generic_storage(); } @@ -230,12 +237,14 @@ void IndexedProperties::put(u32 index, Value value, PropertyAttributes attribute void IndexedProperties::remove(u32 index) { + VERIFY(m_storage); VERIFY(m_storage->has_index(index)); m_storage->remove(index); } bool IndexedProperties::set_array_like_size(size_t new_size) { + ensure_storage(); auto current_array_like_size = array_like_size(); // We can't use simple storage for lengths that don't fit in an i32. @@ -252,6 +261,8 @@ bool IndexedProperties::set_array_like_size(size_t new_size) size_t IndexedProperties::real_size() const { + if (!m_storage) + return 0; if (m_storage->is_simple_storage()) { auto& packed_elements = static_cast(*m_storage).elements(); size_t size = 0; @@ -266,6 +277,8 @@ size_t IndexedProperties::real_size() const Vector IndexedProperties::indices() const { + if (!m_storage) + return {}; if (m_storage->is_simple_storage()) { const auto& storage = static_cast(*m_storage); const auto& elements = storage.elements(); @@ -285,8 +298,18 @@ Vector IndexedProperties::indices() const void IndexedProperties::switch_to_generic_storage() { + if (!m_storage) { + m_storage = make(); + return; + } auto& storage = static_cast(*m_storage); m_storage = make(move(storage)); } +void IndexedProperties::ensure_storage() +{ + if (!m_storage) + m_storage = make(); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/IndexedProperties.h b/Userland/Libraries/LibJS/Runtime/IndexedProperties.h index 7fa69abae2..51826f41f5 100644 --- a/Userland/Libraries/LibJS/Runtime/IndexedProperties.h +++ b/Userland/Libraries/LibJS/Runtime/IndexedProperties.h @@ -72,6 +72,7 @@ private: class GenericIndexedPropertyStorage final : public IndexedPropertyStorage { public: explicit GenericIndexedPropertyStorage(SimpleIndexedPropertyStorage&&); + explicit GenericIndexedPropertyStorage(); virtual bool has_index(u32 index) const override; virtual Optional get(u32 index) const override; @@ -116,11 +117,12 @@ public: IndexedProperties() = default; explicit IndexedProperties(Vector values) - : m_storage(make(move(values))) { + if (!values.is_empty()) + m_storage = make(move(values)); } - bool has_index(u32 index) const { return m_storage->has_index(index); } + bool has_index(u32 index) const { return m_storage ? m_storage->has_index(index) : false; } Optional get(u32 index) const; void put(u32 index, Value value, PropertyAttributes attributes = default_attributes); void remove(u32 index); @@ -131,7 +133,7 @@ public: IndexedPropertyIterator end() const { return IndexedPropertyIterator(*this, array_like_size(), false); }; bool is_empty() const { return array_like_size() == 0; } - size_t array_like_size() const { return m_storage->array_like_size(); } + size_t array_like_size() const { return m_storage ? m_storage->array_like_size() : 0; } bool set_array_like_size(size_t); size_t real_size() const; @@ -141,6 +143,8 @@ public: template void for_each_value(Callback callback) { + if (!m_storage) + return; if (m_storage->is_simple_storage()) { for (auto& value : static_cast(*m_storage).elements()) callback(value); @@ -152,8 +156,9 @@ public: private: void switch_to_generic_storage(); + void ensure_storage(); - NonnullOwnPtr m_storage { make() }; + OwnPtr m_storage; }; }