diff --git a/Libraries/LibWeb/IndexedDB/IDBTransaction.h b/Libraries/LibWeb/IndexedDB/IDBTransaction.h index 5ca6ee15325..194d40c7023 100644 --- a/Libraries/LibWeb/IndexedDB/IDBTransaction.h +++ b/Libraries/LibWeb/IndexedDB/IDBTransaction.h @@ -56,6 +56,7 @@ public: [[nodiscard]] bool is_upgrade_transaction() const { return m_mode == Bindings::IDBTransactionMode::Versionchange; } [[nodiscard]] bool is_readonly() const { return m_mode == Bindings::IDBTransactionMode::Readonly; } [[nodiscard]] bool is_readwrite() const { return m_mode == Bindings::IDBTransactionMode::Readwrite; } + [[nodiscard]] bool is_finished() const { return m_state == TransactionState::Finished; } WebIDL::ExceptionOr abort(); diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp index e51d4822afb..abfe6d31b8d 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp @@ -315,16 +315,41 @@ ErrorOr> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input // https://w3c.github.io/IndexedDB/#close-a-database-connection void close_a_database_connection(GC::Ref connection, bool forced) { + auto& realm = connection->realm(); + // 1. Set connection’s close pending flag to true. connection->set_close_pending(true); - // FIXME: 2. If the forced flag is true, then for each transaction created using connection run abort a transaction with transaction and newly created "AbortError" DOMException. - // FIXME: 3. Wait for all transactions created using connection to complete. Once they are complete, connection is closed. + // 2. If the forced flag is true, then for each transaction created using connection run abort a transaction with transaction and newly created "AbortError" DOMException. + if (forced) { + for (auto const& transaction : connection->transactions()) { + abort_a_transaction(*transaction, WebIDL::AbortError::create(realm, "Connection was closed"_string)); + } + } + + // 3. Wait for all transactions created using connection to complete. Once they are complete, connection is closed. + HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [connection]() { + if constexpr (IDB_DEBUG) { + dbgln("close_a_database_connection: waiting for step 3"); + dbgln("transactions created using connection:"); + for (auto const& transaction : connection->transactions()) { + dbgln(" - {} - {}", transaction->uuid(), (u8)transaction->state()); + } + } + + for (auto const& transaction : connection->transactions()) { + if (!transaction->is_finished()) + return false; + } + + return true; + })); + connection->set_state(IDBDatabase::ConnectionState::Closed); // 4. If the forced flag is true, then fire an event named close at connection. if (forced) - connection->dispatch_event(DOM::Event::create(connection->realm(), HTML::EventNames::close)); + connection->dispatch_event(DOM::Event::create(realm, HTML::EventNames::close)); } // https://w3c.github.io/IndexedDB/#upgrade-a-database