diff --git a/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp b/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp index b023f9f121d..b88fbff3546 100644 --- a/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp +++ b/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -395,4 +396,44 @@ WebIDL::ExceptionOr> IDBObjectStore::get(JS::Value query) return result; } +// https://w3c.github.io/IndexedDB/#dom-idbobjectstore-opencursor +WebIDL::ExceptionOr> IDBObjectStore::open_cursor(JS::Value query, Bindings::IDBCursorDirection direction) +{ + auto& realm = this->realm(); + + // 1. Let transaction be this's transaction. + auto transaction = this->transaction(); + + // 2. Let store be this's object store. + [[maybe_unused]] auto store = this->store(); + + // FIXME: 3. If store has been deleted, throw an "InvalidStateError" DOMException. + + // 4. If transaction’s state is not active, then throw a "TransactionInactiveError" DOMException. + if (transaction->state() != IDBTransaction::TransactionState::Active) + return WebIDL::TransactionInactiveError::create(realm, "Transaction is not active while opening cursor"_string); + + // 5. Let range be the result of converting a value to a key range with query. Rethrow any exceptions. + auto range = TRY(convert_a_value_to_a_key_range(realm, query, false)); + + // 6. Let cursor be a new cursor with its transaction set to transaction, undefined position, direction set to direction, + // got value flag set to false, undefined key and value, source set to store, range set to range, and key only flag set to false. + auto cursor = IDBCursor::create(realm, transaction, {}, direction, false, {}, {}, GC::Ref(*this), range, false); + + // 7. Let operation be an algorithm to run iterate a cursor with the current Realm record and cursor. + auto operation = GC::Function()>::create(realm.heap(), [&realm, cursor] -> WebIDL::ExceptionOr { + return WebIDL::ExceptionOr(iterate_a_cursor(realm, cursor)); + }); + + // 8. Let request be the result of running asynchronously execute a request with this and operation. + auto request = asynchronously_execute_a_request(realm, GC::Ref(*this), operation); + dbgln_if(IDB_DEBUG, "Executing request for open cursor with uuid {}", request->uuid()); + + // 9. Set cursor’s request to request. + cursor->set_request(request); + + // 10. Return request. + return request; +} + } diff --git a/Libraries/LibWeb/IndexedDB/IDBObjectStore.h b/Libraries/LibWeb/IndexedDB/IDBObjectStore.h index 4571e62a3ad..c23ff66c543 100644 --- a/Libraries/LibWeb/IndexedDB/IDBObjectStore.h +++ b/Libraries/LibWeb/IndexedDB/IDBObjectStore.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,7 @@ public: [[nodiscard]] WebIDL::ExceptionOr> put(JS::Value value, Optional const& key); [[nodiscard]] WebIDL::ExceptionOr> count(Optional); [[nodiscard]] WebIDL::ExceptionOr> get(JS::Value); + [[nodiscard]] WebIDL::ExceptionOr> open_cursor(JS::Value, Bindings::IDBCursorDirection = Bindings::IDBCursorDirection::Next); protected: explicit IDBObjectStore(JS::Realm&, GC::Ref, GC::Ref); diff --git a/Libraries/LibWeb/IndexedDB/IDBObjectStore.idl b/Libraries/LibWeb/IndexedDB/IDBObjectStore.idl index 1261331c328..6d21125107d 100644 --- a/Libraries/LibWeb/IndexedDB/IDBObjectStore.idl +++ b/Libraries/LibWeb/IndexedDB/IDBObjectStore.idl @@ -19,7 +19,7 @@ interface IDBObjectStore { [FIXME, NewObject] IDBRequest getAll(optional any query, optional [EnforceRange] unsigned long count); [FIXME, NewObject] IDBRequest getAllKeys(optional any query, optional [EnforceRange] unsigned long count); [NewObject] IDBRequest count(optional any query); - [FIXME, NewObject] IDBRequest openCursor(optional any query, optional IDBCursorDirection direction = "next"); + [NewObject] IDBRequest openCursor(optional any query, optional IDBCursorDirection direction = "next"); [FIXME, NewObject] IDBRequest openKeyCursor(optional any query, optional IDBCursorDirection direction = "next"); IDBIndex index(DOMString name); [NewObject] IDBIndex createIndex(DOMString name, (DOMString or sequence) keyPath, optional IDBIndexParameters options = {});