diff --git a/Libraries/LibWeb/IndexedDB/IDBDatabase.cpp b/Libraries/LibWeb/IndexedDB/IDBDatabase.cpp index 72d858a26e3..339a804bc0e 100644 --- a/Libraries/LibWeb/IndexedDB/IDBDatabase.cpp +++ b/Libraries/LibWeb/IndexedDB/IDBDatabase.cpp @@ -18,10 +18,10 @@ GC_DEFINE_ALLOCATOR(IDBDatabase); IDBDatabase::IDBDatabase(JS::Realm& realm, Database& db) : EventTarget(realm) , m_name(db.name()) - , m_object_store_names(HTML::DOMStringList::create(realm, {})) , m_associated_database(db) { db.associate(*this); + db.object_stores().copy_to(m_object_store_set); } IDBDatabase::~IDBDatabase() = default; @@ -40,7 +40,7 @@ void IDBDatabase::initialize(JS::Realm& realm) void IDBDatabase::visit_edges(Visitor& visitor) { Base::visit_edges(visitor); - visitor.visit(m_object_store_names); + visitor.visit(m_object_store_set); visitor.visit(m_associated_database); } @@ -138,4 +138,16 @@ WebIDL::ExceptionOr> IDBDatabase::create_object_store(St return IDBObjectStore::create(realm, object_store, *transaction); } +// https://w3c.github.io/IndexedDB/#dom-idbdatabase-objectstorenames +GC::Ref IDBDatabase::object_store_names() +{ + // 1. Let names be a list of the names of the object stores in this's object store set. + Vector names; + for (auto const& object_store : this->object_store_set()) + names.append(object_store->name()); + + // 2. Return the result (a DOMStringList) of creating a sorted name list with names. + return create_a_sorted_name_list(realm(), names); +} + } diff --git a/Libraries/LibWeb/IndexedDB/IDBDatabase.h b/Libraries/LibWeb/IndexedDB/IDBDatabase.h index b76b18010b9..fa184b8c5cc 100644 --- a/Libraries/LibWeb/IndexedDB/IDBDatabase.h +++ b/Libraries/LibWeb/IndexedDB/IDBDatabase.h @@ -46,13 +46,14 @@ public: void set_close_pending(bool close_pending) { m_close_pending = close_pending; } void set_state(ConnectionState state) { m_state = state; } - [[nodiscard]] GC::Ref object_store_names() { return m_object_store_names; } [[nodiscard]] String name() const { return m_name; } [[nodiscard]] u64 version() const { return m_version; } [[nodiscard]] bool close_pending() const { return m_close_pending; } [[nodiscard]] ConnectionState state() const { return m_state; } [[nodiscard]] GC::Ref associated_database() { return m_associated_database; } + [[nodiscard]] ReadonlySpan> object_store_set() { return m_object_store_set; } + [[nodiscard]] GC::Ref object_store_names(); WebIDL::ExceptionOr> create_object_store(String const&, IDBObjectStoreParameters const&); void close(); @@ -75,13 +76,17 @@ protected: private: u64 m_version { 0 }; String m_name; - GC::Ref m_object_store_names; // Each connection has a close pending flag which is initially false. bool m_close_pending { false }; + // When a connection is initially created it is in an opened state. ConnectionState m_state { ConnectionState::Open }; + // A connection has an object store set, which is initialized to the set of object stores in the associated database when the connection is created. + // The contents of the set will remain constant except when an upgrade transaction is live. + Vector> m_object_store_set; + // NOTE: There is an associated database in the spec, but there is no mention where it is assigned, nor where its from // So we stash the one we have when opening a connection. GC::Ref m_associated_database; diff --git a/Libraries/LibWeb/IndexedDB/Internal/Database.h b/Libraries/LibWeb/IndexedDB/Internal/Database.h index c5ac1d03eb6..c2d5378dace 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Database.h +++ b/Libraries/LibWeb/IndexedDB/Internal/Database.h @@ -40,6 +40,7 @@ public: return connections; } + ReadonlySpan> object_stores() { return m_object_stores; } bool has_object_store_named(String const& name) const; void add_object_store(GC::Ref object_store) { m_object_stores.append(object_store); }