diff --git a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
index 6b5d0f72ee0..1093c7e7bc5 100644
--- a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
+++ b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -599,7 +600,8 @@ void EventLoop::perform_a_microtask_checkpoint()
global->notify_about_rejected_promises({});
}
- // FIXME: 5. Cleanup Indexed Database transactions.
+ // 5. Cleanup Indexed Database transactions.
+ IndexedDB::cleanup_indexed_database_transactions(*this);
// 6. Perform ClearKeptObjects().
vm().finish_execution_generation();
diff --git a/Libraries/LibWeb/IndexedDB/IDBTransaction.h b/Libraries/LibWeb/IndexedDB/IDBTransaction.h
index 08040edede4..4b486ba6d7a 100644
--- a/Libraries/LibWeb/IndexedDB/IDBTransaction.h
+++ b/Libraries/LibWeb/IndexedDB/IDBTransaction.h
@@ -47,6 +47,7 @@ public:
[[nodiscard]] RequestList& request_list() { return m_request_list; }
[[nodiscard]] ReadonlySpan> scope() const { return m_scope; }
[[nodiscard]] String uuid() const { return m_uuid; }
+ [[nodiscard]] GC::Ptr cleanup_event_loop() const { return m_cleanup_event_loop; }
void set_mode(Bindings::IDBTransactionMode mode) { m_mode = mode; }
void set_error(GC::Ptr error) { m_error = error; }
diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp
index 5f953a082e8..ae9f7b3ae68 100644
--- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp
+++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp
@@ -2051,4 +2051,32 @@ void queue_a_database_task(GC::Ref> steps)
HTML::queue_a_task(HTML::Task::Source::DatabaseAccess, nullptr, nullptr, steps);
}
+// https://w3c.github.io/IndexedDB/#cleanup-indexed-database-transactions
+bool cleanup_indexed_database_transactions(GC::Ref event_loop)
+{
+ bool has_matching_event_loop = false;
+
+ Database::for_each_database([&has_matching_event_loop, event_loop](GC::Root const& database) {
+ for (auto const& connection : database->associated_connections()) {
+ for (auto const& transaction : connection->transactions()) {
+
+ // 2. For each transaction transaction with cleanup event loop matching the current event loop:
+ if (transaction->cleanup_event_loop() == event_loop) {
+ has_matching_event_loop = true;
+
+ // 1. Set transaction’s state to inactive.
+ transaction->set_state(IDBTransaction::TransactionState::Inactive);
+
+ // 2. Clear transaction’s cleanup event loop.
+ transaction->set_cleanup_event_loop(nullptr);
+ }
+ }
+ }
+ });
+
+ // 1. If there are no transactions with cleanup event loop matching the current event loop, return false.
+ // 3. Return true.
+ return has_matching_event_loop;
+}
+
}
diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h
index 373e77050a5..ce04060a78c 100644
--- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h
+++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.h
@@ -57,5 +57,6 @@ JS::Value retrieve_a_value_from_an_index(JS::Realm&, GC::Ref, GC::Ref retrieve_multiple_referenced_values_from_an_index(JS::Realm&, GC::Ref, GC::Ref, Optional);
GC::Ref retrieve_multiple_values_from_an_index(JS::Realm&, GC::Ref, GC::Ref, Optional);
void queue_a_database_task(GC::Ref>);
+bool cleanup_indexed_database_transactions(GC::Ref);
}
diff --git a/Libraries/LibWeb/IndexedDB/Internal/Database.cpp b/Libraries/LibWeb/IndexedDB/Internal/Database.cpp
index cf4f5fd945c..9fa881e01d4 100644
--- a/Libraries/LibWeb/IndexedDB/Internal/Database.cpp
+++ b/Libraries/LibWeb/IndexedDB/Internal/Database.cpp
@@ -14,6 +14,15 @@ namespace Web::IndexedDB {
using IDBDatabaseMapping = HashMap>>;
static IDBDatabaseMapping m_databases;
+void Database::for_each_database(AK::Function const&)> const& visitor)
+{
+ for (auto const& [key, mapping] : m_databases) {
+ for (auto const& database_mapping : mapping) {
+ visitor(database_mapping.value);
+ }
+ }
+}
+
GC_DEFINE_ALLOCATOR(Database);
Database::~Database() = default;
diff --git a/Libraries/LibWeb/IndexedDB/Internal/Database.h b/Libraries/LibWeb/IndexedDB/Internal/Database.h
index ebc5c24485d..721a61855f5 100644
--- a/Libraries/LibWeb/IndexedDB/Internal/Database.h
+++ b/Libraries/LibWeb/IndexedDB/Internal/Database.h
@@ -53,6 +53,8 @@ public:
[[nodiscard]] static ErrorOr> create_for_key_and_name(JS::Realm&, StorageAPI::StorageKey&, String&);
[[nodiscard]] static ErrorOr delete_for_key_and_name(StorageAPI::StorageKey&, String&);
+ static void for_each_database(AK::Function const&)> const& visitor);
+
[[nodiscard]] static GC::Ref create(JS::Realm&, String const&);
virtual ~Database();