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();