IndexedProperties.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/NonnullOwnPtr.h>
  8. #include <LibJS/Runtime/Shape.h>
  9. #include <LibJS/Runtime/Value.h>
  10. namespace JS {
  11. struct ValueAndAttributes {
  12. Value value;
  13. PropertyAttributes attributes { default_attributes };
  14. };
  15. class IndexedProperties;
  16. class IndexedPropertyIterator;
  17. class GenericIndexedPropertyStorage;
  18. class IndexedPropertyStorage {
  19. public:
  20. virtual ~IndexedPropertyStorage() {};
  21. virtual bool has_index(u32 index) const = 0;
  22. virtual Optional<ValueAndAttributes> get(u32 index) const = 0;
  23. virtual void put(u32 index, Value value, PropertyAttributes attributes = default_attributes) = 0;
  24. virtual void remove(u32 index) = 0;
  25. virtual void insert(u32 index, Value value, PropertyAttributes attributes = default_attributes) = 0;
  26. virtual ValueAndAttributes take_first() = 0;
  27. virtual ValueAndAttributes take_last() = 0;
  28. virtual size_t size() const = 0;
  29. virtual size_t array_like_size() const = 0;
  30. virtual void set_array_like_size(size_t new_size) = 0;
  31. virtual bool is_simple_storage() const { return false; }
  32. };
  33. class SimpleIndexedPropertyStorage final : public IndexedPropertyStorage {
  34. public:
  35. SimpleIndexedPropertyStorage() = default;
  36. explicit SimpleIndexedPropertyStorage(Vector<Value>&& initial_values);
  37. virtual bool has_index(u32 index) const override;
  38. virtual Optional<ValueAndAttributes> get(u32 index) const override;
  39. virtual void put(u32 index, Value value, PropertyAttributes attributes = default_attributes) override;
  40. virtual void remove(u32 index) override;
  41. virtual void insert(u32 index, Value value, PropertyAttributes attributes = default_attributes) override;
  42. virtual ValueAndAttributes take_first() override;
  43. virtual ValueAndAttributes take_last() override;
  44. virtual size_t size() const override { return m_packed_elements.size(); }
  45. virtual size_t array_like_size() const override { return m_array_size; }
  46. virtual void set_array_like_size(size_t new_size) override;
  47. virtual bool is_simple_storage() const override { return true; }
  48. const Vector<Value>& elements() const { return m_packed_elements; }
  49. private:
  50. friend GenericIndexedPropertyStorage;
  51. void grow_storage_if_needed();
  52. size_t m_array_size { 0 };
  53. Vector<Value> m_packed_elements;
  54. };
  55. class GenericIndexedPropertyStorage final : public IndexedPropertyStorage {
  56. public:
  57. explicit GenericIndexedPropertyStorage(SimpleIndexedPropertyStorage&&);
  58. virtual bool has_index(u32 index) const override;
  59. virtual Optional<ValueAndAttributes> get(u32 index) const override;
  60. virtual void put(u32 index, Value value, PropertyAttributes attributes = default_attributes) override;
  61. virtual void remove(u32 index) override;
  62. virtual void insert(u32 index, Value value, PropertyAttributes attributes = default_attributes) override;
  63. virtual ValueAndAttributes take_first() override;
  64. virtual ValueAndAttributes take_last() override;
  65. virtual size_t size() const override { return m_sparse_elements.size(); }
  66. virtual size_t array_like_size() const override { return m_array_size; }
  67. virtual void set_array_like_size(size_t new_size) override;
  68. const HashMap<u32, ValueAndAttributes>& sparse_elements() const { return m_sparse_elements; }
  69. private:
  70. size_t m_array_size { 0 };
  71. HashMap<u32, ValueAndAttributes> m_sparse_elements;
  72. };
  73. class IndexedPropertyIterator {
  74. public:
  75. IndexedPropertyIterator(const IndexedProperties&, u32 starting_index, bool skip_empty);
  76. IndexedPropertyIterator& operator++();
  77. IndexedPropertyIterator& operator*();
  78. bool operator!=(const IndexedPropertyIterator&) const;
  79. u32 index() const { return m_index; };
  80. ValueAndAttributes value_and_attributes(Object* this_object, AllowSideEffects = AllowSideEffects::Yes);
  81. private:
  82. void skip_empty_indices();
  83. const IndexedProperties& m_indexed_properties;
  84. u32 m_index;
  85. bool m_skip_empty;
  86. };
  87. class IndexedProperties {
  88. public:
  89. IndexedProperties() = default;
  90. explicit IndexedProperties(Vector<Value> values)
  91. : m_storage(make<SimpleIndexedPropertyStorage>(move(values)))
  92. {
  93. }
  94. bool has_index(u32 index) const { return m_storage->has_index(index); }
  95. Optional<ValueAndAttributes> get(Object* this_object, u32 index, AllowSideEffects = AllowSideEffects::Yes) const;
  96. void put(Object* this_object, u32 index, Value value, PropertyAttributes attributes = default_attributes, AllowSideEffects allow_side_effects = AllowSideEffects::Yes);
  97. bool remove(u32 index);
  98. void insert(u32 index, Value value, PropertyAttributes attributes = default_attributes);
  99. ValueAndAttributes take_first(Object* this_object);
  100. ValueAndAttributes take_last(Object* this_object);
  101. void append(Value value, PropertyAttributes attributes = default_attributes) { put(nullptr, array_like_size(), value, attributes, AllowSideEffects::No); }
  102. IndexedPropertyIterator begin(bool skip_empty = true) const { return IndexedPropertyIterator(*this, 0, skip_empty); };
  103. IndexedPropertyIterator end() const { return IndexedPropertyIterator(*this, array_like_size(), false); };
  104. bool is_empty() const { return array_like_size() == 0; }
  105. size_t array_like_size() const { return m_storage->array_like_size(); }
  106. void set_array_like_size(size_t);
  107. Vector<u32> indices() const;
  108. template<typename Callback>
  109. void for_each_value(Callback callback)
  110. {
  111. if (m_storage->is_simple_storage()) {
  112. for (auto& value : static_cast<SimpleIndexedPropertyStorage&>(*m_storage).elements())
  113. callback(value);
  114. } else {
  115. for (auto& element : static_cast<const GenericIndexedPropertyStorage&>(*m_storage).sparse_elements())
  116. callback(element.value.value);
  117. }
  118. }
  119. private:
  120. void switch_to_generic_storage();
  121. NonnullOwnPtr<IndexedPropertyStorage> m_storage { make<SimpleIndexedPropertyStorage>() };
  122. };
  123. }