diff --git a/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp b/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp index 573b70c8c2c..116c5827bb6 100644 --- a/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp +++ b/Libraries/LibWeb/IndexedDB/IDBObjectStore.cpp @@ -568,4 +568,43 @@ WebIDL::ExceptionOr> IDBObjectStore::get_all(Optional> IDBObjectStore::open_key_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 key 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)); + + // 6. Let cursor be a new cursor with its source handle set to this, undefined position, direction set to direction, got value flag set to false, undefined key and value, range set to range, and key only flag set to true. + auto cursor = IDBCursor::create(realm, GC::Ref(*this), {}, direction, false, {}, {}, range, true); + + // 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 key 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 5817ed2ec0e..133d806f497 100644 --- a/Libraries/LibWeb/IndexedDB/IDBObjectStore.h +++ b/Libraries/LibWeb/IndexedDB/IDBObjectStore.h @@ -56,6 +56,7 @@ public: [[nodiscard]] WebIDL::ExceptionOr> clear(); [[nodiscard]] WebIDL::ExceptionOr> get_key(JS::Value); [[nodiscard]] WebIDL::ExceptionOr> get_all(Optional, Optional); + [[nodiscard]] WebIDL::ExceptionOr> open_key_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 5e64fcd56a4..3bfdf1129c2 100644 --- a/Libraries/LibWeb/IndexedDB/IDBObjectStore.idl +++ b/Libraries/LibWeb/IndexedDB/IDBObjectStore.idl @@ -20,7 +20,7 @@ interface IDBObjectStore { [FIXME, NewObject] IDBRequest getAllKeys(optional any query, optional [EnforceRange] unsigned long count); [NewObject] IDBRequest count(optional any query); [NewObject] IDBRequest openCursor(optional any query, optional IDBCursorDirection direction = "next"); - [FIXME, NewObject] IDBRequest openKeyCursor(optional any query, optional IDBCursorDirection direction = "next"); + [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 = {}); undefined deleteIndex(DOMString name);