diff --git a/index.bs b/index.bs
index c018340..07cf90e 100644
--- a/index.bs
+++ b/index.bs
@@ -1372,6 +1372,56 @@ To convert a value to a key range with
+
+
+
+To convert a value to get all records options
+with |value| and optional |count|, run these steps. The results
+of these steps are a [=/key range=], an optional count, and an
+{{IDBCursorDirection}}:
+
+1. Let |direction| be "{{IDBCursorDirection/next}}".
+
+1. If |value| [=implements=] {{IDBKeyRange}}, or |value| is
+ undefined, or |value| is null:
+
+ 1. Let |range| be the result of
+ [=/converting a value to a key range=] with |value|.
+ Rethrow any exceptions.
+
+ 1. Return |range|, |count| if given, and |direction|.
+
+1. Let |key| be the result of [=/converting a value to a key=]
+ with |value|. Rethrow any exceptions.
+
+1. If |key| is not invalid:
+
+ 1. Let |range| be a [=/key range=] [=containing only=] |key|.
+
+ 1. Return |range|, |count| if given, and |direction|.
+
+1. If [=ECMAScript/Type=](|value|) is not Object,
+ [=exception/throw=] a "{{DataError}}" {{DOMException}}.
+
+1. Let |options| be the result of [=converted to an IDL value|converting=]
+ |value| to an {{IDBGetAllRecordsOptions}}. Rethrow any exceptions.
+
+1. Let |direction| be |options|["{{IDBGetAllRecordsOptions/direction}}"].
+
+1. If |options|["{{IDBGetAllRecordsOptions/count}}"]
+ [=map/exists=], let |count| be
+ |options|["{{IDBGetAllRecordsOptions/count}}"].
+ Otherwise, let |count| not be given.
+
+1. Let |range| be the result of
+ [=/converting a value to a key range=] with
+ |options|["{{IDBGetAllRecordsOptions/query}}"]. Rethrow any exceptions.
+
+1. Return |range|, |count| if given, and |direction|.
+
+
+
+
## Cursor ## {#cursor-construct}
@@ -2731,6 +2781,7 @@ interface IDBObjectStore {
optional [EnforceRange] unsigned long count);
[NewObject] IDBRequest getAllKeys(optional any query,
optional [EnforceRange] unsigned long count);
+ [NewObject] IDBRequest getAllRecords(optional IDBGetAllRecordsOptions options = {});
[NewObject] IDBRequest count(optional any query);
[NewObject] IDBRequest openCursor(optional any query,
@@ -2750,6 +2801,12 @@ dictionary IDBIndexParameters {
boolean unique = false;
boolean multiEntry = false;
};
+
+dictionary IDBGetAllRecordsOptions {
+ any query = null;
+ [EnforceRange] unsigned long count;
+ IDBCursorDirection direction = "next";
+};
@@ -3098,6 +3155,25 @@ The clear() method steps are:
If successful, |request|'s {{IDBRequest/result}} will
be an {{Array}} of the [=/keys=].
+ : |request| = |store| .
+ {{IDBObjectStore/getAllRecords()|getAllRecords}}([|options|])
+ ::
+ Retrieves the [=/key=] and [=/value=] of [=object-store/records=]
+ matching the given |options| (up to
+ {{IDBGetAllRecordsOptions/count}} if given).
+ The {{IDBGetAllRecordsOptions/direction}} option determines
+ the order in which records are returned.
+
+ The |query| parameter for
+ {{IDBObjectStore/getAll()|getAll}} and
+ {{IDBObjectStore/getAllKeys()|getAllKeys}} can also be an
+ {{IDBGetAllRecordsOptions}}, which adds
+ {{IDBGetAllRecordsOptions/direction}} support to those methods.
+
+ If successful, |request|'s {{IDBRequest/result}} will
+ be an {{Array}} of objects, each with `key`, `primaryKey`,
+ and `value` properties.
+
: |request| = |store| .
{{IDBObjectStore/count()|count}}(|query|)
::
@@ -3187,12 +3263,11 @@ The getAll(|query|, |count|) method steps a
1. If |transaction|'s [=transaction/state=] is not [=transaction/active=],
then [=exception/throw=] a "{{TransactionInactiveError}}" {{DOMException}}.
-1. Let |range| be the result of
- [=/converting a value to a key range=] with |query|.
- Rethrow any exceptions.
-
-1. Let |operation| be an algorithm to run [=retrieve multiple values from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, and |count| if given.
+1. Let |range|, |count|, and |direction| be the result of
+ [=converting a value to get all records options=] with |query|
+ and |count| if given. Rethrow any exceptions.
+1. Let |operation| be an algorithm to run [=retrieve multiple values from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, |count| if given, and |direction|.
1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|.
@@ -3201,7 +3276,8 @@ The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}})
identifying the [=object-store/record=] values to be retrieved. If null or not given,
an [=unbounded key range=] is used. If |count| is specified and
there are more than |count| records in range, only the first |count|
-will be retrieved.
+will be retrieved. The |query| parameter can also be an
+{{IDBGetAllRecordsOptions}} dictionary, which adds direction support.
@@ -3220,11 +3296,11 @@ The getAllKeys(|query|, |count|) method ste
1. If |transaction|'s [=transaction/state=] is not [=transaction/active=],
then [=exception/throw=] a "{{TransactionInactiveError}}" {{DOMException}}.
-1. Let |range| be the result of
- [=/converting a value to a key range=] with |query|.
- Rethrow any exceptions.
+1. Let |range|, |count|, and |direction| be the result of
+ [=converting a value to get all records options=] with |query|
+ and |count| if given. Rethrow any exceptions.
-1. Let |operation| be an algorithm to run [=retrieve multiple keys from an object store=] with |store|, |range|, and |count| if given.
+1. Let |operation| be an algorithm to run [=retrieve multiple keys from an object store=] with |store|, |range|, |count| if given, and |direction|.
1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|.
@@ -3233,7 +3309,47 @@ The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}})
identifying the [=object-store/record=] keys to be retrieved. If null or not
given, an [=unbounded key range=] is used. If |count| is specified
and there are more than |count| keys in range, only the first |count|
-will be retrieved.
+will be retrieved. The |query| parameter can also be an
+{{IDBGetAllRecordsOptions}} dictionary, which adds direction support.
+
+
+
+
+
+
+The getAllRecords(|options|) method steps are:
+
+1. Let |transaction| be [=/this=]'s [=object-store-handle/transaction=].
+
+1. Let |store| be [=/this=]'s [=object-store-handle/object store=].
+
+1. If |store| has been deleted, [=exception/throw=] an
+ "{{InvalidStateError}}" {{DOMException}}.
+
+1. If |transaction|'s [=transaction/state=] is not [=transaction/active=],
+ then [=exception/throw=] a "{{TransactionInactiveError}}" {{DOMException}}.
+
+1. Let |direction| be |options|["{{IDBGetAllRecordsOptions/direction}}"].
+
+1. Let |range| be the result of
+ [=/converting a value to a key range=] with
+ |options|["{{IDBGetAllRecordsOptions/query}}"].
+ Rethrow any exceptions.
+
+1. Let |operation| be an algorithm to run [=retrieve multiple records from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, |options|["{{IDBGetAllRecordsOptions/count}}"] if it [=map/exists=], and |direction|.
+
+1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|.
+
+NOTE:
+The |options| parameter is an {{IDBGetAllRecordsOptions}} dictionary.
+Its {{IDBGetAllRecordsOptions/query}} member can be a [=/key=] or
+[=/key range=] (an {{IDBKeyRange}}) identifying the
+[=object-store/records=] to be retrieved. If null or not given, an
+[=unbounded key range=] is used. Its
+{{IDBGetAllRecordsOptions/count}} member specifies the maximum number
+of records to retrieve. Its
+{{IDBGetAllRecordsOptions/direction}} member determines the order
+in which records are returned.
@@ -3605,6 +3721,7 @@ interface IDBIndex {
optional [EnforceRange] unsigned long count);
[NewObject] IDBRequest getAllKeys(optional any query,
optional [EnforceRange] unsigned long count);
+ [NewObject] IDBRequest getAllRecords(optional IDBGetAllRecordsOptions options = {});
[NewObject] IDBRequest count(optional any query);
[NewObject] IDBRequest openCursor(optional any query,
@@ -3752,6 +3869,26 @@ return [=/this=]'s [=index-handle/index=]'s [=index/unique flag=].
If successful, |request|'s {{IDBRequest/result}} will be an
{{Array}} of the [=/keys=].
+ : |request| = |index| .
+ {{IDBIndex/getAllRecords()|getAllRecords}}([|options|])
+ ::
+ Retrieves the [=index/key=], primary [=/key=], and [=/value=]
+ of [=object-store/records=] matching the given |options| (up to
+ {{IDBGetAllRecordsOptions/count}} if given).
+ The {{IDBGetAllRecordsOptions/direction}} option determines
+ the order in which records are returned.
+
+ The |query| parameter for
+ {{IDBIndex/getAll()|getAll}} and
+ {{IDBIndex/getAllKeys()|getAllKeys}} can also be an
+ {{IDBGetAllRecordsOptions}}, which adds
+ {{IDBGetAllRecordsOptions/direction}} support to those methods.
+
+ If successful, |request|'s {{IDBRequest/result}} will
+ be an {{Array}} of objects, each with `key`, `primaryKey`,
+ and `value` properties. The `key` property contains the
+ [=index/record=]'s [=index/key=].
+
: |request| = |index| .
{{IDBIndex/count()|count}}(|query|)
::
@@ -3842,11 +3979,11 @@ The getAll(|query|, |count|) method steps are:
1. If |transaction|'s [=transaction/state=] is not [=transaction/active=],
then [=exception/throw=] a "{{TransactionInactiveError}}" {{DOMException}}.
-1. Let |range| be the result of
- [=/converting a value to a key range=] with |query|.
- Rethrow any exceptions.
+1. Let |range|, |count|, and |direction| be the result of
+ [=converting a value to get all records options=] with |query|
+ and |count| if given. Rethrow any exceptions.
-1. Let |operation| be an algorithm to run [=retrieve multiple referenced values from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, and |count| if given.
+1. Let |operation| be an algorithm to run [=retrieve multiple referenced values from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, |count| if given, and |direction|.
1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|.
@@ -3855,7 +3992,8 @@ The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}})
identifying the [=index/referenced values=] to be retrieved. If null or not given,
an [=unbounded key range=] is used. If |count| is specified and
there are more than |count| records in range, only the first |count|
-will be retrieved.
+will be retrieved. The |query| parameter can also be an
+{{IDBGetAllRecordsOptions}} dictionary, which adds direction support.
@@ -3874,11 +4012,11 @@ The getAllKeys(|query|, |count|) method steps are
1. If |transaction|'s [=transaction/state=] is not [=transaction/active=],
then [=exception/throw=] a "{{TransactionInactiveError}}" {{DOMException}}.
-1. Let |range| be the result of
- [=/converting a value to a key range=] with |query|.
- Rethrow any exceptions.
+1. Let |range|, |count|, and |direction| be the result of
+ [=converting a value to get all records options=] with |query|
+ and |count| if given. Rethrow any exceptions.
-1. Let |operation| be an algorithm to run [=retrieve multiple values from an index=] with |index|, |range|, and |count| if given.
+1. Let |operation| be an algorithm to run [=retrieve multiple values from an index=] with |index|, |range|, |count| if given, and |direction|.
1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|.
@@ -3887,7 +4025,47 @@ The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}})
identifying the [=object-store/record=] keys to be retrieved. If null or not
given, an [=unbounded key range=] is used. If |count| is specified
and there are more than |count| keys in range, only the first |count|
-will be retrieved.
+will be retrieved. The |query| parameter can also be an
+{{IDBGetAllRecordsOptions}} dictionary, which adds direction support.
+
+
+
+
+
+
+The getAllRecords(|options|) method steps are:
+
+1. Let |transaction| be [=/this=]'s [=index-handle/transaction=].
+
+1. Let |index| be [=/this=]'s [=index-handle/index=].
+
+1. If |index| or |index|'s [=/object store=] has
+ been deleted, [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}.
+
+1. If |transaction|'s [=transaction/state=] is not [=transaction/active=],
+ then [=exception/throw=] a "{{TransactionInactiveError}}" {{DOMException}}.
+
+1. Let |direction| be |options|["{{IDBGetAllRecordsOptions/direction}}"].
+
+1. Let |range| be the result of
+ [=/converting a value to a key range=] with
+ |options|["{{IDBGetAllRecordsOptions/query}}"].
+ Rethrow any exceptions.
+
+1. Let |operation| be an algorithm to run [=retrieve multiple records from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, |options|["{{IDBGetAllRecordsOptions/count}}"] if it [=map/exists=], and |direction|.
+
+1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|.
+
+NOTE:
+The |options| parameter is an {{IDBGetAllRecordsOptions}} dictionary.
+Its {{IDBGetAllRecordsOptions/query}} member can be a [=/key=] or
+[=/key range=] (an {{IDBKeyRange}}) identifying the
+[=index/records=] to be retrieved. If null or not given, an
+[=unbounded key range=] is used. Its
+{{IDBGetAllRecordsOptions/count}} member specifies the maximum number
+of records to retrieve. Its
+{{IDBGetAllRecordsOptions/direction}} member determines the order
+in which records are returned.
@@ -5661,15 +5839,29 @@ They return undefined, an ECMAScript value, or an error (a {{DOMException}}):
To
retrieve multiple values from an object
-store with |targetRealm|, |store|, |range| and optional |count|, run these steps.
+store with |targetRealm|, |store|, |range|, optional |count|, and optional |direction|, run these steps.
They return a
[=/sequence=]<{{any}}> or an error (a {{DOMException}}):
1. If |count| is not given or is 0 (zero), let |count| be infinity.
-1. Let |records| be a [=/list=] containing the first |count| [=object-store/records=]
+1. If |direction| is not given, let |direction| be "{{IDBCursorDirection/next}}".
+
+1. If |direction| is "{{IDBCursorDirection/prev}}" or "{{IDBCursorDirection/prevunique}}",
+ let |records| be a [=/list=] containing the last |count| [=object-store/records=]
+ in |store|'s [=object-store/list of records=] whose [=/key=] is
+ [=in=] |range|, in reverse order.
+
+1. Otherwise, let |records| be a [=/list=] containing the first |count| [=object-store/records=]
in |store|'s [=object-store/list of records=] whose [=/key=] is
[=in=] |range|.
+ NOTE:
+ For [=/object stores=], all keys are unique, so
+ "{{IDBCursorDirection/nextunique}}" has the same behavior
+ as "{{IDBCursorDirection/next}}" and
+ "{{IDBCursorDirection/prevunique}}" has the same behavior
+ as "{{IDBCursorDirection/prev}}".
+
1. Let |list| be an empty [=/list=].
1. [=list/For each=] |record| of |records|:
@@ -5704,11 +5896,18 @@ with |store| and |range|, run these steps:
To retrieve multiple keys from an object store
-with |store|, |range| and optional |count|, run these steps:
+with |store|, |range|, optional |count|, and optional |direction|, run these steps:
1. If |count| is not given or is 0 (zero), let |count| be infinity.
-1. Let |records| be a list containing the first |count| [=object-store/records=]
+1. If |direction| is not given, let |direction| be "{{IDBCursorDirection/next}}".
+
+1. If |direction| is "{{IDBCursorDirection/prev}}" or "{{IDBCursorDirection/prevunique}}",
+ let |records| be a [=/list=] containing the last |count| [=object-store/records=]
+ in |store|'s [=object-store/list of records=] whose [=/key=] is
+ [=in=] |range|, in reverse order.
+
+1. Otherwise, let |records| be a [=/list=] containing the first |count| [=object-store/records=]
in |store|'s [=object-store/list of records=] whose [=/key=] is
[=in=] |range|.
@@ -5725,6 +5924,49 @@ with |store|, |range| and optional |count|, run these steps:
+
+
+To retrieve multiple records from an object store
+with |targetRealm|, |store|, |range|, optional |count|, and optional |direction|, run these steps.
+They return a [=/sequence=]<{{any}}> or an error (a {{DOMException}}):
+
+1. If |count| is not given or is 0 (zero), let |count| be infinity.
+
+1. If |direction| is not given, let |direction| be "{{IDBCursorDirection/next}}".
+
+1. If |direction| is "{{IDBCursorDirection/prev}}" or "{{IDBCursorDirection/prevunique}}",
+ let |records| be a [=/list=] containing the last |count| [=object-store/records=]
+ in |store|'s [=object-store/list of records=] whose [=/key=] is
+ [=in=] |range|, in reverse order.
+
+1. Otherwise, let |records| be a [=/list=] containing the first |count| [=object-store/records=]
+ in |store|'s [=object-store/list of records=] whose [=/key=] is
+ [=in=] |range|.
+
+1. Let |list| be an empty [=/list=].
+
+1. [=list/For each=] |record| of |records|:
+
+ 1. Let |serialized| be |record|'s [=/value=]. If an error occurs while reading the value from the
+ underlying storage, return a newly [=exception/created=] "{{NotReadableError}}" {{DOMException}}.
+ 1. Let |entry| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|).
+ 1. Let |keyValue| be the result of [=/converting a
+ key to a value=] with |record|'s [=/key=].
+ 1. Let |result| be a new {{Object}} created as if by the expression `({})`.
+ 1. Perform [=ECMAScript/!=] [$CreateDataProperty$](|result|, "`key`", |keyValue|).
+ 1. Perform [=ECMAScript/!=] [$CreateDataProperty$](|result|, "`primaryKey`", |keyValue|).
+ 1. Perform [=ECMAScript/!=] [$CreateDataProperty$](|result|, "`value`", |entry|).
+ 1. [=list/Append=] |result| to |list|.
+
+ NOTE:
+ For [=/object stores=], `key` and `primaryKey` are the same value
+ because the [=object-store/record=]'s [=/key=] is the primary key.
+
+1. Return |list| converted to a [=/sequence=]<{{any}}>.
+
+
+
+
## Index retrieval operations ## {#index-retrieval-operation}
@@ -5749,12 +5991,47 @@ with |targetRealm|, |index| and |range|, run these steps:
To
retrieve multiple referenced values from an
-index with |targetRealm|, |index|, |range| and optional |count|, run these steps:
+index with |targetRealm|, |index|, |range|, optional |count|, and optional |direction|, run these steps:
1. If |count| is not given or is 0 (zero), let |count| be infinity.
-1. Let |records| be a list containing the first |count| [=object-store/records=]
- in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|.
+1. If |direction| is not given, let |direction| be "{{IDBCursorDirection/next}}".
+
+1. Switch on |direction|:
+
+
+ : "{{IDBCursorDirection/next}}"
+ ::
+ Let |records| be a [=/list=] containing the first |count| [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|.
+
+ : "{{IDBCursorDirection/nextunique}}"
+ ::
+ 1. Let |records| be an empty [=/list=].
+ 1. [=list/For each=] |record| of [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|:
+ 1. If |records| is [=list/empty=], or |record|'s [=index/key=] is
+ not [=equal to=] |records|[|records|'s [=list/size=] − 1]'s [=index/key=]:
+ 1. [=list/Append=] |record| to |records|.
+ 1. If |records|'s [=list/size=] equals |count|, then break.
+
+ : "{{IDBCursorDirection/prev}}"
+ ::
+ Let |records| be a [=/list=] containing the last |count| [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|, in reverse order.
+
+ : "{{IDBCursorDirection/prevunique}}"
+ ::
+ 1. Let |unique| be an empty [=/list=].
+ 1. [=list/For each=] |record| of [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|:
+ 1. If |unique| is [=list/empty=], or |record|'s [=index/key=] is
+ not [=equal to=] |unique|[|unique|'s [=list/size=] − 1]'s [=index/key=]:
+ 1. [=list/Append=] |record| to |unique|.
+ 1. Let |records| be a [=/list=] containing the last |count|
+ items of |unique|, in reverse order.
+
+
1. Let |list| be an empty [=/list=].
@@ -5791,12 +6068,47 @@ To
retrieve a value from an index with
To
retrieve multiple values from an index with
-|index|, |range| and optional |count|, run these steps:
+|index|, |range|, optional |count|, and optional |direction|, run these steps:
1. If |count| is not given or is 0 (zero), let |count| be infinity.
-1. Let |records| be a list containing the first |count| [=index/records=] in
- |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|.
+1. If |direction| is not given, let |direction| be "{{IDBCursorDirection/next}}".
+
+1. Switch on |direction|:
+
+
+ : "{{IDBCursorDirection/next}}"
+ ::
+ Let |records| be a [=/list=] containing the first |count| [=index/records=] in
+ |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|.
+
+ : "{{IDBCursorDirection/nextunique}}"
+ ::
+ 1. Let |records| be an empty [=/list=].
+ 1. [=list/For each=] |record| of [=index/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|:
+ 1. If |records| is [=list/empty=], or |record|'s [=index/key=] is
+ not [=equal to=] |records|[|records|'s [=list/size=] − 1]'s [=index/key=]:
+ 1. [=list/Append=] |record| to |records|.
+ 1. If |records|'s [=list/size=] equals |count|, then break.
+
+ : "{{IDBCursorDirection/prev}}"
+ ::
+ Let |records| be a [=/list=] containing the last |count| [=index/records=] in
+ |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|, in reverse order.
+
+ : "{{IDBCursorDirection/prevunique}}"
+ ::
+ 1. Let |unique| be an empty [=/list=].
+ 1. [=list/For each=] |record| of [=index/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|:
+ 1. If |unique| is [=list/empty=], or |record|'s [=index/key=] is
+ not [=equal to=] |unique|[|unique|'s [=list/size=] − 1]'s [=index/key=]:
+ 1. [=list/Append=] |record| to |unique|.
+ 1. Let |records| be a [=/list=] containing the last |count|
+ items of |unique|, in reverse order.
+
+
1. Let |list| be an empty [=/list=].
@@ -5811,6 +6123,79 @@ To
retrieve multiple values from an index with
+
+
+To
retrieve multiple records from an index with
+|targetRealm|, |index|, |range|, optional |count|, and optional |direction|, run these steps.
+They return a
[=/sequence=]<{{any}}> or an error (a {{DOMException}}):
+
+1. If |count| is not given or is 0 (zero), let |count| be infinity.
+
+1. If |direction| is not given, let |direction| be "{{IDBCursorDirection/next}}".
+
+1. Switch on |direction|:
+
+
+ : "{{IDBCursorDirection/next}}"
+ ::
+ Let |records| be a [=/list=] containing the first |count| [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|.
+
+ : "{{IDBCursorDirection/nextunique}}"
+ ::
+ 1. Let |records| be an empty [=/list=].
+ 1. [=list/For each=] |record| of [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|:
+ 1. If |records| is [=list/empty=], or |record|'s [=index/key=] is
+ not [=equal to=] |records|[|records|'s [=list/size=] − 1]'s [=index/key=]:
+ 1. [=list/Append=] |record| to |records|.
+ 1. If |records|'s [=list/size=] equals |count|, then break.
+
+ : "{{IDBCursorDirection/prev}}"
+ ::
+ Let |records| be a [=/list=] containing the last |count| [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|, in reverse order.
+
+ : "{{IDBCursorDirection/prevunique}}"
+ ::
+ 1. Let |unique| be an empty [=/list=].
+ 1. [=list/For each=] |record| of [=object-store/records=]
+ in |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|:
+ 1. If |unique| is [=list/empty=], or |record|'s [=index/key=] is
+ not [=equal to=] |unique|[|unique|'s [=list/size=] − 1]'s [=index/key=]:
+ 1. [=list/Append=] |record| to |unique|.
+ 1. Let |records| be a [=/list=] containing the last |count|
+ items of |unique|, in reverse order.
+
+
+
+1. Let |list| be an empty [=/list=].
+
+1. [=list/For each=] |record| of |records|:
+
+ 1. Let |serialized| be |record|'s [=index/referenced value=]. If an error occurs while reading the value from the
+ underlying storage, return a newly [=exception/created=] "{{NotReadableError}}" {{DOMException}}.
+ 1. Let |entry| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|).
+ 1. Let |indexKeyValue| be the result of [=/converting a
+ key to a value=] with |record|'s [=index/key=].
+ 1. Let |primaryKeyValue| be the result of [=/converting a
+ key to a value=] with |record|'s [=/value=].
+ 1. Let |result| be a new {{Object}} created as if by the expression `({})`.
+ 1. Perform [=ECMAScript/!=] [$CreateDataProperty$](|result|, "`key`", |indexKeyValue|).
+ 1. Perform [=ECMAScript/!=] [$CreateDataProperty$](|result|, "`primaryKey`", |primaryKeyValue|).
+ 1. Perform [=ECMAScript/!=] [$CreateDataProperty$](|result|, "`value`", |entry|).
+ 1. [=list/Append=] |result| to |list|.
+
+ NOTE:
+ For [=/indexes=], `key` is the [=index/record=]'s [=index/key=]
+ and `primaryKey` is the [=/key=] of the [=object-store/record=] in
+ the [=index/referenced=] [=/object store=].
+
+1. Return |list| converted to a
[=/sequence=]<{{any}}>.
+
+
+
+
## Object store deletion operation ## {#object-store-deletion-operation}
@@ -6719,6 +7104,11 @@ For the revision history of the second edition, see [that document's Revision Hi
* Define [=Queue a database task=] and replace [=Queue a task=] with it (<#421>)
* Add missing parallel step to {{IDBFactory/databases()|databases}}() (<#421>)
* Clarify cursor iteration predicates (<#450>)
+* Added {{IDBObjectStore/getAllRecords()}} and {{IDBIndex/getAllRecords()}} methods. (<#206>)
+* Added {{IDBGetAllRecordsOptions}} dictionary with {{IDBGetAllRecordsOptions/query}}, {{IDBGetAllRecordsOptions/count}}, and {{IDBGetAllRecordsOptions/direction}} members.
+* Added [=convert a value to get all records options=] algorithm to allow {{IDBObjectStore/getAll()}}, {{IDBObjectStore/getAllKeys()}}, {{IDBIndex/getAll()}}, and {{IDBIndex/getAllKeys()}} to accept an {{IDBGetAllRecordsOptions}} dictionary as their first argument, adding direction support.
+* Added [=retrieve multiple records from an object store=] and [=retrieve multiple records from an index=] algorithms.
+* Updated existing retrieval algorithms to support direction.
# Acknowledgements # {#acknowledgements}