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.  
  8. void advance([EnforceRange] unsigned long count);
  9. void continue(optional any key);
  10. void continuePrimaryKey(any key, any primaryKey);
  11.  
  12. [NewObject] IDBRequest update(any value);
  13. [NewObject] IDBRequest delete();
  14. };
  15.  
  16. enum IDBCursorDirection {
  17. "next",
  18. "nextunique",
  19. "prev",
  20. "prevunique"
  21. };

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

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

range . [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://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#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://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException) if the cursor is advancing or is finished.

The source attribute’s getter must return the source of this cursor. 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 the direction of the cursor.

The key attribute’s getter must return the result of running the steps to 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 the steps to 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 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://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException) will be thrown.

The following methods throw a “[TransactionInactiveError](https://www.w3.org/TR/WebIDL-1/#transactioninactiveerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#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://www.w3.org/TR/WebIDL-1/#invalidaccesserror)[DOMException](https://www.w3.org/TR/WebIDL-1/#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 cursor‘s transaction.

  3. If transaction is not active, throw a “[TransactionInactiveError](https://www.w3.org/TR/WebIDL-1/#transactioninactiveerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  4. If the cursor’s source or effective object store has been deleted, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  5. If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  6. Unset the got value flag on the cursor.

  7. Let request be the request created when this cursor was created.

  8. Unset the done flag on request.

  9. Run the steps to asynchronously execute a request with the cursor’s source as source, the steps to iterate a cursor as operation and request, using the current Realm as targetRealm, this cursor 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://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException) being thrown on the second call because the cursor’s got value flag has been unset.

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

  1. Let transaction be this cursor‘s transaction.

  2. If transaction is not active, throw a “[TransactionInactiveError](https://www.w3.org/TR/WebIDL-1/#transactioninactiveerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  3. If the cursor’s source or effective object store has been deleted, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  4. If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  5. If key is given, then:

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

    2. If r is invalid, throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

    3. Let key be r.

    4. If key is less than or equal to this cursor’s position and this cursor’s direction is ["next"](#dom-idbcursordirection-next) or ["nextunique"](#dom-idbcursordirection-nextunique), throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

    5. If key is greater than or equal to this cursor’s position and this cursor’s direction is ["prev"](#dom-idbcursordirection-prev) or ["prevunique"](#dom-idbcursordirection-prevunique), throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  6. Unset the got value flag on the cursor.

  7. Let request be the request created when this cursor was created.

  8. Unset the done flag on request.

  9. Run the steps to asynchronously execute a request with the cursor’s source as source, the steps to iterate a cursor as operation and request, using the current Realm as targetRealm, this cursor 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://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException) being thrown on the second call because the cursor’s got value flag has been unset.

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

  1. Let transaction be this cursor‘s transaction.

  2. If transaction is not active, throw a “[TransactionInactiveError](https://www.w3.org/TR/WebIDL-1/#transactioninactiveerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  3. If the cursor’s source or effective object store has been deleted, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  4. If this cursor’s source is not an index throw an “[InvalidAccessError](https://www.w3.org/TR/WebIDL-1/#invalidaccesserror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  5. If this cursor’s direction is not ["next"](#dom-idbcursordirection-next) or ["prev"](#dom-idbcursordirection-prev), throw an “[InvalidAccessError](https://www.w3.org/TR/WebIDL-1/#invalidaccesserror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  6. If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

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

  8. If r is invalid, throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  9. Let key be r.

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

  11. If r is invalid, throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  12. Let primaryKey be r.

  13. If key is less than this cursor’s position and this cursor’s direction is ["next"](#dom-idbcursordirection-next), throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  14. If key is greater than this cursor’s position and this cursor’s direction is ["prev"](#dom-idbcursordirection-prev), throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  15. If key is equal to this cursor’s position and primaryKey is less than or equal to this cursor’s object store position and this cursor’s direction is ["next"](#dom-idbcursordirection-next), throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  16. If key is equal to this cursor’s position and primaryKey is greater than or equal to this cursor’s object store position and this cursor’s direction is ["prev"](#dom-idbcursordirection-prev), throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  17. Unset the got value flag on the cursor.

  18. Let request be the request created when this cursor was created.

  19. Unset the done flag on request.

  20. Run the steps to asynchronously execute a request with the cursor’s source as source, the steps to iterate a cursor as operation and request, using the current Realm as targetRealm, this cursor, key and primaryKey.

🚧 The [continuePrimaryKey()](#dom-idbcursor-continueprimarykey) method is new in this edition. It is supported in Chrome 58, Firefox 51, and Safari 10.1. 🚧

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://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException) being thrown on the second call because the cursor’s got value flag has been unset.

The following methods throw a “[ReadOnlyError](https://www.w3.org/TR/WebIDL-1/#readonlyerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException) if called within a read-only transaction, and a “[TransactionInactiveError](https://www.w3.org/TR/WebIDL-1/#transactioninactiveerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#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://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#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 cursor‘s transaction.

  2. If transaction is not active, throw a “[TransactionInactiveError](https://www.w3.org/TR/WebIDL-1/#transactioninactiveerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  3. If transaction is a read-only transaction, throw a “[ReadOnlyError](https://www.w3.org/TR/WebIDL-1/#readonlyerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  4. If the cursor’s source or effective object store has been deleted, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  5. If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  6. If this cursor’s key only flag is set, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

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

  8. Let clone be a clone of value in targetRealm. 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 the effective object store of this cursor uses in-line keys, then:

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

    2. If kpk is failure, invalid, or not equal to the cursor’s effective key, throw a “[DataError](https://www.w3.org/TR/WebIDL-1/#dataerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  10. Run the steps to asynchronously execute a request and return the [IDBRequest](#idbrequest) created by these steps. The steps are run with this cursor as source and the steps to store a record into an object store as operation, using this cursor’s effective object store as store, the clone as value, this cursor’s effective key as key, and with the no-overwrite flag unset.

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 cursor‘s transaction.

  2. If transaction is not active, throw a “[TransactionInactiveError](https://www.w3.org/TR/WebIDL-1/#transactioninactiveerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  3. If transaction is a read-only transaction, throw a “[ReadOnlyError](https://www.w3.org/TR/WebIDL-1/#readonlyerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  4. If the cursor’s source or effective object store has been deleted, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  5. If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  6. If this cursor’s key only flag is set, throw an “[InvalidStateError](https://www.w3.org/TR/WebIDL-1/#invalidstateerror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException).

  7. Run the steps to asynchronously execute a request and return the [IDBRequest](#idbrequest) created by these steps. The steps are run with this cursor as source and the steps to delete records from an object store as operation, using this cursor’s effective object store and effective key as store and key respectively.

A cursor that has the key only flag unset 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 the cursor’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.