From cb4473a798b6ff6137cdfe60277098e16dd52820 Mon Sep 17 00:00:00 2001 From: Steve Becker Date: Fri, 20 Mar 2026 13:05:32 -0700 Subject: [PATCH] Initial commit --- index.bs | 452 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 421 insertions(+), 31 deletions(-) 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}