mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 03:55:24 +00:00
LibWeb/IDB: Implement IDBTransaction::commit
This commit is contained in:
parent
e0e2a95983
commit
39c7145d10
5 changed files with 77 additions and 1 deletions
|
@ -103,4 +103,19 @@ GC::Ref<HTML::DOMStringList> IDBTransaction::object_store_names()
|
|||
return create_a_sorted_name_list(realm(), names);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/IndexedDB/#dom-idbtransaction-commit
|
||||
WebIDL::ExceptionOr<void> IDBTransaction::commit()
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
|
||||
// 1. If this's state is not active, then throw an "InvalidStateError" DOMException.
|
||||
if (m_state != TransactionState::Active)
|
||||
return WebIDL::InvalidStateError::create(realm, "Transaction is not active while commiting"_string);
|
||||
|
||||
// 2. Run commit a transaction with this.
|
||||
commit_a_transaction(realm, *this);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
[[nodiscard]] GC::Ptr<IDBRequest> associated_request() const { return m_associated_request; }
|
||||
[[nodiscard]] bool aborted() const { return m_aborted; }
|
||||
[[nodiscard]] GC::Ref<HTML::DOMStringList> object_store_names();
|
||||
[[nodiscard]] RequestList& request_list() { return m_request_list; }
|
||||
[[nodiscard]] ReadonlySpan<GC::Ref<ObjectStore>> scope() const { return m_scope; }
|
||||
[[nodiscard]] String uuid() const { return m_uuid; }
|
||||
|
||||
|
@ -59,6 +60,7 @@ public:
|
|||
[[nodiscard]] bool is_finished() const { return m_state == TransactionState::Finished; }
|
||||
|
||||
WebIDL::ExceptionOr<void> abort();
|
||||
WebIDL::ExceptionOr<void> commit();
|
||||
|
||||
void set_onabort(WebIDL::CallbackType*);
|
||||
WebIDL::CallbackType* onabort();
|
||||
|
|
|
@ -10,7 +10,7 @@ interface IDBTransaction : EventTarget {
|
|||
[SameObject, ImplementedAs=connection] readonly attribute IDBDatabase db;
|
||||
readonly attribute DOMException? error;
|
||||
[FIXME] IDBObjectStore objectStore(DOMString name);
|
||||
[FIXME] undefined commit();
|
||||
undefined commit();
|
||||
undefined abort();
|
||||
|
||||
attribute EventHandler onabort;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibWeb/DOM/EventDispatcher.h>
|
||||
#include <LibWeb/HTML/EventNames.h>
|
||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||
#include <LibWeb/IndexedDB/IDBDatabase.h>
|
||||
#include <LibWeb/IndexedDB/IDBRequest.h>
|
||||
#include <LibWeb/IndexedDB/IDBTransaction.h>
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include <LibWeb/IndexedDB/Internal/ConnectionQueueHandler.h>
|
||||
#include <LibWeb/IndexedDB/Internal/Database.h>
|
||||
#include <LibWeb/Infra/Strings.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/StorageAPI/StorageKey.h>
|
||||
#include <LibWeb/WebIDL/AbstractOperations.h>
|
||||
#include <LibWeb/WebIDL/Buffers.h>
|
||||
|
@ -706,4 +708,60 @@ GC::Ref<HTML::DOMStringList> create_a_sorted_name_list(JS::Realm& realm, Vector<
|
|||
return HTML::DOMStringList::create(realm, names);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/IndexedDB/#commit-a-transaction
|
||||
void commit_a_transaction(JS::Realm& realm, GC::Ref<IDBTransaction> transaction)
|
||||
{
|
||||
// 1. Set transaction’s state to committing.
|
||||
transaction->set_state(IDBTransaction::TransactionState::Committing);
|
||||
|
||||
dbgln_if(IDB_DEBUG, "commit_a_transaction: transaction {} is committing", transaction->uuid());
|
||||
|
||||
// 2. Run the following steps in parallel:
|
||||
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(realm.heap(), [&realm, transaction]() {
|
||||
HTML::TemporaryExecutionContext context(realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
|
||||
|
||||
// 1. Wait until every item in transaction’s request list is processed.
|
||||
HTML::main_thread_event_loop().spin_until(GC::create_function(realm.vm().heap(), [transaction]() {
|
||||
if constexpr (IDB_DEBUG) {
|
||||
dbgln("commit_a_transaction: waiting for step 1");
|
||||
dbgln("requests in queue:");
|
||||
for (auto const& request : transaction->request_list()) {
|
||||
dbgln(" - {} = {}", request->uuid(), request->processed() ? "processed"sv : "not processed"sv);
|
||||
}
|
||||
}
|
||||
|
||||
return transaction->request_list().all_requests_processed();
|
||||
}));
|
||||
|
||||
// 2. If transaction’s state is no longer committing, then terminate these steps.
|
||||
if (transaction->state() != IDBTransaction::TransactionState::Committing)
|
||||
return;
|
||||
|
||||
// FIXME: 3. Attempt to write any outstanding changes made by transaction to the database, considering transaction’s durability hint.
|
||||
// FIXME: 4. If an error occurs while writing the changes to the database, then run abort a transaction with transaction and an appropriate type for the error, for example "QuotaExceededError" or "UnknownError" DOMException, and terminate these steps.
|
||||
|
||||
// 5. Queue a task to run these steps:
|
||||
HTML::queue_a_task(HTML::Task::Source::DatabaseAccess, nullptr, nullptr, GC::create_function(transaction->realm().vm().heap(), [transaction]() {
|
||||
// 1. If transaction is an upgrade transaction, then set transaction’s connection's associated database's upgrade transaction to null.
|
||||
if (transaction->is_upgrade_transaction())
|
||||
transaction->connection()->associated_database()->set_upgrade_transaction(nullptr);
|
||||
|
||||
// 2. Set transaction’s state to finished.
|
||||
transaction->set_state(IDBTransaction::TransactionState::Finished);
|
||||
|
||||
// 3. Fire an event named complete at transaction.
|
||||
transaction->dispatch_event(DOM::Event::create(transaction->realm(), HTML::EventNames::complete));
|
||||
|
||||
// 4. If transaction is an upgrade transaction, then let request be the request associated with transaction and set request’s transaction to null.
|
||||
if (transaction->is_upgrade_transaction()) {
|
||||
auto request = transaction->associated_request();
|
||||
request->set_transaction(nullptr);
|
||||
|
||||
// Ad-hoc: Clear the two-way binding.
|
||||
transaction->set_associated_request(nullptr);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,5 +27,6 @@ void abort_a_transaction(GC::Ref<IDBTransaction>, GC::Ptr<WebIDL::DOMException>)
|
|||
JS::Value convert_a_key_to_a_value(JS::Realm&, GC::Ref<Key>);
|
||||
bool is_valid_key_path(KeyPath const&);
|
||||
GC::Ref<HTML::DOMStringList> create_a_sorted_name_list(JS::Realm&, Vector<String>);
|
||||
void commit_a_transaction(JS::Realm&, GC::Ref<IDBTransaction>);
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue