From 114932f04dbba99e52c3b4d4b93f8f0bae0ae9d1 Mon Sep 17 00:00:00 2001 From: Yao Xiao Date: Tue, 13 Aug 2024 17:45:49 -0400 Subject: [PATCH 1/4] [spec] Remove WindowSharedStorage/WorkletSharedStorage interfaces This addresses the misalignment between spec and code: https://github.com/WICG/shared-storage/issues/154. For the spec, we remove `WindowSharedStorage` and `WorkletSharedStorage` interfaces, and use `[Exposed=Window/SharedStorageWorklet]` to control the exposure of individual fields. --- spec.bs | 393 +++++++++++++++++++++++--------------------------------- 1 file changed, 158 insertions(+), 235 deletions(-) diff --git a/spec.bs b/spec.bs index 01e0a00..fa25dc9 100644 --- a/spec.bs +++ b/spec.bs @@ -270,11 +270,11 @@ When {{Worklet/addModule()}} is called for a worklet, it will run [=check if add
Here are the scenarios where the algorithms [=determine whether shared storage is allowed by context=] and [=check if user preference setting allows access to shared storage=] are used: - - For each method under [[#window-setter]], |environment| is the current context, and |origin| is |environment|'s [=environment settings object/origin=]. - For creating a worklet, |environment| is the [=environment settings object=] associated with the {{Window}} that created the worklet, and |origin| is the module script url's [=url/origin=]. - - For running operations on a worklet (from a {{Window}}), and for each method under [[#worklet-setter]] (from {{SharedStorageWorkletGlobalScope}}), |environment| is the [=environment settings object=] associated with the {{Window}} that created the worklet, and |origin| is the worklet's [=global scopes=][0]'s [=global object/realm=]'s [=realm/settings object=]'s [=environment settings object/origin=]. + - For running operations on a worklet (from a {{Window}}), |environment| is the [=environment settings object=] associated with the {{Window}} that created the worklet, and |origin| is the worklet's [=global scopes=][0]'s [=global object/realm=]'s [=realm/settings object=]'s [=environment settings object/origin=]. + - For [[#setter]], |environment| is either the current context (when called from a {{Window}}) or the [=environment settings object=] associated with the {{Window}} that created the worklet (when called from a {{SharedStorageWorkletGlobalScope}}), and |origin| is |environment|'s [=environment settings object/origin=]. - For [[#ss-fetch-algo]], |environment| is the request's [=request/window=], and |origin| is the request's [=request/current URL=]'s [=url/origin=]. - - For [[#ss-fetch-algo]], for {{WindowSharedStorage/createWorklet()}} called with a cross-origin worklet script using the dataOrigin option with value `"script-origin"` (which would result in a worklet where [=SharedStorageWorklet/has cross-origin data origin=] is true), and for {{SharedStorageWorklet/selectURL()}} and {{SharedStorageWorklet/run()}} that operate on a worklet where [=SharedStorageWorklet/has cross-origin data origin=] is true, |allowedInOpaqueOriginContext| is true. For other methods, |allowedInOpaqueOriginContext| is false. + - For [[#ss-fetch-algo]], for {{SharedStorage/createWorklet()}} called with a cross-origin worklet script using the dataOrigin option with value `"script-origin"` (which would result in a worklet where [=SharedStorageWorklet/has cross-origin data origin=] is true), and for {{SharedStorageWorklet/selectURL()}} and {{SharedStorageWorklet/run()}} that operate on a worklet where [=SharedStorageWorklet/has cross-origin data origin=] is true, |allowedInOpaqueOriginContext| is true. For other methods, |allowedInOpaqueOriginContext| is false.
@@ -345,7 +345,7 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes= 1. If the result of running [=Is feature enabled in document for origin?=] on "[=PermissionsPolicy/shared-storage-select-url=]", |document|, and |workletDataOrigin| returns false, return a [=promise rejected=] with a {{TypeError}}. 1. If [=this=]'s [=global scopes=] is [=list/empty=], then return a [=promise rejected=] with a {{TypeError}}. - Note: This can happen if either {{WindowSharedStorage/selectURL()}} or {{SharedStorageWorklet/selectURL()}} is called before {{addModule()}}. + Note: This can happen if either {{SharedStorage/selectURL()}} or {{SharedStorageWorklet/selectURL()}} is called before {{addModule()}}. 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for |globalScope| is false, return a [=promise rejected=] with a {{TypeError}}. 1. If |urls| is empty or if |urls|'s [=list/size=] is greater than 8, return a [=promise rejected=] with a {{TypeError}}. @@ -478,7 +478,7 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes=

The \`Shared-Storage-Cross-Origin-Worklet-Allowed\` HTTP response header

- The \`Shared-Storage-Cross-Origin-Worklet-Allowed\` HTTP response header, along with the traditional CORS headers, can be used to grant a cross-origin site the permission to create a worklet from the module script's [=/URL=]'s [=url/origin=], and to run subsequent operations on the worklet using the module script's [=/URL=]'s [=url/origin=] as the data partition origin for accessing shared storage data, i.e. the [=environment settings object/origin=] set in [[#set-up-a-worklet-environment-settings-object-monkey-patch]], which becomes the [=url/origin=] used in all {{WorkletSharedStorage}} calls to [=obtain a shared storage bottle map=]. + The \`Shared-Storage-Cross-Origin-Worklet-Allowed\` HTTP response header, along with the traditional CORS headers, can be used to grant a cross-origin site the permission to create a worklet from the module script's [=/URL=]'s [=url/origin=], and to run subsequent operations on the worklet using the module script's [=/URL=]'s [=url/origin=] as the data partition origin for accessing shared storage data, i.e. the [=environment settings object/origin=] set in [[#set-up-a-worklet-environment-settings-object-monkey-patch]], which becomes the [=url/origin=] used in all {{SharedStorage}} calls to [=obtain a shared storage bottle map=]. Worklets that load cross-origin scripts rely on CORS as a baseline permission mechanism to indicate trusted external origins. However, CORS alone is insufficient for creation of a worklet with cross-origin script whose [=data partition origin=] is the script origin. Unlike simple resource sharing, worklets allow the creator site to execute JavaScript within the context of the target origin. To ensure security, an additional response header, \`Shared-Storage-Cross-Origin-Worklet-Allowed\`, is required from the script origin. @@ -548,7 +548,7 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes= undefined register(DOMString name, Function operationCtor); - readonly attribute WorkletSharedStorage sharedStorage; + readonly attribute SharedStorage sharedStorage; }; @@ -558,7 +558,7 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes= Each {{SharedStorageWorkletGlobalScope}} also has an associated operation map, which is a [=map=], initially empty, of [=strings=] (denoting operation names) to [=functions=]. - Each {{SharedStorageWorkletGlobalScope}} also has an associated {{WorkletSharedStorage}} instance, with the [=SharedStorageWorkletGlobalScope/sharedStorage getter=] algorithm as described below. + Each {{SharedStorageWorkletGlobalScope}} also has an associated {{SharedStorage}} instance, with the [=SharedStorageWorkletGlobalScope/sharedStorage getter=] algorithm as described below. ## {{SharedStorageWorkletGlobalScope}} algorithms ## {#scope-algo}
@@ -976,15 +976,34 @@ The Shared Storage API will integrate into the [=Storage Model|Storage API=] as 1. Otherwise, return false.
+ +Extension to the {{Window}} interface {#window-extension} +===================================================== +Each {{Window}} object has an associated {{SharedStorage}} instance {{Window/sharedStorage}}, which is created alongside the .{{Window}} if [=Shared Storage=] is enabled, with the [=Window/sharedStorage getter|getter=] below. + + + partial interface Window { + [SecureContext] readonly attribute SharedStorage? sharedStorage; + }; + + +
+ The {{Window/sharedStorage}} getter steps are: + + 1. If [=this=] is [=fully active=], return [=this=]'s {{Window/sharedStorage}}. + 1. Otherwise, return null. +
+ + The {{SharedStorage}} Interface {#shared-storage-interface} ========================================================== -The {{SharedStorage}} interface is the base for derived interfaces {{WindowSharedStorage}} and {{WorkletSharedStorage}}, which are exposed to the {{Window}} and the {{SharedStorageWorklet}}, respectively. +The {{SharedStorage}} interface is exposed to {{Window}} and {{SharedStorageWorklet}}. -Methods that allow the setting and/or deleting of data are exposed to both the {{Window}} and the {{SharedStorageWorklet}} and hence are declared in the base {{SharedStorage}} interface, although their implementations may vary depending on their [=environment=]. This makes it possible to modify the data in Shared Storage from multiple contexts. +Methods that allow the setting and/or deleting of data are exposed to both the {{Window}} and the {{SharedStorageWorklet}}, although their implementations may vary depending on their [=environment=]. This makes it possible to modify the data in Shared Storage from multiple contexts. -Meanwhile, methods for posting operations to run inside {{SharedStorageWorkletGlobalScope}} (i.e. {{SharedStorageWorklet/selectURL()}} and {{SharedStorageWorklet/run()}}), along with the {{WindowSharedStorage/worklet}} attribute which is used to call {{Worklet/addModule()}}, are declared in {{WindowSharedStorage}} and exposed to the {{Window}} only, as these are the means by which the {{Window}} interacts with the {{SharedStorageWorklet}}. +Meanwhile, methods for posting operations to run inside {{SharedStorageWorkletGlobalScope}} (i.e. {{SharedStorageWorklet/selectURL()}} and {{SharedStorageWorklet/run()}}), along with the {{SharedStorage/worklet}} attribute which is used to call {{Worklet/addModule()}}, are exposed to the {{Window}} only, as these are the means by which the {{Window}} interacts with the {{SharedStorageWorklet}}. -On the other hand, methods for getting data from the [=shared storage database=] are declared in {{WorkletSharedStorage}} and exposed to the {{SharedStorageWorklet}} only, in order to carefully control the flow of data read from the [=shared storage database|database=]. +On the other hand, methods for getting data from the [=shared storage database=] are exposed to the {{SharedStorageWorklet}} only, in order to carefully control the flow of data read from the [=shared storage database|database=]. [Exposed=(Window,SharedStorageWorklet)] @@ -996,29 +1015,37 @@ On the other hand, methods for getting data from the [=shared storage database=] DOMString value); Promise<any> delete(DOMString key); Promise<any> clear(); - }; - - dictionary SharedStorageSetMethodOptions { - boolean ignoreIfPresent = false; - }; - - - ## The {{WindowSharedStorage}} interface ## {#window} - The {{WindowSharedStorage}} interface is as follows. - - - [Exposed=(Window)] - interface WindowSharedStorage : SharedStorage { + [Exposed=Window] Promise<SharedStorageResponse> selectURL(DOMString name, sequence<SharedStorageUrlWithMetadata> urls, optional SharedStorageRunOperationMethodOptions options = {}); + + [Exposed=Window] Promise<any> run(DOMString name, optional SharedStorageRunOperationMethodOptions options = {}); + [Exposed=Window] Promise<SharedStorageWorklet> createWorklet(USVString moduleURL, optional SharedStorageWorkletOptions options = {}); + [Exposed=Window] readonly attribute SharedStorageWorklet worklet; + + [Exposed=SharedStorageWorklet] + Promise<DOMString> get(DOMString key); + + [Exposed=SharedStorageWorklet] + Promise<unsigned long> length(); + + [Exposed=SharedStorageWorklet] + Promise<double> remainingBudget(); + + [Exposed=SharedStorageWorklet] + async iterable<DOMString, DOMString>; + }; + + dictionary SharedStorageSetMethodOptions { + boolean ignoreIfPresent = false; }; dictionary SharedStorageRunOperationMethodOptions { @@ -1032,133 +1059,26 @@ On the other hand, methods for getting data from the [=shared storage database=] }; - ### Window Setter/Deleter Methods ### {#window-setter} - -
- The set(|key|, |value|, |options|) method step is: - 1. Return the result of running [=WindowSharedStorage/set a key-value pair=] on {{WindowSharedStorage}}, |key|, |value|, and |options|. -
- -
- The append(|key|, |value|) method step is: - 1. Return the result of running [=WindowSharedStorage/append a key-value pair=] on {{WindowSharedStorage}}, |key|, and |value|. -
- -
- The delete(|key|) method step is: - 1. Return the result of running [=WindowSharedStorage/delete a key=] on {{WindowSharedStorage}} and |key|. -
+## Run Operation Methods on {{SharedStorage}} ## {#run-op-shared-storage}
- The clear() method step is: - 1. Return the result of running [=WindowSharedStorage/clear all keys=] on {{WindowSharedStorage}}. -
- -
- To set a key-value pair, given {{WindowSharedStorage}} |sharedStorage|, [=string=] |key|, [=string=] |value|, and {{SharedStorageSetMethodOptions}} |options|, perform the following steps: - - 1. Let |promise| be a new [=promise=]. - 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. If |value|'s [=string/length=] exceeds the [=value/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be |sharedStorage|'s {{Window}}'s [=Window/browsing context=]. - 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=]. - 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. - 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. - 1. Let |realm| be the [=current realm=]. - 1. [=Enqueue the following steps=] on |queue|: - 1. If |options|["`ignoreIfPresent`"] is true and the result of running [=shared storage database/retrieve an entry from the database=] with |queue|, |databaseMap|, |environment|, and |key| is not undefined: - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. - 1. Abort these steps. - 1. Run [=shared storage database/store an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value|. - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. - 1. Return |promise|. -
- -
- To append a key-value pair, given {{WindowSharedStorage}} |sharedStorage|, [=string=] |key|, and [=string=] |value|, perform the following steps: - - 1. Let |promise| be a new [=promise=]. - 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. If |value|'s [=string/length=] exceeds the [=value/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be |sharedStorage|'s {{Window}}'s [=Window/browsing context=]. - 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=]. - 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. - 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. - 1. Let |realm| be the [=current realm=]. - 1. [=Enqueue the following steps=] on |queue|: - 1. Let |currentValue| be the result of running [=shared storage database/retrieve an entry from the database=] with |queue|, |databaseMap|, |environment|, and |key|. - 1. If |currentValue| is failure: - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. - 1. Abort these steps. - 1. If |currentValue| is not undefined: - 1. Let |list| be a new [=/list=]. - 1. [=list/Append=] |currentValue| to |list|. - 1. [=list/Append=] |value| to |list|. - 1. Set |value| to the result of running [=string/concatenate=] on |list|. - 1. Run [=shared storage database/store an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value|. - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. - 1. Return |promise|. -
- -
- To delete a key, given {{WindowSharedStorage}} |sharedStorage| and [=string=] |key|, perform the following steps: - - 1. Let |promise| be a new [=promise=]. - 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be |sharedStorage|'s {{Window}}'s [=Window/browsing context=]. - 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=]. - 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. - 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. - 1. Let |realm| be the [=current realm=]. - 1. [=Enqueue the following steps=] on |queue|: - 1. Run [=shared storage database/delete an entry from the database=] with |queue|, |environment|, and |key|. - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. - 1. Return |promise|. -
- -
- To clear all keys, given {{WindowSharedStorage}} |sharedStorage|, perform the following steps: - - 1. Let |promise| be a new [=promise=]. - 1. Let |context| be |sharedStorage|'s {{Window}}'s [=Window/browsing context=]. - 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=] - 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. - 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. - 1. Let |realm| be the [=current realm=]. - 1. [=Enqueue the following steps=] on |queue|: - 1. Run [=shared storage database/clear all entries in the database=] with |queue| and |environment|. - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. - 1. Return |promise|. -
- - ### Run Operation Methods on {{WindowSharedStorage}} ### {#run-op-shared-storage} - -
- The selectURL(|name|, |urls|, |options|) method steps are: + The selectURL(|name|, |urls|, |options|) method steps are: 1. Let |sharedStorage| be [=this=]. - 1. Return |sharedStorage|.{{WindowSharedStorage/worklet}}.{{SharedStorageWorklet/selectURL()|selectURL}}(|name|, |urls|, |options|). + 1. Return |sharedStorage|.{{SharedStorage/worklet}}.{{SharedStorageWorklet/selectURL()|selectURL}}(|name|, |urls|, |options|).
- The run(|name|, |options|) method steps are: + The run(|name|, |options|) method steps are: 1. Let |sharedStorage| be [=this=]. - 1. Return |sharedStorage|.{{WindowSharedStorage/worklet}}.{{SharedStorageWorklet/run()|run}}(|name|, |options|). + 1. Return |sharedStorage|.{{SharedStorage/worklet}}.{{SharedStorageWorklet/run()|run}}(|name|, |options|).
- ### Create a new worklet via {{WindowSharedStorage}} ### {#create-a-new-worklet-via-shared-storage} +## Create a new worklet via {{SharedStorage}} ## {#create-a-new-worklet-via-shared-storage}
- The createWorklet(|moduleURL|, |options|) method steps are: + The createWorklet(|moduleURL|, |options|) method steps are: 1. Let |sharedStorageWorklet| be a new {{SharedStorageWorklet}}. 1. If |options| [=map/contains=] |dataOrigin|, set |sharedStorageWorklet|'s [=SharedStorageWorklet/data origin=] to |options|[|dataOrigin|]. @@ -1169,147 +1089,150 @@ On the other hand, methods for getting data from the [=shared storage database=] 1. Return |resultPromise|.
- ## Extension to the {{Window}} interface ## {#extension} - - Each {{Window}} object has an associated {{WindowSharedStorage}} instance {{Window/sharedStorage}}, which is created alongside the .{{Window}} if [=Shared Storage=] is enabled, with the [=Window/sharedStorage getter|getter=] below. - - - partial interface Window { - [SecureContext] readonly attribute WindowSharedStorage? sharedStorage; - }; - - -
- The {{Window/sharedStorage}} getter steps are: - - 1. If [=this=] is [=fully active=], return [=this=]'s {{Window/sharedStorage}}. - 1. Otherwise, return null. -
- - ## The {{WorkletSharedStorage}} interface ## {#worklet-shared-storage} - - The {{WorkletSharedStorage}} interface is as follows. - - - [Exposed=(SharedStorageWorklet)] - interface WorkletSharedStorage : SharedStorage { - Promise<DOMString> get(DOMString key); - Promise<unsigned long> length(); - Promise<double> remainingBudget(); - - async iterable<DOMString, DOMString>; - }; - - - ### Worklet Setter/Deleter Methods ### {#worklet-setter} +## Setter/Deleter Methods ## {#setter}
- The set(|key|, |value|, |options|) method steps are: + The set(|key|, |value|, |options|) method steps are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. - 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. If |value|'s [=string/length=] exceeds the [=value/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. Let |globalObject| be the [=current realm=]'s [=global object=]. + 1. Let |context| be null. + 1. If |globalObject| is a {{Window}}: + 1. Set |context| to |globalObject|'s [=Window/browsing context=]. + 1. Else: + 1. Set |context| to |globalObject|'s [=outside settings=]'s [=target browsing context=]. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. + 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. + 1. If |value|'s [=string/length=] exceeds the [=value/maximum length=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |realm| be the [=current realm=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |realm|'s [=realm/settings object=]'s [=environment settings object/origin=]. + 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=]. 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. + 1. Let |realm| be the [=current realm=]. 1. [=Enqueue the following steps=] on |queue|: 1. If |options|["`ignoreIfPresent`"] is true: 1. Let |currentValue| be the result of running [=shared storage database/retrieve an entry from the database=] with |queue|, |databaseMap|, |environment|, and |key|. - 1. If |currentValue| is failure: + 1. If |currentValue| is failure and if |globalObject| is a {{SharedStorageWorkletGlobalScope}}: 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. 1. Abort these steps. 1. If |currentValue| is not undefined: 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. 1. Abort these steps. - 1. If the result of running [=shared storage database/store an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value| is false, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. - 1. Otherwise, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. + 1. Let |result| be the result of running [=shared storage database/store an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value|. + 1. If |result| is false and if |globalObject| is a {{SharedStorageWorkletGlobalScope}}: + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. + 1. Abort these steps. + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. 1. Return |promise|.
- The append(|key|, |value|) method steps are: + The append(|key|, |value|) method steps are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. - 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. If |value|'s [=string/length=] exceeds the [=value/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. Let |globalObject| be the [=current realm=]'s [=global object=]. + 1. Let |context| be null. + 1. If |globalObject| is a {{Window}}: + 1. Set |context| to |globalObject|'s [=Window/browsing context=]. + 1. Else: + 1. Set |context| to |globalObject|'s [=outside settings=]'s [=target browsing context=]. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. + 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. + 1. If |value|'s [=string/length=] exceeds the [=value/maximum length=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |realm| be the [=current realm=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |realm|'s [=realm/settings object=]'s [=environment settings object/origin=]. + 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=]. 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. + 1. Let |realm| be the [=current realm=]. 1. [=Enqueue the following steps=] on |queue|: 1. Let |currentValue| be the result of running [=shared storage database/retrieve an entry from the database=] with |queue|, |databaseMap|, |environment|, and |key|. 1. If |currentValue| is failure: - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. + 1. If |globalObject| is a {{Window}}: + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. + 1. Else: + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. 1. Abort these steps. 1. If |currentValue| is not undefined: 1. Let |list| be a new [=/list=]. 1. [=list/Append=] |currentValue| to |list|. 1. [=list/Append=] |value| to |list|. 1. Set |value| to the result of running [=string/concatenate=] on |list|. - 1. If the result of running [=shared storage database/store an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value| is false, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. - 1. Otherwise, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. + 1. Let |result| be the result of running [=shared storage database/store an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value|. + 1. If |result| is false and if |globalObject| is a {{SharedStorageWorkletGlobalScope}}: + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. + 1. Abort these steps. + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. 1. Return |promise|.
- The delete(|key|) method steps are: + The delete(|key|) method steps are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. - 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. Let |globalObject| be the [=current realm=]'s [=global object=]. + 1. Let |context| be null. + 1. If |globalObject| is a {{Window}}: + 1. Set |context| to |globalObject|'s [=Window/browsing context=]. + 1. Else: + 1. Set |context| to |globalObject|'s [=outside settings=]'s [=target browsing context=]. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. + 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |realm| be the [=current realm=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |realm|'s [=realm/settings object=]'s [=environment settings object/origin=]. + 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=]. 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. + 1. Let |realm| be the [=current realm=]. 1. [=Enqueue the following steps=] on |queue|: - 1. If the result of running [=shared storage database/delete an entry from the database=] with |queue|, |environment|, and |key| is false, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. - 1. Otherwise, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. + 1. Let |result| be the result of running [=shared storage database/delete an entry from the database=] with |queue|, |databaseMap|, and |key|. + 1. If |result| is false and if |globalObject| is a {{SharedStorageWorkletGlobalScope}}: + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. + 1. Abort these steps. + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. 1. Return |promise|.
- The clear() method steps are: + The clear() method steps are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. Let |globalObject| be the [=current realm=]'s [=global object=]. + 1. Let |context| be null. + 1. If |globalObject| is a {{Window}}: + 1. Set |context| to |globalObject|'s [=Window/browsing context=]. + 1. Else: + 1. Set |context| to |globalObject|'s [=outside settings=]'s [=target browsing context=]. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. - 1. Let |realm| be the [=current realm=]. - 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |realm|'s [=realm/settings object=]'s [=environment settings object/origin=]. + 1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=]. 1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}. 1. Let |queue| be |context|'s associated [=shared storage database|database=]'s [=shared storage database/shared storage database queue=]. + 1. Let |realm| be the [=current realm=]. 1. [=Enqueue the following steps=] on |queue|: - 1. If the result of running [=shared storage database/clear all entries in the database=] with |queue| and |environment| is false, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. - 1. Otherwise, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. + 1. Let |result| be the result of running [=shared storage database/clear all entries in the database=] with |queue| and |databaseMap|. + 1. If |result| is false and if |globalObject| is a {{SharedStorageWorkletGlobalScope}}: + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}. + 1. Abort these steps. + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined. 1. Return |promise|.
- ### Getter Methods ### {#getter} +## Getter Methods ## {#getter}
- The get(|key|) method steps are: + The get(|key|) method steps are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. 1. If |key|'s [=string/length=] exceeds the [=key/maximum length=], return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. Let |context| be {{SharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. @@ -1326,11 +1249,11 @@ On the other hand, methods for getting data from the [=shared storage database=]
- The length() method steps are: + The length() method steps are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. + 1. Let |context| be {{SharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. @@ -1346,11 +1269,11 @@ On the other hand, methods for getting data from the [=shared storage database=]
- The remainingBudget() method steps are: + The remainingBudget() method steps are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. + 1. Let |context| be {{SharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. @@ -1367,20 +1290,20 @@ On the other hand, methods for getting data from the [=shared storage database=] 1. Return |promise|.
- ### Iteration ### {#iteration} +## Iteration ## {#iteration} - Each {{WorkletSharedStorage}} [=async iterator=] instance has a [=queue=] pending entries of [=shared storage database/entry|entries=], initially [=list/empty=]. +Each {{SharedStorage}} [=async iterator=] instance has a [=queue=] pending entries of [=shared storage database/entry|entries=], initially [=list/empty=]. - Each {{WorkletSharedStorage}} [=async iterator=] instance also has a {{boolean}} error, initially false. +Each {{SharedStorage}} [=async iterator=] instance also has a {{boolean}} error, initially false. - The [=WorkletSharedStorageIterator/asynchronous iterator initialization steps=] and [=WorkletSharedStorageIterator/get the next iteration result=] algorithms defined below correspond to those referred to as the [=/asynchronous iterator initialization steps=] and [=/get the next iteration result=] algorithms in the [=Web IDL Standard=]. +The [=SharedStorageIterator/asynchronous iterator initialization steps=] and [=SharedStorageIterator/get the next iteration result=] algorithms defined below correspond to those referred to as the [=/asynchronous iterator initialization steps=] and [=/get the next iteration result=] algorithms in the [=Web IDL Standard=].
- The asynchronous iterator initialization steps for a {{WorkletSharedStorage}} [=async iterator=] |iterator| are: + The asynchronous iterator initialization steps for a {{SharedStorage}} [=async iterator=] |iterator| are: 1. Let |promise| be a new [=promise=]. - 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{WorkletSharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. - 1. Let |context| be {{WorkletSharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. + 1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}. + 1. Let |context| be {{SharedStorage}}'s {{SharedStorageWorkletGlobalScope}}'s [=outside settings=]'s [=target browsing context=]. 1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}. 1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}. 1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=]. @@ -1394,21 +1317,21 @@ On the other hand, methods for getting data from the [=shared storage database=] 1. Otherwise, [=queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with |entries|. 1. [=Upon fulfillment=] of |promise|, run the following: 1. Let |promiseEntries| be the value of |promise|. - 1. [=map/iterate|For each=] [=shared storage database/entry=] |entry| in |promiseEntries|, [=queue/enqueue=] |entry| in |iterator|'s [=WorkletSharedStorageIterator/pending entries=]. - 1. [=Upon rejection=] of |promise|, set |iterator|'s [=WorkletSharedStorageIterator/error=] to true. + 1. [=map/iterate|For each=] [=shared storage database/entry=] |entry| in |promiseEntries|, [=queue/enqueue=] |entry| in |iterator|'s [=SharedStorageIterator/pending entries=]. + 1. [=Upon rejection=] of |promise|, set |iterator|'s [=SharedStorageIterator/error=] to true.
- Toget the next iteration result, given a {{WorkletSharedStorage}}'s [=async iterator=] |iterator|, run the following steps: + Toget the next iteration result, given a {{SharedStorage}}'s [=async iterator=] |iterator|, run the following steps: 1. Let |promise| be a new [=promise=]. 1. [=Enqueue the following steps=]: - 1. If |iterator|'s [=WorkletSharedStorageIterator/error=] is true, return a [=promise rejected=] with a {{TypeError}}. - 1. If |iterator|'s [=WorkletSharedStorageIterator/pending entries=] is [=list/empty=]: + 1. If |iterator|'s [=SharedStorageIterator/error=] is true, return a [=promise rejected=] with a {{TypeError}}. + 1. If |iterator|'s [=SharedStorageIterator/pending entries=] is [=list/empty=]: 1. Create an object |doneObject|. 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with |doneObject|. 1. Abort these steps. - 1. Otherwise, let |entry| be the result of [=queue/dequeue|dequeueing=] from |iterator|'s [=WorkletSharedStorageIterator/pending entries=]. + 1. Otherwise, let |entry| be the result of [=queue/dequeue|dequeueing=] from |iterator|'s [=SharedStorageIterator/pending entries=]. 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with |entry|. 1. Return |promise|.
@@ -1416,7 +1339,7 @@ On the other hand, methods for getting data from the [=shared storage database=] Triggering Operations Via HTTP Response Header {#http} ====================================================== -While setter and deleter operations (e.g.. {{WindowSharedStorage/set()}}, {{WindowSharedStorage/append()}}, {{WindowSharedStorage/delete()}}, {{WindowSharedStorage/clear()}}) can be initiated via the above APIs for {{Window}} or {{SharedStorageWorkletGlobalScope}}, setter/deleter operations can alternatively be triggered via HTTP [=/response=] [=header=]. +While setter and deleter operations (e.g.. {{SharedStorage/set()}}, {{SharedStorage/append()}}, {{SharedStorage/delete()}}, {{SharedStorage/clear()}}) can be initiated via the above APIs for {{Window}} or {{SharedStorageWorkletGlobalScope}}, setter/deleter operations can alternatively be triggered via HTTP [=/response=] [=header=]. This will require monkey patches to the HTML and Fetch specifications. @@ -1621,19 +1544,19 @@ The IDL attribute {{HTMLSharedStorageWritableElementUtils/sharedStorageWritable}
If |operationString| is "`clear`":
Perform the following steps: - 1. Run [=WindowSharedStorage/clear all keys=] on |sharedStorage|. + 1. Run run |sharedStorage|.{{SharedStorage/clear()|clear}}(). 1. Continue.
If |operationString| is "`delete`":
Perform the following steps: 1. Let |key| be the result of running [=obtain a string-like parameter value=] with |parameters| and "`key`". - 1. If |key| is not null, run [=WindowSharedStorage/delete a key=] on |sharedStorage| with |key|. + 1. If |key| is not null, run |sharedStorage|.{{SharedStorage/delete()|delete}}(|key|). 1. Continue.
If |operationString| is "`append`":
Perform the following steps: 1. Let |key| be the result of running [=obtain a string-like parameter value=] with |parameters| and "`key`". 1. If |key| is null, continue. 1. Let |value| be the result of running [=obtain a string-like parameter value=] with |parameters| and "`value`". - 1. If |value| is not null, run [=WindowSharedStorage/append a key-value pair=] on |sharedStorage| with |key| and |value|. + 1. If |value| is not null, run |sharedStorage|.{{SharedStorage/append()|append}}(|key|, |value|). 1. Continue.
If |operationString| is "`set`":
Perform the following steps: @@ -1642,8 +1565,8 @@ The IDL attribute {{HTMLSharedStorageWritableElementUtils/sharedStorageWritable} 1. Let |value| be the result of running [=obtain a string-like parameter value=] with |parameters| and "`value`". 1. If |value| is null, continue. 1. Let |options| be a new {{SharedStorageSetMethodOptions}}. - 1. If the result of running [=obtain a boolean parameter value=] with |parameters| and "`ignore_if_present`" is true, [=map/set=] |options|["`ignoreIfPresent`"] to true.. - 1. Run [=WindowSharedStorage/set a key-value pair=] on |sharedStorage| with |key|, |value|, and |options|. + 1. If the result of running [=obtain a boolean parameter value=] with |parameters| and "`ignore_if_present`" is true, [=map/set=] |options|["`ignoreIfPresent`"] to true. + 1. Run |sharedStorage|.{{SharedStorage/set()|set}}(|key|, |value|, |options|). 1. Continue.
If |operationString| is anything else:
Continue. From b37bf844a38ec98a3d4642083b2bd08d078e692e Mon Sep 17 00:00:00 2001 From: Jeremy Roman Date: Fri, 9 Aug 2024 16:12:13 -0400 Subject: [PATCH 2/4] Adjust callback function invocation. Unforunately this isn't purely editorial, because in the process of adjusting the use of "invoke" a number of other things needed to be clarified. Namely: * the operation map now holds JS function objects (i.e., anything with [[Call]]) * these function objects are converted to a specific IDL types only when they are about to be invoked * the select URL algorithm reacts to the promise rather than expecting its value (or rejection reason) to be immediately available Part of whatwg/webidl#1425. --- spec.bs | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/spec.bs b/spec.bs index fa25dc9..869cf2c 100644 --- a/spec.bs +++ b/spec.bs @@ -71,7 +71,6 @@ spec: webidl; urlPrefix: https://webidl.spec.whatwg.org text: async iterator; url: idl-async-iterable text: promise; url: idl-promise text: promise rejected; url: a-promise-rejected-with - text: convert; for: ecmascript-to-idl; url: dfn-convert-ecmascript-to-idl-value spec: storage; urlPrefix: https://storage.spec.whatwg.org/ type: dfn text: storage model; url: model @@ -313,20 +312,26 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes= Note: This could happen if {{SharedStorageWorkletGlobalScope/register()}} was never called with |operationName|. - 1. Let |operation| be |operationMap|[|operationName|]. - 1. [=Assert=]: |operation|'s [=associated realm=] is [=this=]'s [=relevant realm=]. + 1. [=Assert=]: |operationMap|[|operationName|]'s [=associated realm=] is [=this=]'s [=relevant realm=]. + 1. Let |operation| be |operationMap|[|operationName|], [=converted to an IDL value|converted=] to {{RunFunctionForSharedStorageSelectURLOperation}}. 1. Let |argumentsList| be the [=/list=] « |urlList| ». - 1. If |options| [=map/contains=] |data|, [=list/append=] |data| to |argumentsList|. - 1. Let |index| be the result of [=invoking=] |operation| with |argumentsList|. - 1. If [=an exception was thrown=], then [=queue a global task=] on the [=DOM manipulation task source=], given |window|, to [=reject=] |promise| with a {{TypeError}}, and abort these steps. + 1. If |options|["{{SharedStorageRunOperationMethodOptions/data}}"] [=map/exists=], [=list/append=] it to |argumentsList|. + 1. Let |indexPromise| be the result of [=invoking=] |operation| with |argumentsList|. + 1. [=promise/React=] to |indexPromise|: - Note: This indicates that either |operationCtor|'s run() method encounters an error (where |operationCtor| is the parameter in {{SharedStorageWorkletGlobalScope/register()}}), or the result |index| is a non-integer value, which violates the selectURL() protocol, and we don't know which url should be selected. +
+ : If it was fulfilled with value |index|: + :: 1. If |index| is greater than |urlList|'s [=list/size=], then [=queue a global task=] on the [=DOM manipulation task source=], given |window|, to [=reject=] |promise| with a {{TypeError}}, and abort these steps. - 1. If |index| is greater than |urlList|'s [=list/size=], then [=queue a global task=] on the [=DOM manipulation task source=], given |window|, to [=reject=] |promise| with a {{TypeError}}, and abort these steps. + Note: The result index is beyond the input urls' size. This violates the selectURL() protocol, and we don't know which url should be selected. - Note: The result index is beyond the input urls' size. This violates the selectURL() protocol, and we don't know which url should be selected. + 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |window|, to [=resolve=] |promise| with |index|. - 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |window|, to [=resolve=] |promise| with |index|. + : If it was rejected: + :: 1. [=Queue a global task=] on the [=DOM manipulation task source=], given |window|, to [=reject=] |promise| with a {{TypeError}}. + + Note: This indicates that either |operationCtor|'s run() method encounters an error (where |operationCtor| is the parameter in {{SharedStorageWorkletGlobalScope/register()}}), or the result |index| is a non-integer value, which violates the selectURL() protocol, and we don't know which url should be selected. +
@@ -420,13 +425,11 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes= 1. If [=this=]'s [=module map=] is not [=map/empty=]: 1. Let |operationMap| be [=this=]'s {{SharedStorageWorkletGlobalScope}}'s [=SharedStorageWorkletGlobalScope/operation map=]. 1. If |operationMap| [=map/contains=] |name|: - 1. Let |operation| be |operationMap|[|name|]. - 1. [=Assert=]: |operation|'s [=associated realm=] is [=this=]'s [=relevant realm=]. - 1. If |options| [=map/contains=] |data|: - 1. Let |argumentsList| be a new [=/list=]. - 1. [=list/Append=] |data| to |argumentsList|. - 1. [=Invoke=] |operation| with |argumentsList|. - 1. Otherwise, [=invoke=] |operation| without any arguments list. + 1. [=Assert=]: |operationMap|[|name|]'s [=associated realm=] is [=this=]'s [=relevant realm=]. + 1. Let |operation| be |operationMap|[|name|], [=converted to an IDL value|converted=] to {{Function}}. + 1. Let |argumentsList| be a new [=/list=]. + 1. If |options|["{{SharedStorageRunOperationMethodOptions/data}}"] [=map/exists=], [=list/append=] it to |argumentsList|. + 1. [=Invoke=] |operation| with |argumentsList| and "`report`". 1. If |options|["`keepAlive`"] is false: 1. Wait for |operation| to finish running, if applicable. 1. Run [=terminate a worklet global scope=] with [=this=]. @@ -556,7 +559,7 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes= Each {{SharedStorageWorkletGlobalScope}} has an associated [=/boolean=] addModule success, which is initialized to false. - Each {{SharedStorageWorkletGlobalScope}} also has an associated operation map, which is a [=map=], initially empty, of [=strings=] (denoting operation names) to [=functions=]. + Each {{SharedStorageWorkletGlobalScope}} also has an associated operation map, which is a [=map=], initially empty, of [=strings=] (denoting operation names) to [=function objects=]. Each {{SharedStorageWorkletGlobalScope}} also has an associated {{SharedStorage}} instance, with the [=SharedStorageWorkletGlobalScope/sharedStorage getter=] algorithm as described below. @@ -570,8 +573,8 @@ Moreover, each {{SharedStorageWorklet}}'s [=global scopes|list of global scopes= 1. If |operationCtor| is missing, throw a {{TypeError}}. 1. Let |operationClassInstance| be the result of [=constructing=] |operationCtor|, with no arguments. 1. Let |runFunction| be [=Get=](|operationClassInstance|, "`run`"). Rethrow any exceptions. - 1. Let |runIDLFunction| be the result of [=ecmascript-to-idl/converting=] |runFunction| to a Web IDL {{RunFunctionForSharedStorageSelectURLOperation}} instance. - 1. [=map/Set=] the value of |operationMap|[|name|] to |runIDLFunction|. + 1. If IsCallable(|runFunction|) is false, throw a {{TypeError}}. + 1. [=map/Set=] the value of |operationMap|[|name|] to |runFunction|.
Issue(151): The "name" and "operationCtor" cannot be missing here given WebIDL. Should just check for default/empty values. From 174f7fc34f1163898491e91fc8dcc0005ae6424c Mon Sep 17 00:00:00 2001 From: Yao Xiao Date: Tue, 20 Aug 2024 15:15:10 -0400 Subject: [PATCH 3/4] Fix typo --- spec.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.bs b/spec.bs index 869cf2c..b815fa2 100644 --- a/spec.bs +++ b/spec.bs @@ -1547,7 +1547,7 @@ The IDL attribute {{HTMLSharedStorageWritableElementUtils/sharedStorageWritable}
If |operationString| is "`clear`":
Perform the following steps: - 1. Run run |sharedStorage|.{{SharedStorage/clear()|clear}}(). + 1. Run |sharedStorage|.{{SharedStorage/clear()|clear}}(). 1. Continue.
If |operationString| is "`delete`":
Perform the following steps: From 53d753ba88743cf54d2b57b8fd823a8bb89e3ab1 Mon Sep 17 00:00:00 2001 From: Yao Xiao Date: Tue, 20 Aug 2024 20:32:21 -0400 Subject: [PATCH 4/4] Fix typo --- spec.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.bs b/spec.bs index b815fa2..d41400d 100644 --- a/spec.bs +++ b/spec.bs @@ -982,7 +982,7 @@ The Shared Storage API will integrate into the [=Storage Model|Storage API=] as Extension to the {{Window}} interface {#window-extension} ===================================================== -Each {{Window}} object has an associated {{SharedStorage}} instance {{Window/sharedStorage}}, which is created alongside the .{{Window}} if [=Shared Storage=] is enabled, with the [=Window/sharedStorage getter|getter=] below. +Each {{Window}} object has an associated {{SharedStorage}} instance {{Window/sharedStorage}}, which is created alongside the {{Window}} if [=Shared Storage=] is enabled, with the [=Window/sharedStorage getter|getter=] below. partial interface Window {