LibWeb: Change Storage{Bottle,Bucket,Shelf} to be GC-allocated

In upcoming changes StorageBottle will own pointers to GC-allocated
objects, so it needs to be a GC-allocated object itself to avoid
introducing more GC roots.
This commit is contained in:
Aliaksandr Kalenik 2025-06-11 18:51:22 +02:00 committed by Alexander Kalenik
commit f53559cb55
Notes: github-actions[bot] 2025-06-12 15:06:02 +00:00
12 changed files with 117 additions and 44 deletions

View file

@ -25,12 +25,12 @@ static HashTable<GC::RawRef<Storage>>& all_storages()
return storages;
}
GC::Ref<Storage> Storage::create(JS::Realm& realm, Type type, NonnullRefPtr<StorageAPI::StorageBottle> storage_bottle)
GC::Ref<Storage> Storage::create(JS::Realm& realm, Type type, GC::Ref<StorageAPI::StorageBottle> storage_bottle)
{
return realm.create<Storage>(realm, type, move(storage_bottle));
}
Storage::Storage(JS::Realm& realm, Type type, NonnullRefPtr<StorageAPI::StorageBottle> storage_bottle)
Storage::Storage(JS::Realm& realm, Type type, GC::Ref<StorageAPI::StorageBottle> storage_bottle)
: Bindings::PlatformObject(realm)
, m_type(type)
, m_storage_bottle(move(storage_bottle))
@ -65,6 +65,12 @@ void Storage::finalize()
all_storages().remove(*this);
}
void Storage::visit_edges(GC::Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_storage_bottle);
}
// https://html.spec.whatwg.org/multipage/webstorage.html#dom-storage-length
size_t Storage::length() const
{

View file

@ -27,7 +27,7 @@ public:
Session,
};
[[nodiscard]] static GC::Ref<Storage> create(JS::Realm&, Type, NonnullRefPtr<StorageAPI::StorageBottle>);
[[nodiscard]] static GC::Ref<Storage> create(JS::Realm&, Type, GC::Ref<StorageAPI::StorageBottle>);
~Storage();
@ -44,10 +44,11 @@ public:
void dump() const;
private:
Storage(JS::Realm&, Type, NonnullRefPtr<StorageAPI::StorageBottle>);
Storage(JS::Realm&, Type, GC::Ref<StorageAPI::StorageBottle>);
virtual void initialize(JS::Realm&) override;
virtual void finalize() override;
virtual void visit_edges(GC::Cell::Visitor&) override;
// ^PlatformObject
virtual Optional<JS::Value> item_value(size_t index) const override;
@ -61,7 +62,7 @@ private:
void broadcast(Optional<String> const& key, Optional<String> const& old_value, Optional<String> const& new_value);
Type m_type {};
NonnullRefPtr<StorageAPI::StorageBottle> m_storage_bottle;
GC::Ref<StorageAPI::StorageBottle> m_storage_bottle;
u64 m_stored_bytes { 0 };
};

View file

@ -50,6 +50,7 @@ static RefPtr<Gfx::SkiaBackendContext> get_skia_backend_context()
TraversableNavigable::TraversableNavigable(GC::Ref<Page> page)
: Navigable(page)
, m_storage_shed(StorageAPI::StorageShed::create(page->heap()))
, m_session_history_traversal_queue(vm().heap().allocate<SessionHistoryTraversalQueue>())
{
if (!page->client().is_svg_page_client()) {
@ -75,6 +76,7 @@ void TraversableNavigable::visit_edges(Cell::Visitor& visitor)
Base::visit_edges(visitor);
visitor.visit(m_session_history_entries);
visitor.visit(m_session_history_traversal_queue);
visitor.visit(m_storage_shed);
}
static OrderedHashTable<TraversableNavigable*>& user_agent_top_level_traversable_set()

View file

@ -164,7 +164,7 @@ private:
// https://storage.spec.whatwg.org/#traversable-navigable-storage-shed
// A traversable navigable holds a storage shed, which is a storage shed. A traversable navigables storage shed holds all session storage data.
StorageAPI::StorageShed m_storage_shed;
GC::Ref<StorageAPI::StorageShed> m_storage_shed;
GC::Ref<SessionHistoryTraversalQueue> m_session_history_traversal_queue;

View file

@ -471,7 +471,7 @@ WebIDL::ExceptionOr<GC::Ref<Storage>> Window::local_storage()
return WebIDL::SecurityError::create(realm, "localStorage is not available"_string);
// 4. Let storage be a new Storage object whose map is map.
auto storage = Storage::create(realm, Storage::Type::Session, map.release_nonnull());
auto storage = Storage::create(realm, Storage::Type::Session, *map);
// 5. Set this's associated Document's local storage holder to storage.
associated_document.set_local_storage_holder(storage);
@ -498,7 +498,7 @@ WebIDL::ExceptionOr<GC::Ref<Storage>> Window::session_storage()
return WebIDL::SecurityError::create(realm, "sessionStorage is not available"_string);
// 4. Let storage be a new Storage object whose map is map.
auto storage = Storage::create(realm, Storage::Type::Session, map.release_nonnull());
auto storage = Storage::create(realm, Storage::Type::Session, *map);
// 5. Set this's associated Document's session storage holder to storage.
associated_document.set_session_storage_holder(storage);