From c5462df2ef6feb7b57586ab2f9fc5d082b051d20 Mon Sep 17 00:00:00 2001 From: Steve Becker Date: Tue, 24 Jun 2025 16:16:57 -0700 Subject: [PATCH 1/8] Initial commit --- index.bs | 515 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 390 insertions(+), 125 deletions(-) diff --git a/index.bs b/index.bs index 6b5c023..f917750 100644 --- a/index.bs +++ b/index.bs @@ -1371,6 +1371,38 @@ To convert a value to a key range with +A potentially valid key range is a value that could probably be [=convert a value to a key range|converted to a key range=] successfully without throwing an exception. +This algorithm considers certain [=key/type|types=] of values that could produce valid [=key|keys=]. +However, the actual [=convert a value to a key range|conversion=] of a [=potentially valid key range=] to a [=key range=] might still throw an exception. + +NOTE: + For example, a value that is a detached ArrayBuffer is a potentially valid key range that will throw when [=convert a value to a key range|converted to a key range=]. + +
+ + To determine when a value is a potentially valid key range with |value|, run these steps: + + 1. If |value| is a [=/key range=], return true. + + 1. Else if [=ECMAScript/Type=](|value|) is Number, return true. + + 1. Else if [=ECMAScript/Type=](|value|) is String, return true. + + 1. Else if |value| is a {{Date}} (has a \[[DateValue]] internal slot), return true. + + 1. Else if |value| is a [=buffer source type=], return true. + + 1. Else if |value| is an [=ECMAScript/Array exotic object=], return true. + + 1. Else return false. + +NOTE: + The {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} methods use [=is a potentially valid key range=] to handle their first argument. + If the argument is a [=potentially valid key range=], {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} use [=key range=] for their first argument. + Otherwise, {{IDBGetAllOptions}} is used for their first argument. + +
+ ## Cursor ## {#cursor-construct} @@ -1801,6 +1833,29 @@ store.put(4); // will throw DataError ``` + +## Record Snapshot ## {#record-snapshot-construct} + + +A record snapshot contains keys and values copied from an [=object-store/list of records|object store record=] or an [=index/list of records|index record=]. + +
+ +A [=/record snapshot=] has a key which is a [=key=]. + +A [=/record snapshot=] has a value which is a [=value=]. + +NOTE: + For an [=index/list of records|index record=], the snapshot's [=record snapshot/value=] is a copy of the record's [=index/referenced value=]. + For an [=object-store/list of records|object store record=], the snapshot's [=record snapshot/value=] is the [=object-store/record|record's value=]. + +A [=/record snapshot=] also has a primary key which is a [=key=]. + +NOTE: + For an [=index/list of records|index record=], the snapshot's [=record snapshot/primary key=] is the record's [=index/values|value=], which is the key of the record in the index's [=index/referenced|referenced object store=]. + For an [=object-store/list of records|object store record=], the snapshot's [=record snapshot/primary key=] and [=record snapshot/key=] are the same [=key=], which is the [=object-store/record|record's key=]. + +
# Exceptions # {#exceptions} @@ -2726,10 +2781,11 @@ interface IDBObjectStore { [NewObject] IDBRequest clear(); [NewObject] IDBRequest get(any query); [NewObject] IDBRequest getKey(any query); - [NewObject] IDBRequest getAll(optional any query, + [NewObject] IDBRequest getAll(optional any query_or_options, optional [EnforceRange] unsigned long count); - [NewObject] IDBRequest getAllKeys(optional any query, + [NewObject] IDBRequest getAllKeys(optional any query_or_options, optional [EnforceRange] unsigned long count); + [NewObject] IDBRequest getAllRecords(optional IDBGetAllOptions options = {}); [NewObject] IDBRequest count(optional any query); [NewObject] IDBRequest openCursor(optional any query, @@ -2749,6 +2805,12 @@ dictionary IDBIndexParameters { boolean unique = false; boolean multiEntry = false; }; + +dictionary IDBGetAllOptions { + any query = null; + [EnforceRange] unsigned long count; + IDBCursorDirection direction = "next"; +};
@@ -3078,24 +3140,31 @@ The clear() method steps are: [=/key=], or `undefined` if there was no matching [=object-store/record=]. - : |request| = |store| . - {{IDBObjectStore/getAll()|getAll}}(|query| [, |count|]) + : |request| = |store| . {{IDBObjectStore/getAll()|getAll}}(|query| [, |count|]) + : |request| = |store| . {{IDBObjectStore/getAll()|getAll}}({|query|, |count|, |direction|}) :: - Retrieves the [=/values=] of the [=object-store/records=] matching the - given [=/key=] or [=/key range=] in |query| (up to |count| if given). + Retrieves the [=/values=] of the [=object-store/records=] matching the given [=/key=] or [=/key range=] in |query| (up to |count| if given). + Set the |direction| option to "{{IDBCursorDirection/next}}" to retrieve the first |count| values, or "{{IDBCursorDirection/prev}}" to return the last |count| values. - If successful, |request|'s {{IDBRequest/result}} will - be an {{Array}} of the [=/values=]. + If successful, |request|'s {{IDBRequest/result}} will be an {{Array}} of the [=/values=]. - : |request| = |store| . - {{IDBObjectStore/getAllKeys()|getAllKeys}}(|query| [, - |count|]) + : |request| = |store| . {{IDBObjectStore/getAllKeys()|getAllKeys}}(|query| [, |count|]) + : |request| = |store| . {{IDBObjectStore/getAllKeys()|getAllKeys}}({|query|, |count|, |direction|}) :: - Retrieves the [=/keys=] of [=object-store/records=] matching the - given [=/key=] or [=/key range=] in |query| (up to |count| if given). + Retrieves the [=/keys=] of [=object-store/records=] matching the given [=/key=] or [=/key range=] in |query| (up to |count| if given). + Set the |direction| option to "{{IDBCursorDirection/next}}" to retrieve the first |count| keys, or "{{IDBCursorDirection/prev}}" to return the last |count| keys. - If successful, |request|'s {{IDBRequest/result}} will - be an {{Array}} of the [=/keys=]. + If successful, |request|'s {{IDBRequest/result}} will be an {{Array}} of the [=/keys=]. + + : |request| = |store| . {{IDBObjectStore/getAllRecords()|getAllRecords}}({|query|, |count|, |direction|}) + :: + Retrieves the [=/keys=] and [=/values=] of [=object-store/records=]. + + The |query| option specifies a [=/key=] or [=key range=] to match. + The |count| option limits the number or records matched. + Set the |direction| option to "{{IDBCursorDirection/next}}" to retrieve the first |count| records, or "{{IDBCursorDirection/prev}}" to return the last |count| records. + + If successful, |request|'s {{IDBRequest/result}} will be an {{Array}}, with each member being a {{IDBRecord}}. : |request| = |store| . {{IDBObjectStore/count()|count}}(|query|) @@ -3174,7 +3243,7 @@ the first existing key in that range.
-The getAll(|query|, |count|) method steps are: +The getAll(|query_or_options|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=object-store-handle/transaction=]. @@ -3186,17 +3255,30 @@ 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 |range| be a [=key range=]. -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 |direction| be a [=cursor/direction|cursor direction=]. +1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + + 1. Set |direction| to "{{IDBCursorDirection/next}}". + +1. Else: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + + 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + + 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. + +1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "value", |direction|, and |count| if given. 1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. NOTE: -The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}}) +The |range| 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| @@ -3207,7 +3289,7 @@ will be retrieved.
-The getAllKeys(|query|, |count|) method steps are: +The getAllKeys(|query_or_options|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=object-store-handle/transaction=]. @@ -3219,16 +3301,30 @@ 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| be a [=key range=]. + +1. Let |direction| be a [=cursor/direction|cursor direction=]. + +1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + + 1. Set |direction| to "{{IDBCursorDirection/next}}". -1. Let |operation| be an algorithm to run [=retrieve multiple keys from an object store=] with |store|, |range|, and |count| if given. +1. Else: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + + 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + + 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. + +1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "key", |direction|, and |count| if given. 1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. NOTE: -The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}}) +The |range| 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| @@ -3237,6 +3333,39 @@ will be retrieved.
+
+ +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, then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}. + +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 |options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + +1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "record", |options|["{{IDBGetAllOptions/direction}}"], and |options|["{{IDBGetAllOptions/count}}"] if given. + +1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. + +
+ + + + + +
The count(|query|) method steps are: @@ -3600,10 +3729,11 @@ interface IDBIndex { [NewObject] IDBRequest get(any query); [NewObject] IDBRequest getKey(any query); - [NewObject] IDBRequest getAll(optional any query, + [NewObject] IDBRequest getAll(optional any query_or_options, optional [EnforceRange] unsigned long count); - [NewObject] IDBRequest getAllKeys(optional any query, + [NewObject] IDBRequest getAllKeys(optional any query_or_options, optional [EnforceRange] unsigned long count); + [NewObject] IDBRequest getAllRecords(optional IDBGetAllOptions options = {}); [NewObject] IDBRequest count(optional any query); [NewObject] IDBRequest openCursor(optional any query, @@ -3732,24 +3862,34 @@ return [=/this=]'s [=index-handle/index=]'s [=index/unique flag=]. [=/key=], or `undefined` if there was no matching [=object-store/record=]. - : |request| = |index| . - {{IDBIndex/getAll()|getAll}}(|query| [, |count|]) + : |request| = |index| . {{IDBIndex/getAll()|getAll}}(|query| [, |count|]) + : |request| = |index| . {{IDBIndex/getAll()|getAll}}({|query|, |count|, |direction|}) :: - Retrieves the [=/values=] of the [=object-store/records=] matching the given - [=/key=] or [=/key range=] in |query| (up to |count| if given). + Retrieves the [=/values=] of the [=object-store/records=] matching the given [=/key=] or [=/key range=] in |query| (up to |count| if given). + Set the |direction| option to "{{IDBCursorDirection/next}}" to retrieve the first |count| values, "{{IDBCursorDirection/prev}}" to return the last |count| values. + Set the |direction| option to "{{IDBCursorDirection/nextunique}}" or "{{IDBCursorDirection/prevunique}}" to exclude records with duplicate index keys after retrieving the first record with the duplicate index key. - If successful, |request|'s {{IDBRequest/result}} will be an - {{Array}} of the [=/values=]. + If successful, |request|'s {{IDBRequest/result}} will be an {{Array}} of the [=/values=]. - : |request| = |index| . - {{IDBIndex/getAllKeys()|getAllKeys}}(|query| [, - |count|]) + : |request| = |index| . {{IDBIndex/getAllKeys()|getAllKeys}}(|query| [, |count|]) + : |request| = |index| . {{IDBIndex/getAllKeys()|getAllKeys}}({|query|, |count|, |direction|}) :: - Retrieves the [=/keys=] of [=object-store/records=] matching the given - [=/key=] or [=/key range=] in |query| (up to |count| if given). + Retrieves the [=/keys=] of [=object-store/records=] matching the given [=/key=] or [=/key range=] in |query| (up to |count| if given). + Set the |direction| option to "{{IDBCursorDirection/next}}" to retrieve the first |count| keys, "{{IDBCursorDirection/prev}}" to return the last |count| keys. + Set the |direction| option to "{{IDBCursorDirection/nextunique}}" or "{{IDBCursorDirection/prevunique}}" to exclude records with duplicate index keys after retrieving the first record with the duplicate index key. - If successful, |request|'s {{IDBRequest/result}} will be an - {{Array}} of the [=/keys=]. + If successful, |request|'s {{IDBRequest/result}} will be an {{Array}} of the [=/keys=]. + + : |request| = |index| . {{IDBIndex/getAllRecords()|getAllRecords}}({|query|, |count|, |direction|}) + :: + Retrieves the [=/keys=], [=/values=], and index [=/keys=] of [=object-store/records=]. + + The |query| option specifies a [=/key=] or [=key range=] to match. + The |count| option limits the number or records matched. + Set the |direction| option to "{{IDBCursorDirection/next}}" to retrieve the first |count| records, "{{IDBCursorDirection/prev}}" to return the last |count| records. + Set the |direction| option to "{{IDBCursorDirection/nextunique}}" or "{{IDBCursorDirection/prevunique}}" to exclude records with duplicate index keys after retrieving the first record with the duplicate index key. + + If successful, |request|'s {{IDBRequest/result}} will be an {{Array}}, with each member being an {{IDBRecord}}. Use the {{IDBRecord/key|IDBRecord's key}} to get the record's index [=key=]. Use the {{IDBRecord/primaryKey|IDBRecord's primaryKey}} to get the record's [=key=]. : |request| = |index| . {{IDBIndex/count()|count}}(|query|) @@ -3829,7 +3969,7 @@ in that range.
-The getAll(|query|, |count|) method steps are: +The getAll(|query_or_options|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=index-handle/transaction=]. @@ -3841,16 +3981,30 @@ 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| be a [=key range=]. + +1. Let |direction| be a [=cursor/direction|cursor direction=]. + +1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + + 1. Set |direction| to "{{IDBCursorDirection/next}}". + +1. Else: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + + 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + + 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. -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 items from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, "value", |direction| and |count| if given. 1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. NOTE: -The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}}) +The |range| 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| @@ -3861,7 +4015,7 @@ will be retrieved.
-The getAllKeys(|query|, |count|) method steps are: +The getAllKeys(|query_or_options|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=index-handle/transaction=]. @@ -3873,16 +4027,30 @@ 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| be a [=key range=]. + +1. Let |direction| be a [=cursor/direction|cursor direction=]. + +1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + + 1. Set |direction| to "{{IDBCursorDirection/next}}". -1. Let |operation| be an algorithm to run [=retrieve multiple values from an index=] with |index|, |range|, and |count| if given. +1. Else: + + 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + + 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + + 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. + +1. Let |operation| be an algorithm to run [=retrieve multiple items from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, "key", |direction| and |count| if given. 1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. NOTE: -The |query| parameter can be a [=/key=] or [=/key range=] (an {{IDBKeyRange}}) +The |range| 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| @@ -3891,6 +4059,39 @@ will be retrieved.
+
+ +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, then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}. + +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 |options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + +1. Let |operation| be an algorithm to run [=retrieve multiple items from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, "record", |options|["{{IDBGetAllOptions/direction}}"], and |options|["{{IDBGetAllOptions/count}}"] if given. + +1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. + +
+ + + + + +
The count(|query|) method steps are: @@ -4215,6 +4416,44 @@ The includes(|key|) method steps are:
+ +## The {{IDBRecord}} interface ## {#record-interface} + + +The {{IDBRecord}} interface represents a [=record snapshot=]. + + +[Exposed=(Window,Worker)] +interface IDBRecord { + readonly attribute any key; + readonly attribute any primaryKey; + readonly attribute any value; +}; + + +
+ : |record| . {{IDBRecord/key}} + :: + Returns the record's [=key=]. + + : |record| . {{IDBRecord/primaryKey}} + :: + If the record is retrieved from an [=index=], returns the key of the record in the index's [=index/referenced|referenced object store=]. + + If the record is retrieved from an [=object store=], returns the record's [=key=], which is the same key as |record|.{{IDBRecord/key}}. + + : |record| . {{IDBRecord/value}} + :: + Returns the record's [=value=]. +
+ +The key getter steps are to return the result of [=/converting a key to a value=] with [=/this=]'s [=record snapshot/key=]. + +The primaryKey getter steps are to return the result of [=/converting a key to a value=] with [=/this=]'s [=record snapshot/primary key=]. + +The value getter steps are to return [=/this=]'s [=record snapshot/value=]. + + ## The {{IDBCursor}} interface ## {#cursor-interface} @@ -5488,6 +5727,7 @@ To fire an error event at a |request|, run these steps:
+ ## Clone a value ## {#clone-value} @@ -5657,32 +5897,6 @@ 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. -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=] - 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. Append |entry| to |list|. - -1. Return |list| converted to a [=/sequence=]<{{any}}>. - -
- -
To retrieve a key from an object store @@ -5702,24 +5916,43 @@ with |store| and |range|, run these steps:
-To retrieve multiple keys from an object store -with |store|, |range| and optional |count|, run these steps: +To retrieve multiple items from an object store with |targetRealm|, |store|, |range|, |kind|, |direction|, and optional |count|, 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 |store|'s [=object-store/list of records=] whose [=/key=] is - [=in=] |range|. +1. Let |records| be a an empty [=/list=] of [=object-store/records=]. + +1. If |direction| is "{{IDBCursorDirection/next}}" or "{{IDBCursorDirection/nextunique}}", set |records| to the first |count| of |store|'s [=object-store/list of records=] whose [=/key=] is [=in=] |range|. + +1. If |direction| is "{{IDBCursorDirection/prev}}" or "{{IDBCursorDirection/prevunique}}", set |records| to the last |count| of |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. [=list/For each=] |record| of |records|, switching on |kind|: + +
+ : "key" + :: + 1. Let |key| be the result of [=/converting a key to a value=] with |record|'s key. + 1. [=list/Append=] |key| to |list|. + + : "value" + :: + 1. Let |serialized| be |record|'s [=/value=]. + 1. Let |value| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|). + 1. [=list/Append=] |value| to |list|. - 1. Let |entry| be the result of [=/converting a - key to a value=] with |record|'s key. - 1. Append |entry| to |list|. + : "record" + :: + 1. Let |key| be the |record|'s key. + 1. Let |serialized| be |record|'s [=/value=]. + 1. Let |value| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|). + 1. Let |record snapshot| be a new [=record snapshot=] with its [=record snapshot/key=] set to |key|, [=record snapshot/value=] set to |value|, and [=record snapshot/primary key=] set to |key|. + 1. [=list/Append=] |record snapshot| to |list|. + +
-1. Return |list| converted to a [=/sequence=]<{{any}}>. +1. Return |list|.
@@ -5745,32 +5978,6 @@ 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: - -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. Let |list| be an empty [=/list=]. - -1. [=list/For each=] |record| of |records|: - - 1. Let |serialized| be |record|'s [=index/referenced value=]. - 1. Let |entry| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|). - 1. Append |entry| to |list|. - -1. Return |list| converted to a [=/sequence=]<{{any}}>. - -
- -NOTE: - The [=index/values=] of an [=index/record=] in an index are the keys of - [=object-store/records=] in the [=index/referenced=] object store. -
To retrieve a value from an index with @@ -5789,26 +5996,82 @@ To retrieve a value from an index with
-To retrieve multiple values from an index with -|index|, |range| and optional |count|, run these steps: +To retrieve multiple items from an index with |targetRealm|, |index|, |range|, |kind|, |direction| and optional |count|, 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. Let |records| be a an empty [=/list=] of [=object-store/records=]. + +1. Switching on |direction|: + +
+ : "next" + :: + 1. Set |records| to the first |count| of |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. + + : "nextunique" + :: + 1. Let |range records| be a list containing the |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. + 1. Let |range records length| be |range records|'s [=list/size=]. + 1. Let |i| be 0. + 1. While |i| is less than |range records length|, then: + 1. Increase |i| by 1. + 1. if |record|'s [=list/size=] is equal to |count|, then [=iteration/break=]. + 1. If |i| is greater than 0 and the result of [=comparing two keys=] using the keys from |range records[i]| and |range records[i-1]| is equal, then [=iteration/continue=]. + 1. Else [=list/append=] |range records[i]| to |records|. + + : "prev" + :: + 1. Set |records| to the last |count| of |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. + + : "prevunique" + :: + 1. Let |range records| be a list containing the |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. + 1. Let |range records length| be |range records|'s [=list/size=]. + 1. Let |i| be 0. + 1. While |i| is less than |range records length|, then: + 1. Increase |i| by 1. + 1. if |record|'s [=list/size=] is equal to |count|, then [=iteration/break=]. + 1. If |i| is greater than 0 and the result of [=comparing two keys=] using the keys from |range records[i]| and |range records[i-1]| is equal, then [=iteration/continue=]. + 1. Else [=list/prepend=] |range records[i]| to |records|. + +
1. Let |list| be an empty [=/list=]. -1. [=list/For each=] |record| of |records|: +1. [=list/For each=] |record| of |records|, switching on |kind|: - 1. Let |entry| be the result of [=/converting a - key to a value=] with |record|'s value. - 1. Append |entry| to |list|. +
+ : "key" + :: + 1. Let |key| be the result of [=/converting a key to a value=] with |record|'s value. + 1. [=list/Append=] |key| to |list|. -1. Return |list| converted to a [=/sequence=]<{{any}}>. + : "value" + :: + 1. Let |serialized| be |record|'s [=index/referenced value=]. + 1. Let |value| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|). + 1. [=list/Append=] |value| to |list|. + + : "record" + :: + 1. Let |index key| be the |record|'s key. + 1. Let |key| be the |record|'s value. + 1. Let |serialized| be |record|'s [=index/referenced value=]. + 1. Let |value| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|). + 1. Let |record snapshot| be a new [=record snapshot=] with its [=record snapshot/key=] set to |index key|, [=record snapshot/value=] set to |value|, and [=record snapshot/primary key=] set to |key|. + 1. [=list/Append=] |record snapshot| to |list|. + +
+ +1. Return |list|.
+ + ## Object store deletion operation ## {#object-store-deletion-operation} @@ -6718,6 +6981,8 @@ 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>) +* Add {{IDBObjectStore/getAllRecords(options)}} method to {{IDBObjectStore}} and {{IDBIndex}}. (<#206>) +* Add direction option to {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} for {{IDBObjectStore}} and {{IDBIndex}} (<#130>) # Acknowledgements # {#acknowledgements} From cdc3aa256ee212f4a5f9fe2329fb78ddfe244cb4 Mon Sep 17 00:00:00 2001 From: Steve Becker Date: Tue, 24 Jun 2025 23:20:54 -0700 Subject: [PATCH 2/8] Try to improve definition of 'potentially valid key range' --- index.bs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.bs b/index.bs index f917750..e27108b 100644 --- a/index.bs +++ b/index.bs @@ -1371,12 +1371,12 @@ To convert a value to a key range with
-A potentially valid key range is a value that could probably be [=convert a value to a key range|converted to a key range=] successfully without throwing an exception. -This algorithm considers certain [=key/type|types=] of values that could produce valid [=key|keys=]. -However, the actual [=convert a value to a key range|conversion=] of a [=potentially valid key range=] to a [=key range=] might still throw an exception. + +A potentially valid key range is a value that is a [=key/type|type of key=] or a [=key range=]. +However, [=convert a value to a key range|converting=] a [=potentially valid key range=] to a [=key range=] could throw an exception. NOTE: - For example, a value that is a detached ArrayBuffer is a potentially valid key range that will throw when [=convert a value to a key range|converted to a key range=]. + For example, a value that is a [=BufferSource/detached|detached BufferSource=] is a [=potentially valid key range=] that will throw an exception when used with [=convert a value to a key range=].
@@ -1398,7 +1398,7 @@ NOTE: NOTE: The {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} methods use [=is a potentially valid key range=] to handle their first argument. - If the argument is a [=potentially valid key range=], {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} use [=key range=] for their first argument. + If the argument is a [=potentially valid key range=], {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} use a [=key range=] for their first argument. Otherwise, {{IDBGetAllOptions}} is used for their first argument.
From 43e154b0bf1ecf52793f017cb79aa5631d216a30 Mon Sep 17 00:00:00 2001 From: Steve Becker Date: Thu, 26 Jun 2025 15:50:53 -0700 Subject: [PATCH 3/8] Rework 'potentially valid key range' definition and notes to address review feedback --- index.bs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/index.bs b/index.bs index e27108b..2c0adf6 100644 --- a/index.bs +++ b/index.bs @@ -1372,15 +1372,14 @@ To convert a value to a key range with
-A potentially valid key range is a value that is a [=key/type|type of key=] or a [=key range=]. -However, [=convert a value to a key range|converting=] a [=potentially valid key range=] to a [=key range=] could throw an exception. +A potentially valid key range is an ECMAScript value that is probably a [=key=] or [=key range=], however, [=convert a value to a key range|converting=] this value to a [=key range=] may throw an exception. NOTE: - For example, a value that is a [=BufferSource/detached|detached BufferSource=] is a [=potentially valid key range=] that will throw an exception when used with [=convert a value to a key range=]. + For example, a [=BufferSource/detached|detached BufferSource=] is a [=potentially valid key range=] that will throw an exception when used with [=convert a value to a key range=].
- To determine when a value is a potentially valid key range with |value|, run these steps: + To determine when a value is a potentially valid key range with ECMAScript |value|, run these steps: 1. If |value| is a [=/key range=], return true. @@ -1396,10 +1395,15 @@ NOTE: 1. Else return false. -NOTE: +
+ NOTE: The {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} methods use [=is a potentially valid key range=] to handle their first argument. - If the argument is a [=potentially valid key range=], {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} use a [=key range=] for their first argument. - Otherwise, {{IDBGetAllOptions}} is used for their first argument. + If the argument is a [=potentially valid key range=], {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} run [=convert a value to a key range=] with the argument. + Otherwise, {{IDBGetAllOptions}} is used for the first argument. + + {{IDBObjectStore/getAll()}} and {{IDBObjectStore/getAllKeys()}} throw exceptions for {{Date}}, {{Array}}, and {{ArrayBuffer}} first arguments that return invalid when used with [=convert a value to a key=]. + For example, running {{IDBObjectStore/getAll()}} with a NaN {{Date}} first argument throws an exception instead of successfully using an {{IDBGetAllOptions}} dictionary with default values. +
From b2fe0e42dccbfcc43d8965c51d953f70a5fbae97 Mon Sep 17 00:00:00 2001 From: Steve Becker Date: Tue, 22 Jul 2025 17:24:19 -0700 Subject: [PATCH 4/8] Address code review feedback - nits --- index.bs | 100 +++++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/index.bs b/index.bs index 2c0adf6..2c6da92 100644 --- a/index.bs +++ b/index.bs @@ -1838,7 +1838,7 @@ store.put(4); // will throw DataError
-## Record Snapshot ## {#record-snapshot-construct} +## Record snapshot ## {#record-snapshot-construct} A record snapshot contains keys and values copied from an [=object-store/list of records|object store record=] or an [=index/list of records|index record=]. @@ -2785,9 +2785,9 @@ interface IDBObjectStore { [NewObject] IDBRequest clear(); [NewObject] IDBRequest get(any query); [NewObject] IDBRequest getKey(any query); - [NewObject] IDBRequest getAll(optional any query_or_options, + [NewObject] IDBRequest getAll(optional any queryOrOptions, optional [EnforceRange] unsigned long count); - [NewObject] IDBRequest getAllKeys(optional any query_or_options, + [NewObject] IDBRequest getAllKeys(optional any queryOrOptions, optional [EnforceRange] unsigned long count); [NewObject] IDBRequest getAllRecords(optional IDBGetAllOptions options = {}); [NewObject] IDBRequest count(optional any query); @@ -3168,7 +3168,7 @@ The clear() method steps are: The |count| option limits the number or records matched. Set the |direction| option to "{{IDBCursorDirection/next}}" to retrieve the first |count| records, or "{{IDBCursorDirection/prev}}" to return the last |count| records. - If successful, |request|'s {{IDBRequest/result}} will be an {{Array}}, with each member being a {{IDBRecord}}. + If successful, |request|'s {{IDBRequest/result}} will be an {{Array}}, with each member being an {{IDBRecord}}. : |request| = |store| . {{IDBObjectStore/count()|count}}(|query|) @@ -3247,7 +3247,7 @@ the first existing key in that range.
-The getAll(|query_or_options|, |count|) method steps are: +The getAll(|queryOrOptions|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=object-store-handle/transaction=]. @@ -3263,19 +3263,19 @@ The getAll(|query_or_options|, |count|) met 1. Let |direction| be a [=cursor/direction|cursor direction=]. -1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: +1. If running [=is a potentially valid key range=] with |queryOrOptions| is true, then: - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|. Rethrow any exceptions. 1. Set |direction| to "{{IDBCursorDirection/next}}". 1. Else: - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + 1. Set |count| to |queryOrOptions|["{{IDBGetAllOptions/count}}"]. - 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. + 1. Set |direction| to |queryOrOptions|["{{IDBGetAllOptions/direction}}"]. 1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "value", |direction|, and |count| if given. @@ -3293,7 +3293,7 @@ will be retrieved.
-The getAllKeys(|query_or_options|, |count|) method steps are: +The getAllKeys(|queryOrOptions|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=object-store-handle/transaction=]. @@ -3309,19 +3309,19 @@ The getAllKeys(|query_or_options|, |count|) 1. Let |direction| be a [=cursor/direction|cursor direction=]. -1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: +1. If running [=is a potentially valid key range=] with |queryOrOptions| is true, then: - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|. Rethrow any exceptions. 1. Set |direction| to "{{IDBCursorDirection/next}}". 1. Else: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + + 1. Set |count| to |queryOrOptions|["{{IDBGetAllOptions/count}}"]. - 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. + 1. Set |direction| to |queryOrOptions|["{{IDBGetAllOptions/direction}}"]. 1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "key", |direction|, and |count| if given. @@ -3733,9 +3733,9 @@ interface IDBIndex { [NewObject] IDBRequest get(any query); [NewObject] IDBRequest getKey(any query); - [NewObject] IDBRequest getAll(optional any query_or_options, + [NewObject] IDBRequest getAll(optional any queryOrOptions, optional [EnforceRange] unsigned long count); - [NewObject] IDBRequest getAllKeys(optional any query_or_options, + [NewObject] IDBRequest getAllKeys(optional any queryOrOptions, optional [EnforceRange] unsigned long count); [NewObject] IDBRequest getAllRecords(optional IDBGetAllOptions options = {}); [NewObject] IDBRequest count(optional any query); @@ -3973,7 +3973,7 @@ in that range.
-The getAll(|query_or_options|, |count|) method steps are: +The getAll(|queryOrOptions|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=index-handle/transaction=]. @@ -3989,19 +3989,19 @@ The getAll(|query_or_options|, |count|) method st 1. Let |direction| be a [=cursor/direction|cursor direction=]. -1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: +1. If running [=is a potentially valid key range=] with |queryOrOptions| is true, then: - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|. Rethrow any exceptions. 1. Set |direction| to "{{IDBCursorDirection/next}}". 1. Else: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + + 1. Set |count| to |queryOrOptions|["{{IDBGetAllOptions/count}}"]. - 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. + 1. Set |direction| to |queryOrOptions|["{{IDBGetAllOptions/direction}}"]. 1. Let |operation| be an algorithm to run [=retrieve multiple items from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, "value", |direction| and |count| if given. @@ -4019,7 +4019,7 @@ will be retrieved.
-The getAllKeys(|query_or_options|, |count|) method steps are: +The getAllKeys(|queryOrOptions|, |count|) method steps are: 1. Let |transaction| be [=/this=]'s [=index-handle/transaction=]. @@ -4035,19 +4035,19 @@ The getAllKeys(|query_or_options|, |count|) metho 1. Let |direction| be a [=cursor/direction|cursor direction=]. -1. If running [=is a potentially valid key range=] with |query_or_options| is true, then: +1. If running [=is a potentially valid key range=] with |queryOrOptions| is true, then: - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|. Rethrow any exceptions. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|. Rethrow any exceptions. 1. Set |direction| to "{{IDBCursorDirection/next}}". 1. Else: - 1. Set |range| to the result of [=/converting a value to a key range=] with |query_or_options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. + 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - 1. Set |count| to |query_or_options|["{{IDBGetAllOptions/count}}"]. + 1. Set |count| to |queryOrOptions|["{{IDBGetAllOptions/count}}"]. - 1. Set |direction| to |query_or_options|["{{IDBGetAllOptions/direction}}"]. + 1. Set |direction| to |queryOrOptions|["{{IDBGetAllOptions/direction}}"]. 1. Let |operation| be an algorithm to run [=retrieve multiple items from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, "key", |direction| and |count| if given. @@ -4442,9 +4442,9 @@ interface IDBRecord { : |record| . {{IDBRecord/primaryKey}} :: - If the record is retrieved from an [=index=], returns the key of the record in the index's [=index/referenced|referenced object store=]. + If the record was retrieved from an [=index=], returns the key of the record in the index's [=index/referenced|referenced object store=]. - If the record is retrieved from an [=object store=], returns the record's [=key=], which is the same key as |record|.{{IDBRecord/key}}. + If the record was retrieved from an [=object store=], returns the record's [=key=], which is the same key as |record|.{{IDBRecord/key}}. : |record| . {{IDBRecord/value}} :: @@ -5924,7 +5924,7 @@ To retrieve multiple items from an object store with |targetRealm|, | 1. If |count| is not given or is 0 (zero), let |count| be infinity. -1. Let |records| be a an empty [=/list=] of [=object-store/records=]. +1. Let |records| be an empty [=/list=] of [=object-store/records=]. 1. If |direction| is "{{IDBCursorDirection/next}}" or "{{IDBCursorDirection/nextunique}}", set |records| to the first |count| of |store|'s [=object-store/list of records=] whose [=/key=] is [=in=] |range|. @@ -5951,8 +5951,8 @@ To retrieve multiple items from an object store with |targetRealm|, | 1. Let |key| be the |record|'s key. 1. Let |serialized| be |record|'s [=/value=]. 1. Let |value| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|). - 1. Let |record snapshot| be a new [=record snapshot=] with its [=record snapshot/key=] set to |key|, [=record snapshot/value=] set to |value|, and [=record snapshot/primary key=] set to |key|. - 1. [=list/Append=] |record snapshot| to |list|. + 1. Let |recordSnapshot| be a new [=record snapshot=] with its [=record snapshot/key=] set to |key|, [=record snapshot/value=] set to |value|, and [=record snapshot/primary key=] set to |key|. + 1. [=list/Append=] |recordSnapshot| to |list|. @@ -6004,7 +6004,7 @@ To retrieve multiple items from an index with |targetRealm|, |index|, 1. If |count| is not given or is 0 (zero), let |count| be infinity. -1. Let |records| be a an empty [=/list=] of [=object-store/records=]. +1. Let |records| be an empty [=/list=] of [=object-store/records=]. 1. Switching on |direction|: @@ -6015,14 +6015,14 @@ To retrieve multiple items from an index with |targetRealm|, |index|, : "nextunique" :: - 1. Let |range records| be a list containing the |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. - 1. Let |range records length| be |range records|'s [=list/size=]. + 1. Let |rangeRecords| be a list containing the |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. + 1. Let |rangeRecordsLength| be |rangeRecords|'s [=list/size=]. 1. Let |i| be 0. - 1. While |i| is less than |range records length|, then: + 1. While |i| is less than |rangeRecordsLength|, then: 1. Increase |i| by 1. 1. if |record|'s [=list/size=] is equal to |count|, then [=iteration/break=]. - 1. If |i| is greater than 0 and the result of [=comparing two keys=] using the keys from |range records[i]| and |range records[i-1]| is equal, then [=iteration/continue=]. - 1. Else [=list/append=] |range records[i]| to |records|. + 1. If the result of [=comparing two keys=] using the keys from |rangeRecords[i]| and |rangeRecords[i-1]| is equal, then [=iteration/continue=]. + 1. Else [=list/append=] |rangeRecords[i]| to |records|. : "prev" :: @@ -6030,14 +6030,14 @@ To retrieve multiple items from an index with |targetRealm|, |index|, : "prevunique" :: - 1. Let |range records| be a list containing the |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. - 1. Let |range records length| be |range records|'s [=list/size=]. + 1. Let |rangeRecords| be a list containing the |index|'s [=index/list of records=] whose [=index/key=] is [=in=] |range|. + 1. Let |rangeRecordsLength| be |rangeRecords|'s [=list/size=]. 1. Let |i| be 0. - 1. While |i| is less than |range records length|, then: + 1. While |i| is less than |rangeRecordsLength|, then: 1. Increase |i| by 1. 1. if |record|'s [=list/size=] is equal to |count|, then [=iteration/break=]. - 1. If |i| is greater than 0 and the result of [=comparing two keys=] using the keys from |range records[i]| and |range records[i-1]| is equal, then [=iteration/continue=]. - 1. Else [=list/prepend=] |range records[i]| to |records|. + 1. If the result of [=comparing two keys=] using the keys from |rangeRecords[i]| and |rangeRecords[i-1]| is equal, then [=iteration/continue=]. + 1. Else [=list/prepend=] |rangeRecords[i]| to |records|. @@ -6063,8 +6063,8 @@ To retrieve multiple items from an index with |targetRealm|, |index|, 1. Let |key| be the |record|'s value. 1. Let |serialized| be |record|'s [=index/referenced value=]. 1. Let |value| be [=ECMAScript/!=] [$StructuredDeserialize$](|serialized|, |targetRealm|). - 1. Let |record snapshot| be a new [=record snapshot=] with its [=record snapshot/key=] set to |index key|, [=record snapshot/value=] set to |value|, and [=record snapshot/primary key=] set to |key|. - 1. [=list/Append=] |record snapshot| to |list|. + 1. Let |recordSnapshot| be a new [=record snapshot=] with its [=record snapshot/key=] set to |index key|, [=record snapshot/value=] set to |value|, and [=record snapshot/primary key=] set to |key|. + 1. [=list/Append=] |recordSnapshot| to |list|. From bdddcca56b196d9bccf23de5754a9005d8b51e8f Mon Sep 17 00:00:00 2001 From: Steve Becker Date: Wed, 23 Jul 2025 13:15:58 -0700 Subject: [PATCH 5/8] Create an algorithm for repeated get all operations --- index.bs | 255 ++++++++++++++----------------------------------------- 1 file changed, 65 insertions(+), 190 deletions(-) diff --git a/index.bs b/index.bs index 2c6da92..f17a81c 100644 --- a/index.bs +++ b/index.bs @@ -3249,44 +3249,8 @@ the first existing key in that range. The getAll(|queryOrOptions|, |count|) 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 |range| be a [=key range=]. - -1. Let |direction| be a [=cursor/direction|cursor direction=]. - -1. If running [=is a potentially valid key range=] with |queryOrOptions| is true, then: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|. Rethrow any exceptions. - - 1. Set |direction| to "{{IDBCursorDirection/next}}". - -1. Else: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - - 1. Set |count| to |queryOrOptions|["{{IDBGetAllOptions/count}}"]. - - 1. Set |direction| to |queryOrOptions|["{{IDBGetAllOptions/direction}}"]. - -1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "value", |direction|, and |count| if given. - -1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. - -NOTE: -The |range| 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. +1. Return the result of [=/creating a request to retrieve multiple items=] with [=ECMAScript/the current Realm record=], [=/this=], "value", |queryOrOptions|, and |count| if given. + Rethrow any exceptions.
@@ -3295,44 +3259,8 @@ will be retrieved. The getAllKeys(|queryOrOptions|, |count|) 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 |range| be a [=key range=]. - -1. Let |direction| be a [=cursor/direction|cursor direction=]. - -1. If running [=is a potentially valid key range=] with |queryOrOptions| is true, then: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|. Rethrow any exceptions. - - 1. Set |direction| to "{{IDBCursorDirection/next}}". - -1. Else: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - - 1. Set |count| to |queryOrOptions|["{{IDBGetAllOptions/count}}"]. - - 1. Set |direction| to |queryOrOptions|["{{IDBGetAllOptions/direction}}"]. - -1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "key", |direction|, and |count| if given. - -1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. - -NOTE: -The |range| 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. +1. Return the result of [=/creating a request to retrieve multiple items=] with [=ECMAScript/the current Realm record=], [=/this=], "key", |queryOrOptions|, and |count| if given. + Rethrow any exceptions.
@@ -3341,28 +3269,11 @@ will be retrieved. 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, then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}. - -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 |options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - -1. Let |operation| be an algorithm to run [=retrieve multiple items from an object store=] with [=ECMAScript/the current Realm record=], |store|, |range|, "record", |options|["{{IDBGetAllOptions/direction}}"], and |options|["{{IDBGetAllOptions/count}}"] if given. - -1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. +1. Return the result of [=/creating a request to retrieve multiple items=] with [=ECMAScript/the current Realm record=], [=/this=], "record", and |options|. + Rethrow any exceptions.
- -
@@ -4021,44 +3896,8 @@ will be retrieved. The getAllKeys(|queryOrOptions|, |count|) 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 |range| be a [=key range=]. - -1. Let |direction| be a [=cursor/direction|cursor direction=]. - -1. If running [=is a potentially valid key range=] with |queryOrOptions| is true, then: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|. Rethrow any exceptions. - - 1. Set |direction| to "{{IDBCursorDirection/next}}". - -1. Else: - - 1. Set |range| to the result of [=/converting a value to a key range=] with |queryOrOptions|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - - 1. Set |count| to |queryOrOptions|["{{IDBGetAllOptions/count}}"]. - - 1. Set |direction| to |queryOrOptions|["{{IDBGetAllOptions/direction}}"]. - -1. Let |operation| be an algorithm to run [=retrieve multiple items from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, "key", |direction| and |count| if given. - -1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. - -NOTE: -The |range| 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. +1. Return the result of [=/creating a request to retrieve multiple items=] with [=ECMAScript/the current Realm record=], [=/this=], "key", |queryOrOptions|, and |count| if given. + Rethrow any exceptions. @@ -4067,28 +3906,11 @@ will be retrieved. 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, then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}. - -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 |options|["{{IDBGetAllOptions/query}}"]. Rethrow any exceptions. - -1. Let |operation| be an algorithm to run [=retrieve multiple items from an index=] with [=ECMAScript/the current Realm record=], |index|, |range|, "record", |options|["{{IDBGetAllOptions/direction}}"], and |options|["{{IDBGetAllOptions/count}}"] if given. - -1. Return the result (an {{IDBRequest}}) of running [=asynchronously execute a request=] with [=/this=] and |operation|. +1. Return the result of [=/creating a request to retrieve multiple items=] with [=ECMAScript/the current Realm record=], [=/this=], "record", and |options|. + Rethrow any exceptions. - -