LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
/*
|
2021-04-22 16:53:07 -07:00
|
|
|
* Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
*/
|
|
|
|
|
2020-10-20 00:24:53 +01:00
|
|
|
#include <AK/QuickSort.h>
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
#include <LibJS/Runtime/Accessor.h>
|
|
|
|
#include <LibJS/Runtime/IndexedProperties.h>
|
|
|
|
|
|
|
|
namespace JS {
|
|
|
|
|
2021-05-17 23:13:37 +01:00
|
|
|
constexpr const size_t SPARSE_ARRAY_HOLE_THRESHOLD = 200;
|
|
|
|
constexpr const size_t LENGTH_SETTER_GENERIC_STORAGE_THRESHOLD = 4 * MiB;
|
2021-03-21 11:33:45 +01:00
|
|
|
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
SimpleIndexedPropertyStorage::SimpleIndexedPropertyStorage(Vector<Value>&& initial_values)
|
|
|
|
: m_array_size(initial_values.size())
|
|
|
|
, m_packed_elements(move(initial_values))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SimpleIndexedPropertyStorage::has_index(u32 index) const
|
|
|
|
{
|
|
|
|
return index < m_array_size && !m_packed_elements[index].is_empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<ValueAndAttributes> SimpleIndexedPropertyStorage::get(u32 index) const
|
|
|
|
{
|
|
|
|
if (index >= m_array_size)
|
|
|
|
return {};
|
|
|
|
return ValueAndAttributes { m_packed_elements[index], default_attributes };
|
|
|
|
}
|
|
|
|
|
2021-03-21 11:33:45 +01:00
|
|
|
void SimpleIndexedPropertyStorage::grow_storage_if_needed()
|
|
|
|
{
|
|
|
|
if (m_array_size <= m_packed_elements.size())
|
|
|
|
return;
|
|
|
|
// Grow storage by 25% at a time.
|
|
|
|
m_packed_elements.resize(m_array_size + (m_array_size / 4));
|
|
|
|
}
|
|
|
|
|
2020-06-02 17:13:09 -07:00
|
|
|
void SimpleIndexedPropertyStorage::put(u32 index, Value value, PropertyAttributes attributes)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(attributes == default_attributes);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
|
|
|
|
if (index >= m_array_size) {
|
|
|
|
m_array_size = index + 1;
|
2021-03-21 11:33:45 +01:00
|
|
|
grow_storage_if_needed();
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
m_packed_elements[index] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleIndexedPropertyStorage::remove(u32 index)
|
|
|
|
{
|
|
|
|
if (index < m_array_size)
|
|
|
|
m_packed_elements[index] = {};
|
|
|
|
}
|
|
|
|
|
2020-06-02 17:13:09 -07:00
|
|
|
void SimpleIndexedPropertyStorage::insert(u32 index, Value value, PropertyAttributes attributes)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(attributes == default_attributes);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
m_array_size++;
|
|
|
|
m_packed_elements.insert(index, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueAndAttributes SimpleIndexedPropertyStorage::take_first()
|
|
|
|
{
|
|
|
|
m_array_size--;
|
|
|
|
return { m_packed_elements.take_first(), default_attributes };
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueAndAttributes SimpleIndexedPropertyStorage::take_last()
|
|
|
|
{
|
|
|
|
m_array_size--;
|
|
|
|
auto last_element = m_packed_elements[m_array_size];
|
|
|
|
m_packed_elements[m_array_size] = {};
|
|
|
|
return { last_element, default_attributes };
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleIndexedPropertyStorage::set_array_like_size(size_t new_size)
|
|
|
|
{
|
|
|
|
m_array_size = new_size;
|
|
|
|
m_packed_elements.resize(new_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericIndexedPropertyStorage::GenericIndexedPropertyStorage(SimpleIndexedPropertyStorage&& storage)
|
|
|
|
{
|
|
|
|
m_array_size = storage.array_like_size();
|
2021-03-21 11:33:45 +01:00
|
|
|
for (size_t i = 0; i < storage.m_packed_elements.size(); ++i) {
|
|
|
|
m_sparse_elements.set(i, { storage.m_packed_elements[i], default_attributes });
|
|
|
|
}
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GenericIndexedPropertyStorage::has_index(u32 index) const
|
|
|
|
{
|
|
|
|
return m_sparse_elements.contains(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<ValueAndAttributes> GenericIndexedPropertyStorage::get(u32 index) const
|
|
|
|
{
|
|
|
|
if (index >= m_array_size)
|
|
|
|
return {};
|
|
|
|
return m_sparse_elements.get(index);
|
|
|
|
}
|
|
|
|
|
2020-06-02 17:13:09 -07:00
|
|
|
void GenericIndexedPropertyStorage::put(u32 index, Value value, PropertyAttributes attributes)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
|
|
|
if (index >= m_array_size)
|
|
|
|
m_array_size = index + 1;
|
2021-03-21 11:33:45 +01:00
|
|
|
m_sparse_elements.set(index, { value, attributes });
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void GenericIndexedPropertyStorage::remove(u32 index)
|
|
|
|
{
|
|
|
|
if (index >= m_array_size)
|
|
|
|
return;
|
|
|
|
if (index + 1 == m_array_size) {
|
|
|
|
take_last();
|
|
|
|
return;
|
|
|
|
}
|
2021-03-21 11:33:45 +01:00
|
|
|
m_sparse_elements.remove(index);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
2020-06-02 17:13:09 -07:00
|
|
|
void GenericIndexedPropertyStorage::insert(u32 index, Value value, PropertyAttributes attributes)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
|
|
|
if (index >= m_array_size) {
|
|
|
|
put(index, value, attributes);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_array_size++;
|
|
|
|
|
|
|
|
if (!m_sparse_elements.is_empty()) {
|
|
|
|
HashMap<u32, ValueAndAttributes> new_sparse_elements;
|
|
|
|
for (auto& entry : m_sparse_elements)
|
|
|
|
new_sparse_elements.set(entry.key >= index ? entry.key + 1 : entry.key, entry.value);
|
|
|
|
m_sparse_elements = move(new_sparse_elements);
|
|
|
|
}
|
|
|
|
|
2021-03-21 11:33:45 +01:00
|
|
|
m_sparse_elements.set(index, { value, attributes });
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ValueAndAttributes GenericIndexedPropertyStorage::take_first()
|
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(m_array_size > 0);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
m_array_size--;
|
|
|
|
|
2021-03-21 11:33:45 +01:00
|
|
|
auto indices = m_sparse_elements.keys();
|
|
|
|
quick_sort(indices);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
|
2021-03-21 11:33:45 +01:00
|
|
|
auto it = m_sparse_elements.find(indices.first());
|
|
|
|
auto first_element = it->value;
|
|
|
|
m_sparse_elements.remove(it);
|
2021-03-20 13:43:42 +01:00
|
|
|
return first_element;
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ValueAndAttributes GenericIndexedPropertyStorage::take_last()
|
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(m_array_size > 0);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
m_array_size--;
|
|
|
|
|
2021-03-21 11:33:45 +01:00
|
|
|
auto result = m_sparse_elements.get(m_array_size);
|
2021-05-17 23:20:29 +01:00
|
|
|
if (!result.has_value())
|
|
|
|
return {};
|
2021-03-21 11:33:45 +01:00
|
|
|
m_sparse_elements.remove(m_array_size);
|
|
|
|
return result.value();
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void GenericIndexedPropertyStorage::set_array_like_size(size_t new_size)
|
|
|
|
{
|
2020-09-01 19:47:50 +01:00
|
|
|
m_array_size = new_size;
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
|
2021-03-21 11:33:45 +01:00
|
|
|
HashMap<u32, ValueAndAttributes> new_sparse_elements;
|
|
|
|
for (auto& entry : m_sparse_elements) {
|
|
|
|
if (entry.key < new_size)
|
|
|
|
new_sparse_elements.set(entry.key, entry.value);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
2021-03-21 11:33:45 +01:00
|
|
|
m_sparse_elements = move(new_sparse_elements);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
IndexedPropertyIterator::IndexedPropertyIterator(const IndexedProperties& indexed_properties, u32 staring_index, bool skip_empty)
|
|
|
|
: m_indexed_properties(indexed_properties)
|
|
|
|
, m_index(staring_index)
|
|
|
|
, m_skip_empty(skip_empty)
|
|
|
|
{
|
2020-10-20 00:24:53 +01:00
|
|
|
if (m_skip_empty)
|
|
|
|
skip_empty_indices();
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
IndexedPropertyIterator& IndexedPropertyIterator::operator++()
|
|
|
|
{
|
|
|
|
m_index++;
|
|
|
|
|
2020-10-20 00:24:53 +01:00
|
|
|
if (m_skip_empty)
|
|
|
|
skip_empty_indices();
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
IndexedPropertyIterator& IndexedPropertyIterator::operator*()
|
|
|
|
{
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IndexedPropertyIterator::operator!=(const IndexedPropertyIterator& other) const
|
|
|
|
{
|
|
|
|
return m_index != other.m_index;
|
|
|
|
}
|
|
|
|
|
2021-06-17 03:12:41 +03:00
|
|
|
ValueAndAttributes IndexedPropertyIterator::value_and_attributes(Object* this_object, AllowSideEffects allow_side_effects)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
|
|
|
if (m_index < m_indexed_properties.array_like_size())
|
2021-06-17 03:12:41 +03:00
|
|
|
return m_indexed_properties.get(this_object, m_index, allow_side_effects).value_or({});
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2020-10-20 00:24:53 +01:00
|
|
|
void IndexedPropertyIterator::skip_empty_indices()
|
|
|
|
{
|
|
|
|
auto indices = m_indexed_properties.indices();
|
|
|
|
for (auto i : indices) {
|
|
|
|
if (i < m_index)
|
|
|
|
continue;
|
|
|
|
m_index = i;
|
2020-11-07 00:18:57 +00:00
|
|
|
return;
|
2020-10-20 00:24:53 +01:00
|
|
|
}
|
2020-11-07 00:18:57 +00:00
|
|
|
m_index = m_indexed_properties.array_like_size();
|
2020-10-20 00:24:53 +01:00
|
|
|
}
|
|
|
|
|
2021-06-17 03:12:41 +03:00
|
|
|
Optional<ValueAndAttributes> IndexedProperties::get(Object* this_object, u32 index, AllowSideEffects allow_side_effects) const
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
|
|
|
auto result = m_storage->get(index);
|
2021-06-17 03:12:41 +03:00
|
|
|
if (allow_side_effects == AllowSideEffects::No)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
return result;
|
|
|
|
if (!result.has_value())
|
|
|
|
return {};
|
2020-09-08 13:17:37 +04:30
|
|
|
auto& value = result.value();
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
if (value.value.is_accessor()) {
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(this_object);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
auto& accessor = value.value.as_accessor();
|
|
|
|
return ValueAndAttributes { accessor.call_getter(this_object), value.attributes };
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-06-17 03:12:41 +03:00
|
|
|
void IndexedProperties::put(Object* this_object, u32 index, Value value, PropertyAttributes attributes, AllowSideEffects allow_side_effects)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
2021-03-21 11:33:45 +01:00
|
|
|
if (m_storage->is_simple_storage() && (attributes != default_attributes || index > (array_like_size() + SPARSE_ARRAY_HOLE_THRESHOLD))) {
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
switch_to_generic_storage();
|
2021-03-21 11:33:45 +01:00
|
|
|
}
|
|
|
|
|
2021-06-17 03:12:41 +03:00
|
|
|
if (m_storage->is_simple_storage() || allow_side_effects == AllowSideEffects::No) {
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
m_storage->put(index, value, attributes);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto value_here = m_storage->get(index);
|
|
|
|
if (value_here.has_value() && value_here.value().value.is_accessor()) {
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(this_object);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
value_here.value().value.as_accessor().call_setter(this_object, value);
|
|
|
|
} else {
|
|
|
|
m_storage->put(index, value, attributes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IndexedProperties::remove(u32 index)
|
|
|
|
{
|
|
|
|
auto result = m_storage->get(index);
|
|
|
|
if (!result.has_value())
|
|
|
|
return true;
|
2020-06-02 17:13:09 -07:00
|
|
|
if (!result.value().attributes.is_configurable())
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
return false;
|
|
|
|
m_storage->remove(index);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-02 17:13:09 -07:00
|
|
|
void IndexedProperties::insert(u32 index, Value value, PropertyAttributes attributes)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
2021-03-21 11:33:45 +01:00
|
|
|
if (m_storage->is_simple_storage()) {
|
|
|
|
if (attributes != default_attributes
|
|
|
|
|| index > (array_like_size() + SPARSE_ARRAY_HOLE_THRESHOLD)) {
|
|
|
|
switch_to_generic_storage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_storage->insert(index, value, attributes);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
}
|
|
|
|
|
2020-09-08 13:26:54 +04:30
|
|
|
ValueAndAttributes IndexedProperties::take_first(Object* this_object)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
|
|
|
auto first = m_storage->take_first();
|
|
|
|
if (first.value.is_accessor())
|
|
|
|
return { first.value.as_accessor().call_getter(this_object), first.attributes };
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
2020-09-08 13:26:54 +04:30
|
|
|
ValueAndAttributes IndexedProperties::take_last(Object* this_object)
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
{
|
|
|
|
auto last = m_storage->take_last();
|
|
|
|
if (last.value.is_accessor())
|
|
|
|
return { last.value.as_accessor().call_getter(this_object), last.attributes };
|
|
|
|
return last;
|
|
|
|
}
|
|
|
|
|
2020-09-01 19:45:29 +01:00
|
|
|
void IndexedProperties::set_array_like_size(size_t new_size)
|
|
|
|
{
|
2021-03-30 13:32:19 +02:00
|
|
|
auto current_array_like_size = array_like_size();
|
|
|
|
|
|
|
|
// We can't use simple storage for lengths that don't fit in an i32.
|
|
|
|
// Also, to avoid gigantic unused storage allocations, let's put an (arbitrary) 4M cap on simple storage here.
|
|
|
|
// This prevents something like "a = []; a.length = 0x80000000;" from allocating 2G entries.
|
|
|
|
if (m_storage->is_simple_storage()
|
|
|
|
&& (new_size > NumericLimits<i32>::max()
|
2021-05-17 23:13:37 +01:00
|
|
|
|| (current_array_like_size < LENGTH_SETTER_GENERIC_STORAGE_THRESHOLD && new_size > LENGTH_SETTER_GENERIC_STORAGE_THRESHOLD))) {
|
2021-03-30 13:32:19 +02:00
|
|
|
switch_to_generic_storage();
|
|
|
|
}
|
|
|
|
|
2020-09-01 19:45:29 +01:00
|
|
|
m_storage->set_array_like_size(new_size);
|
|
|
|
}
|
|
|
|
|
2020-10-20 00:24:53 +01:00
|
|
|
Vector<u32> IndexedProperties::indices() const
|
|
|
|
{
|
|
|
|
if (m_storage->is_simple_storage()) {
|
|
|
|
const auto& storage = static_cast<const SimpleIndexedPropertyStorage&>(*m_storage);
|
|
|
|
const auto& elements = storage.elements();
|
2021-03-21 11:33:45 +01:00
|
|
|
Vector<u32> indices;
|
2020-10-20 00:24:53 +01:00
|
|
|
indices.ensure_capacity(storage.array_like_size());
|
|
|
|
for (size_t i = 0; i < elements.size(); ++i) {
|
|
|
|
if (!elements.at(i).is_empty())
|
|
|
|
indices.unchecked_append(i);
|
|
|
|
}
|
2021-03-21 11:33:45 +01:00
|
|
|
return indices;
|
2020-10-20 00:24:53 +01:00
|
|
|
}
|
2021-03-21 11:33:45 +01:00
|
|
|
const auto& storage = static_cast<const GenericIndexedPropertyStorage&>(*m_storage);
|
|
|
|
auto indices = storage.sparse_elements().keys();
|
|
|
|
quick_sort(indices);
|
2020-10-20 00:24:53 +01:00
|
|
|
return indices;
|
|
|
|
}
|
|
|
|
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
void IndexedProperties::switch_to_generic_storage()
|
|
|
|
{
|
2020-09-08 13:17:37 +04:30
|
|
|
auto& storage = static_cast<SimpleIndexedPropertyStorage&>(*m_storage);
|
LibJS: Object index properties have descriptors; Handle sparse indices
This patch adds an IndexedProperties object for storing indexed
properties within an Object. This accomplishes two goals: indexed
properties now have an associated descriptor, and objects now gracefully
handle sparse properties.
The IndexedProperties class is a wrapper around two other classes, one
for simple indexed properties storage, and one for general indexed
property storage. Simple indexed property storage is the common-case,
and is simply a vector of properties which all have attributes of
default_attributes (writable, enumerable, and configurable).
General indexed property storage is for a collection of indexed
properties where EITHER one or more properties have attributes other
than default_attributes OR there is a property with a large index (in
particular, large is '200' or higher).
Indexed properties are now treated relatively the same as storage within
the various Object methods. Additionally, there is a custom iterator
class for IndexedProperties which makes iteration easy. The iterator
skips empty values by default, but can be configured otherwise.
Likewise, it evaluates getters by default, but can be set not to.
2020-05-27 11:35:09 -07:00
|
|
|
m_storage = make<GenericIndexedPropertyStorage>(move(storage));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|