4.8. The IDBCursor interface

Cursor objects implement the [IDBCursor](#idbcursor) interface. There is only ever one [IDBCursor](#idbcursor) instance representing a given cursor. There is no limit on how many cursors can be used at the same time.

  1. [Exposed=(Window,Worker)]
  2. interface IDBCursor {
  3. readonly attribute (IDBObjectStore or IDBIndex) source;
  4. readonly attribute IDBCursorDirection direction;
  5. readonly attribute any key;
  6. readonly attribute any primaryKey;
  7. [SameObject] readonly attribute IDBRequest request;
  8.  
  9. void advance([EnforceRange] unsigned long count);
  10. void continue(optional any key);
  11. void continuePrimaryKey(any key, any primaryKey);
  12.  
  13. [NewObject] IDBRequest update(any value);
  14. [NewObject] IDBRequest delete();
  15. };
  16.  
  17. enum IDBCursorDirection {
  18. "next",
  19. "nextunique",
  20. "prev",
  21. "prevunique"
  22. };

cursor . [source](#dom-idbcursor-source)

Returns the [IDBObjectStore](#idbobjectstore) or [IDBIndex](#idbindex) the cursor was opened from.

cursor . [direction](#dom-idbcursor-direction)

Returns the direction (["next"](#dom-idbcursordirection-next), ["nextunique"](#dom-idbcursordirection-nextunique), ["prev"](#dom-idbcursordirection-prev) or ["prevunique"](#dom-idbcursordirection-prevunique)) of the cursor.

cursor . [key](#dom-idbcursor-key)

Returns the key of the cursor. Throws a “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) if the cursor is advancing or is finished.

cursor . [primaryKey](#dom-idbcursor-primarykey)

Returns the effective key of the cursor. Throws a “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) if the cursor is advancing or is finished.

cursor . [request](#dom-idbcursor-request)

Returns the request that was used to obtain this cursor.

The source attribute’s getter must return this‘s source. This attribute never returns null or throws an exception, even if the cursor is currently being iterated, has iterated past its end, or its transaction is not active.

The direction attribute’s getter must return this‘s direction.

The key attribute’s getter must return the result of running convert a key to a value with the cursor’s current key. Note that if this property returns an object (e.g. a Date or Array), it returns the same object instance every time it is inspected, until the cursor’s key is changed. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.

The primaryKey attribute’s getter must return the result of running convert a key to a value with the cursor’s current effective key. Note that if this property returns an object (e.g. a Date or Array), it returns the same object instance every time it is inspected, until the cursor’s effective key is changed. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.

The request attribute’s getter must return this‘s request.

🚧 The [request](#dom-idbcursor-request) attribute is new in this edition. It is supported in Chrome 76, Edge 79, and Firefox 77. 🚧

The following methods advance a cursor. Once the cursor has advanced, a success event will be fired at the same [IDBRequest](#idbrequest) returned when the cursor was opened. The [result](#dom-idbrequest-result) will be the same cursor if a record was in range, or undefined otherwise.

If called while the cursor is already advancing, an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) will be thrown.

The following methods throw a “[TransactionInactiveError](https://heycam.github.io/webidl/#transactioninactiveerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) if called when the transaction is not active.

cursor . [advance](#dom-idbcursor-advance)(count)

Advances the cursor through the next count records in range.

cursor . [continue](#dom-idbcursor-continue)()

Advances the cursor to the next record in range.

cursor . [continue](#dom-idbcursor-continue)(key)

Advances the cursor to the next record in range matching or after key.

cursor . [continuePrimaryKey](#dom-idbcursor-continueprimarykey)(key, primaryKey)

Advances the cursor to the next record in range matching or after key and primaryKey. Throws an “[InvalidAccessError](https://heycam.github.io/webidl/#invalidaccesserror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) if the source is not an index.

The advance(count) method, when invoked, must run these steps:

  1. If count is 0 (zero), throw a TypeError.

  2. Let transaction be this‘s transaction.

  3. If transaction’s state is not active, then throw a “[TransactionInactiveError](https://heycam.github.io/webidl/#transactioninactiveerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  4. If this‘s source or effective object store has been deleted, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  5. If this‘s got value flag is false, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  6. Set this‘s got value flag to false.

  7. Let request be this‘s request.

  8. Set request’s processed flag to false.

  9. Set request’s done flag to false.

  10. Run asynchronously execute a request with this‘s source as source, iterate a cursor as operation and request, using the current Realm as targetRealm, this, and count.

Calling this method more than once before new cursor data has been loaded - for example, calling [advance()](#dom-idbcursor-advance) twice from the same onsuccess handler - results in an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) being thrown on the second call because the cursor’s got value flag has been set to false.

The continue(key) method, when invoked, must run these steps:

  1. Let transaction be this‘s transaction.

  2. If transaction’s state is not active, then throw a “[TransactionInactiveError](https://heycam.github.io/webidl/#transactioninactiveerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  3. If this‘s source or effective object store has been deleted, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  4. If this‘s got value flag is false, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  5. If key is given, then:

    1. Let r be the result of running convert a value to a key with key. Rethrow any exceptions.

    2. If r is invalid, throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

    3. Let key be r.

    4. If key is less than or equal to this‘s position and this‘s direction is ["next"](#dom-idbcursordirection-next) or ["nextunique"](#dom-idbcursordirection-nextunique), then throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

    5. If key is greater than or equal to this‘s position and this‘s direction is ["prev"](#dom-idbcursordirection-prev) or ["prevunique"](#dom-idbcursordirection-prevunique), then throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  6. Set this‘s got value flag to false.

  7. Let request be this‘s request.

  8. Set request’s processed flag to false.

  9. Set request’s done flag to false.

  10. Run asynchronously execute a request with this‘s source as source, iterate a cursor as operation and request, using the current Realm as targetRealm, this, and key (if given).

Calling this method more than once before new cursor data has been loaded - for example, calling [continue()](#dom-idbcursor-continue) twice from the same onsuccess handler - results in an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) being thrown on the second call because the cursor’s got value flag has been set to false.

The continuePrimaryKey(key, primaryKey) method, when invoked, must run these steps:

  1. Let transaction be this‘s transaction.

  2. If transaction’s state is not active, then throw a “[TransactionInactiveError](https://heycam.github.io/webidl/#transactioninactiveerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  3. If this‘s source or effective object store has been deleted, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  4. If this‘s source is not an index throw an “[InvalidAccessError](https://heycam.github.io/webidl/#invalidaccesserror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  5. If this‘s direction is not ["next"](#dom-idbcursordirection-next) or ["prev"](#dom-idbcursordirection-prev), throw an “[InvalidAccessError](https://heycam.github.io/webidl/#invalidaccesserror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  6. If this‘s got value flag is false, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  7. Let r be the result of running convert a value to a key with key. Rethrow any exceptions.

  8. If r is invalid, throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  9. Let key be r.

  10. Let r be the result of running convert a value to a key with primaryKey. Rethrow any exceptions.

  11. If r is invalid, throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  12. Let primaryKey be r.

  13. If key is less than this‘s position and this‘s direction is ["next"](#dom-idbcursordirection-next), throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  14. If key is greater than this‘s position and this‘s direction is ["prev"](#dom-idbcursordirection-prev), throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  15. If key is equal to this‘s position and primaryKey is less than or equal to this‘s object store position and this‘s direction is ["next"](#dom-idbcursordirection-next), throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  16. If key is equal to this‘s position and primaryKey is greater than or equal to this‘s object store position and this‘s direction is ["prev"](#dom-idbcursordirection-prev), throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  17. Set this‘s got value flag to false.

  18. Let request be this‘s request.

  19. Set request’s processed flag to false.

  20. Set request’s done flag to false.

  21. Run asynchronously execute a request with this‘s source as source, iterate a cursor as operation and request, using the current Realm as targetRealm, this, key and primaryKey.

Calling this method more than once before new cursor data has been loaded - for example, calling [continuePrimaryKey()](#dom-idbcursor-continueprimarykey) twice from the same onsuccess handler - results in an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) being thrown on the second call because the cursor’s got value flag has been set to false.

The following methods throw a “[ReadOnlyError](https://heycam.github.io/webidl/#readonlyerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) if called within a read-only transaction, and a “[TransactionInactiveError](https://heycam.github.io/webidl/#transactioninactiveerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) if called when the transaction is not active.

request = cursor . [update](#dom-idbcursor-update)(value)

Updated the record pointed at by the cursor with a new value.

Throws a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException) if the effective object store uses in-line keys and the key would have changed.

If successful, request’s [result](#dom-idbrequest-result) will be the record‘s key.

request = cursor . [delete](#dom-idbcursor-delete)()

Delete the record pointed at by the cursor with a new value.

If successful, request’s [result](#dom-idbrequest-result) will be undefined.

The update(value) method, when invoked, must run these steps:

  1. Let transaction be this‘s transaction.

  2. If transaction’s state is not active, then throw a “[TransactionInactiveError](https://heycam.github.io/webidl/#transactioninactiveerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  3. If transaction is a read-only transaction, throw a “[ReadOnlyError](https://heycam.github.io/webidl/#readonlyerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  4. If this‘s source or effective object store has been deleted, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  5. If this‘s got value flag is false, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  6. If this‘s key only flag is true, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  7. Let targetRealm be a user-agent defined Realm.

  8. Let clone be a clone of value in targetRealm during transaction. Rethrow any exceptions.

    Why create a copy of the value? The value is serialized when stored. Treating it as a copy here allows other algorithms in this specification to treat it as an ECMAScript value, but implementations can optimize this if the difference in behavior is not observable.

  9. If this‘s effective object store uses in-line keys, then:

    1. Let kpk be the result of running extract a key from a value using a key path with clone and the key path of this‘s effective object store. Rethrow any exceptions.

    2. If kpk is failure, invalid, or not equal to this‘s effective key, throw a “[DataError](https://heycam.github.io/webidl/#dataerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  10. Return the result (an [IDBRequest](#idbrequest)) of running asynchronously execute a request with this as source and store a record into an object store as operation, using this‘s effective object store as store, the clone as value, this‘s effective key as key, and with the no-overwrite flag false.

A result of running the steps to store a record into an object store is that if the record has been deleted since the cursor moved to it, a new record will be created.

The delete() method, when invoked, must run these steps:

  1. Let transaction be this‘s transaction.

  2. If transaction’s state is not active, then throw a “[TransactionInactiveError](https://heycam.github.io/webidl/#transactioninactiveerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  3. If transaction is a read-only transaction, throw a “[ReadOnlyError](https://heycam.github.io/webidl/#readonlyerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  4. If this‘s source or effective object store has been deleted, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  5. If this‘s got value flag is false, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  6. If this‘s key only flag is true, throw an “[InvalidStateError](https://heycam.github.io/webidl/#invalidstateerror)[DOMException](https://heycam.github.io/webidl/#idl-DOMException).

  7. Return the result (an [IDBRequest](#idbrequest)) of running asynchronously execute a request with this as source and delete records from an object store as operation, using this‘s effective object store and effective key as store and key respectively.

A cursor that has its key only flag set to false implements the [IDBCursorWithValue](#idbcursorwithvalue) interface as well.

  1. [Exposed=(Window,Worker)]
  2. interface IDBCursorWithValue : IDBCursor {
  3. readonly attribute any value;
  4. };

cursor . [value](#dom-idbcursorwithvalue-value)

Returns the cursor‘s current value.

The value attribute’s getter must return this‘s current value. Note that if this property returns an object, it returns the same object instance every time it is inspected, until the cursor’s value is changed. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.