LibWeb/IDB: Add some debug output

This commit is contained in:
stelar7 2025-04-02 10:28:04 +02:00
parent 90ec4cee11
commit 6646759569
9 changed files with 75 additions and 0 deletions

View file

@ -114,6 +114,10 @@
# cmakedefine01 ICO_DEBUG
#endif
#ifndef IDB_DEBUG
# cmakedefine01 IDB_DEBUG
#endif
#ifndef IDL_DEBUG
# cmakedefine01 IDL_DEBUG
#endif

View file

@ -6,6 +6,7 @@
#include <LibWeb/Bindings/IDBDatabasePrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Crypto/Crypto.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/IndexedDB/IDBDatabase.h>
#include <LibWeb/IndexedDB/IDBObjectStore.h>
@ -20,6 +21,7 @@ IDBDatabase::IDBDatabase(JS::Realm& realm, Database& db)
, m_name(db.name())
, m_associated_database(db)
{
m_uuid = MUST(Crypto::generate_random_uuid());
db.associate(*this);
m_object_store_set = Vector<GC::Ref<ObjectStore>> { db.object_stores() };
}

View file

@ -46,6 +46,7 @@ public:
void set_close_pending(bool close_pending) { m_close_pending = close_pending; }
void set_state(ConnectionState state) { m_state = state; }
[[nodiscard]] String uuid() const { return m_uuid; }
[[nodiscard]] String name() const { return m_name; }
[[nodiscard]] u64 version() const { return m_version; }
[[nodiscard]] bool close_pending() const { return m_close_pending; }
@ -95,6 +96,9 @@ private:
// 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<Database> m_associated_database;
// NOTE: Used for debug purposes
String m_uuid;
};
}

View file

@ -7,6 +7,7 @@
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Crypto/Crypto.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/IndexedDB/IDBRequest.h>
#include <LibWeb/IndexedDB/IDBTransaction.h>
@ -21,6 +22,7 @@ IDBRequest::IDBRequest(JS::Realm& realm, IDBRequestSource source)
: EventTarget(realm)
, m_source(source)
{
m_uuid = MUST(Crypto::generate_random_uuid());
}
void IDBRequest::initialize(JS::Realm& realm)

View file

@ -30,6 +30,7 @@ public:
[[nodiscard]] bool processed() const { return m_processed; }
[[nodiscard]] IDBRequestSource source() const { return m_source; }
[[nodiscard]] GC::Ptr<IDBTransaction> transaction() const { return m_transaction; }
[[nodiscard]] String uuid() const { return m_uuid; }
[[nodiscard]] Bindings::IDBRequestReadyState ready_state() const;
[[nodiscard]] WebIDL::ExceptionOr<GC::Ptr<WebIDL::DOMException>> error() const;
@ -56,15 +57,22 @@ protected:
private:
// A request has a processed flag which is initially false.
bool m_processed { false };
// A request has a done flag which is initially false.
bool m_done { false };
// A request has a result and an error
JS::Value m_result;
GC::Ptr<WebIDL::DOMException> m_error;
// A request has a source object.
IDBRequestSource m_source;
// A request has a transaction which is initially null.
GC::Ptr<IDBTransaction> m_transaction;
// NOTE: Used for debug purposes
String m_uuid;
};
}

View file

@ -5,6 +5,7 @@
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Crypto/Crypto.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/IndexedDB/IDBTransaction.h>
#include <LibWeb/IndexedDB/Internal/Algorithms.h>
@ -22,6 +23,7 @@ IDBTransaction::IDBTransaction(JS::Realm& realm, GC::Ref<IDBDatabase> connection
, m_durability(durability)
, m_scope(move(scopes))
{
m_uuid = MUST(Crypto::generate_random_uuid());
}
GC::Ref<IDBTransaction> IDBTransaction::create(JS::Realm& realm, GC::Ref<IDBDatabase> connection, Bindings::IDBTransactionMode mode, Bindings::IDBTransactionDurability durability = Bindings::IDBTransactionDurability::Default, Vector<GC::Ref<ObjectStore>> scopes = {})

View file

@ -45,6 +45,7 @@ public:
[[nodiscard]] bool aborted() const { return m_aborted; }
[[nodiscard]] GC::Ref<HTML::DOMStringList> object_store_names();
[[nodiscard]] ReadonlySpan<GC::Ref<ObjectStore>> scope() const { return m_scope; }
[[nodiscard]] String uuid() const { return m_uuid; }
void set_mode(Bindings::IDBTransactionMode mode) { m_mode = mode; }
void set_state(TransactionState state) { m_state = state; }
@ -100,5 +101,8 @@ private:
// A transaction optionally has a cleanup event loop which is an event loop.
GC::Ptr<HTML::EventLoop> m_cleanup_event_loop;
// NOTE: Used for debug purposes
String m_uuid;
};
}

View file

@ -36,9 +36,18 @@ WebIDL::ExceptionOr<GC::Ref<IDBDatabase>> open_a_database_connection(JS::Realm&
// 2. Add request to queue.
queue.append(request);
dbgln_if(IDB_DEBUG, "open_a_database_connection: added request {} to queue", request->uuid());
// 3. Wait until all previous requests in queue have been processed.
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [queue, request]() {
if constexpr (IDB_DEBUG) {
dbgln("open_a_database_connection: waiting for step 3");
dbgln("requests in queue:");
for (auto const& item : queue) {
dbgln("[{}] - {} = {}", item == request ? "x"sv : " "sv, item->uuid(), item->processed() ? "processed"sv : "not processed"sv);
}
}
return queue.all_previous_requests_processed(request);
}));
@ -71,6 +80,7 @@ WebIDL::ExceptionOr<GC::Ref<IDBDatabase>> open_a_database_connection(JS::Realm&
// 8. Let connection be a new connection to db.
auto connection = IDBDatabase::create(realm, *db);
dbgln_if(IDB_DEBUG, "Created new connection with UUID: {}", connection->uuid());
// 9. Set connections version to version.
connection->set_version(version);
@ -97,6 +107,11 @@ WebIDL::ExceptionOr<GC::Ref<IDBDatabase>> open_a_database_connection(JS::Realm&
// 3. Wait for all of the events to be fired.
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [&events_to_fire, &events_fired]() {
if constexpr (IDB_DEBUG) {
dbgln("open_a_database_connection: waiting for step 10.3");
dbgln("events_fired: {}, events_to_fire: {}", events_fired, events_to_fire);
}
return events_fired == events_to_fire;
}));
@ -112,6 +127,14 @@ WebIDL::ExceptionOr<GC::Ref<IDBDatabase>> open_a_database_connection(JS::Realm&
// 5. Wait until all connections in openConnections are closed.
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [open_connections]() {
if constexpr (IDB_DEBUG) {
dbgln("open_a_database_connection: waiting for step 10.5");
dbgln("open connections: {}", open_connections.size());
for (auto const& connection : open_connections) {
dbgln(" - {}", connection->uuid());
}
}
for (auto const& entry : open_connections) {
if (entry->state() != IDBDatabase::ConnectionState::Closed) {
return false;
@ -314,6 +337,7 @@ GC::Ref<IDBTransaction> upgrade_a_database(JS::Realm& realm, GC::Ref<IDBDatabase
// 2. Let transaction be a new upgrade transaction with connection used as connection.
// 3. Set transactions scope to connections object store set.
auto transaction = IDBTransaction::create(realm, connection, Bindings::IDBTransactionMode::Versionchange, Bindings::IDBTransactionDurability::Default, Vector<GC::Ref<ObjectStore>> { connection->object_store_set() });
dbgln_if(IDB_DEBUG, "Created new upgrade transaction with UUID: {}", transaction->uuid());
// 4. Set dbs upgrade transaction to transaction.
db->set_upgrade_transaction(transaction);
@ -364,6 +388,7 @@ GC::Ref<IDBTransaction> upgrade_a_database(JS::Realm& realm, GC::Ref<IDBDatabase
// 11. Wait for transaction to finish.
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [&wait_for_transaction]() {
dbgln_if(IDB_DEBUG, "upgrade_a_database: waiting for step 11");
return !wait_for_transaction;
}));
@ -378,9 +403,18 @@ WebIDL::ExceptionOr<u64> delete_a_database(JS::Realm& realm, StorageAPI::Storage
// 2. Add request to queue.
queue.append(request);
dbgln_if(IDB_DEBUG, "delete_a_database: added request {} to queue", request->uuid());
// 3. Wait until all previous requests in queue have been processed.
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [queue, request]() {
if constexpr (IDB_DEBUG) {
dbgln("delete_a_database: waiting for step 3");
dbgln("requests in queue:");
for (auto const& item : queue) {
dbgln("[{}] - {} = {}", item == request ? "x"sv : " "sv, item->uuid(), item->processed() ? "processed"sv : "not processed"sv);
}
}
return queue.all_previous_requests_processed(request);
}));
@ -411,6 +445,11 @@ WebIDL::ExceptionOr<u64> delete_a_database(JS::Realm& realm, StorageAPI::Storage
// 7. Wait for all of the events to be fired.
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [&events_to_fire, &events_fired]() {
if constexpr (IDB_DEBUG) {
dbgln("delete_a_database: waiting for step 7");
dbgln("events_fired: {}, events_to_fire: {}", events_fired, events_to_fire);
}
return events_fired == events_to_fire;
}));
@ -425,6 +464,14 @@ WebIDL::ExceptionOr<u64> delete_a_database(JS::Realm& realm, StorageAPI::Storage
// 9. Wait until all connections in openConnections are closed.
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [open_connections]() {
if constexpr (IDB_DEBUG) {
dbgln("delete_a_database: waiting for step 9");
dbgln("open connections: {}", open_connections.size());
for (auto const& connection : open_connections) {
dbgln(" - {}", connection->uuid());
}
}
for (auto const& entry : open_connections) {
if (entry->state() != IDBDatabase::ConnectionState::Closed) {
return false;
@ -451,6 +498,7 @@ void abort_a_transaction(GC::Ref<IDBTransaction> transaction, GC::Ptr<WebIDL::DO
{
// NOTE: This is not spec'ed anywhere, but we need to know IF the transaction was aborted.
transaction->set_aborted(true);
dbgln_if(IDB_DEBUG, "abort_a_transaction: transaction {} is aborting", transaction->uuid());
// FIXME: 1. All the changes made to the database by the transaction are reverted.
// For upgrade transactions this includes changes to the set of object stores and indexes, as well as the change to the version.

View file

@ -24,6 +24,7 @@ set(HTML_SCRIPT_DEBUG ON)
set(HTTPJOB_DEBUG ON)
set(HUNKS_DEBUG ON)
set(ICO_DEBUG ON)
set(IDB_DEBUG ON)
set(IDL_DEBUG ON)
set(IMAGE_DECODER_DEBUG ON)
set(IMAGE_LOADER_DEBUG ON)