LibWeb/IDB: Implement IDBCursor::advance

This commit is contained in:
stelar7 2025-05-13 09:54:00 +02:00 committed by Andrew Kaster
commit 6afa2c8eee
Notes: github-actions[bot] 2025-05-13 16:50:15 +00:00
3 changed files with 48 additions and 1 deletions

View file

@ -169,4 +169,50 @@ JS::Value IDBCursor::primary_key() const
return convert_a_key_to_a_value(realm(), effective_key());
}
// https://w3c.github.io/IndexedDB/#dom-idbcursor-advance
WebIDL::ExceptionOr<void> IDBCursor::advance(WebIDL::UnsignedLong count)
{
auto& realm = this->realm();
// 1. If count is 0 (zero), throw a TypeError.
if (count == 0)
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Count must not be zero (0)"_string };
// 2. Let transaction be thiss transaction.
auto transaction = this->transaction();
// 3. If transactions 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 advancing cursor"_string);
// FIXME: 4. If thiss source or effective object store has been deleted, throw an "InvalidStateError" DOMException.
// 5. If thiss got value flag is false, indicating that the cursor is being iterated or has iterated past its end, throw an "InvalidStateError" DOMException.
if (!m_got_value)
return WebIDL::InvalidStateError::create(realm, "Cursor is active or EOL while advancing"_string);
// 6. Set thiss got value flag to false.
m_got_value = false;
// 7. Let request be thiss request.
auto request = this->request();
// 8. Set requests processed flag to false.
request->set_processed(false);
// 9. Set requests done flag to false.
request->set_done(false);
// 10. Let operation be an algorithm to run iterate a cursor with the current Realm record, this, and count.
auto operation = GC::Function<WebIDL::ExceptionOr<JS::Value>()>::create(realm.heap(), [this, &realm, count] -> WebIDL::ExceptionOr<JS::Value> {
return WebIDL::ExceptionOr<JS::Value>(iterate_a_cursor(realm, *this, nullptr, nullptr, count));
});
// 11. Run asynchronously execute a request with thiss source handle, operation, and request.
asynchronously_execute_a_request(realm, source_handle(), operation, request);
dbgln_if(IDB_DEBUG, "Executing request for cursor advance with uuid {}", request->uuid());
return {};
}
}

View file

@ -45,6 +45,7 @@ public:
[[nodiscard]] JS::Value primary_key() const;
[[nodiscard]] GC::Ptr<IDBRequest> request() { return m_request; }
WebIDL::ExceptionOr<void> advance(WebIDL::UnsignedLong);
WebIDL::ExceptionOr<void> continue_(JS::Value);
[[nodiscard]] JS::Value value() { return m_value.value_or(JS::js_undefined()); }

View file

@ -7,7 +7,7 @@ interface IDBCursor {
readonly attribute any key;
readonly attribute any primaryKey;
[SameObject] readonly attribute IDBRequest request;
[FIXME] undefined advance([EnforceRange] unsigned long count);
undefined advance([EnforceRange] unsigned long count);
undefined continue(optional any key);
[FIXME] undefined continuePrimaryKey(any key, any primaryKey);
[FIXME, NewObject] IDBRequest update(any value);