From 569c3de4be318708eaa81ad74c90a8794ae35ece Mon Sep 17 00:00:00 2001 From: sisidovski Date: Fri, 2 Feb 2024 17:57:42 +0900 Subject: [PATCH 01/19] Add `race-network-and-fetch-handler` option --- docs/index.bs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index 4979e20b..6646ee7d 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1578,7 +1578,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ }; enum RunningStatus { "running", "not-running" }; - enum RouterSourceEnum { "cache", "fetch-event", "network" }; + enum RouterSourceEnum { "cache", "fetch-event", "network", "race-network-and-fetch-handler" };
@@ -3154,6 +3154,23 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |client| is not null, |response|'s [=response/type=] is "`opaque`", and [=cross-origin resource policy check=] with |request|'s [=request/origin=], |client|, "", and |response|'s [=filtered response/internal response=] returns blocked, then return null. 1. Return |response|. 1. Return null. + 1. Else if |source| is {{RouterSourceEnum/"race-network-and-fetch-handler"}}, and |request|'s [=request/method=] is \`GET\` then: + + Note: In order to avoid duplicated fetches to |request|, the user agent may reuse |raceNetworkRequestResponse| as the result of |e|'s [=FetchEvent/potential response=], or the fallback request. + + 1. Let |raceFetchController| be null. + 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": + 1. Set |raceFetchController| to the result of [=Fetch|fetching=] |request|. + + To [=fetch/processResponse=] for |raceNetworkRequestResponse|, run these substeps: + 1. If |response| is not null, or |raceNetworkRequestResponse|'s [=response/type=] is "`error`", then: + 1. terminate these substeps. + 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: + 1. Set |response| to |raceNetworkRequestResponse|. + 1. Return |response|. + 1. [=If aborted=], then: + 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. + 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. 1. If |request| is a non-subresource request, |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`GET\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] fetch, and |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set then: Note: If the above is true except |registration|'s [=active worker=]'s set of event types to handle **does not** contain fetch, then the user agent may wish to show a console warning, as the developer's intent isn't clear. From ad5f0b94adf8faa71bc7cd0085f061047f694f15 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Mon, 5 Feb 2024 17:30:27 +0900 Subject: [PATCH 02/19] Abort the request if the fetch handler respond --- docs/index.bs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 6646ee7d..2691a6d4 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3116,6 +3116,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |client| be |request|'s [=request/client=]. 1. Let |reservedClient| be |request|'s [=request/reserved client=]. 1. Let |preloadResponse| be a new [=promise=]. + 1. Let |raceFetchController| be null. 1. Let |workerRealm| be null. 1. Let |eventHandled| be null. 1. Let |timingInfo| be a new [=service worker timing info=]. @@ -3158,13 +3159,12 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ Note: In order to avoid duplicated fetches to |request|, the user agent may reuse |raceNetworkRequestResponse| as the result of |e|'s [=FetchEvent/potential response=], or the fallback request. - 1. Let |raceFetchController| be null. 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of [=Fetch|fetching=] |request|. To [=fetch/processResponse=] for |raceNetworkRequestResponse|, run these substeps: 1. If |response| is not null, or |raceNetworkRequestResponse|'s [=response/type=] is "`error`", then: - 1. terminate these substeps. + 1. Terminate these substeps. 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: 1. Set |response| to |raceNetworkRequestResponse|. 1. Return |response|. @@ -3235,7 +3235,11 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |response| is null, |request|'s [=request/body=] is not null, and |request|'s [=request/body=]'s [=body/source=] is null, then: 1. If |request|'s [=request/body=] is [=Body/unusable=], set |handleFetchFailed| to true. 1. Else, [=ReadableStream/cancel=] |request|'s [=request/body=] with undefined. - 1. If |response| is not null, then set |response|'s [=response/service worker timing info=] to |timingInfo|. + 1. If |response| is not null, then: + 1. Set |response|'s [=response/service worker timing info=] to |timingInfo|. + 1. If |raceFetchController| is not null, then: + 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. + 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. 1. If |controller| [=fetch controller/state=] is "terminated" or "aborted", then: 1. Let |deserializedError| be a "{{AbortError}}" {{DOMException}}. From 10db402896b67693fea4f0463374b79ea73cf686 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Tue, 6 Feb 2024 09:58:53 +0900 Subject: [PATCH 03/19] Fix nav preload condition, indent, FetchEvent --- docs/index.bs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 2691a6d4..fc50df7f 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3157,7 +3157,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Return null. 1. Else if |source| is {{RouterSourceEnum/"race-network-and-fetch-handler"}}, and |request|'s [=request/method=] is \`GET\` then: - Note: In order to avoid duplicated fetches to |request|, the user agent may reuse |raceNetworkRequestResponse| as the result of |e|'s [=FetchEvent/potential response=], or the fallback request. + Note: In order to avoid duplicated fetches to |request|, the user agent may reuse |raceNetworkRequestResponse| as the result of {{FetchEvent}}'s [=FetchEvent/potential response=], or the fallback request. 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of [=Fetch|fetching=] |request|. @@ -3168,10 +3168,10 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: 1. Set |response| to |raceNetworkRequestResponse|. 1. Return |response|. - 1. [=If aborted=], then: - 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. - 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. - 1. If |request| is a non-subresource request, |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`GET\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] fetch, and |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set then: + 1. [=If aborted=], then: + 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. + 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. + 1. If |request| is a non-subresource request, |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`GET\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] fetch, |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set, and |raceFetchController| is null then: Note: If the above is true except |registration|'s [=active worker=]'s set of event types to handle **does not** contain fetch, then the user agent may wish to show a console warning, as the developer's intent isn't clear. From e6e70bce34915a57962be9260533672164392576 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Tue, 6 Feb 2024 16:08:29 +0900 Subject: [PATCH 04/19] Split Handle Fetch --- docs/index.bs | 60 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index fc50df7f..fcf0b8eb 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3108,17 +3108,12 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ : Output :: |response|, a [=/response=] - 1. Let |handleFetchFailed| be false. - 1. Let |respondWithEntered| be false. - 1. Let |eventCanceled| be false. 1. Let |response| be null. 1. Let |registration| be null. 1. Let |client| be |request|'s [=request/client=]. 1. Let |reservedClient| be |request|'s [=request/reserved client=]. 1. Let |preloadResponse| be a new [=promise=]. - 1. Let |raceFetchController| be null. 1. Let |workerRealm| be null. - 1. Let |eventHandled| be null. 1. Let |timingInfo| be a new [=service worker timing info=]. 1. Assert: |request|'s [=request/destination=] is not "serviceworker". 1. If |request|'s [=request/destination=] is either "embed" or "object", then: @@ -3159,19 +3154,22 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ Note: In order to avoid duplicated fetches to |request|, the user agent may reuse |raceNetworkRequestResponse| as the result of {{FetchEvent}}'s [=FetchEvent/potential response=], or the fallback request. - 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": - 1. Set |raceFetchController| to the result of [=Fetch|fetching=] |request|. - - To [=fetch/processResponse=] for |raceNetworkRequestResponse|, run these substeps: - 1. If |response| is not null, or |raceNetworkRequestResponse|'s [=response/type=] is "`error`", then: - 1. Terminate these substeps. - 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: - 1. Set |response| to |raceNetworkRequestResponse|. - 1. Return |response|. - 1. [=If aborted=], then: - 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. - 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. - 1. If |request| is a non-subresource request, |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`GET\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] fetch, |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set, and |raceFetchController| is null then: + 1. Let |queue| be an empty [=queue=] of [=/response=]. + 1. Run the following substeps [=in parallel=]: + 1. Let |raceFetchController| to the result of [=Fetch|fetching=] |request|. + 1. To [=fetch/processResponse=] for |raceNetworkRequestResponse|, run these substeps: + 1. If |raceNetworkRequestResponse|'s [=response/type=] is "`error`", then: + 1. Terminate these substeps. + 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: + 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. + 1. Run the following substeps [=in parallel=]: + 1. Resolve |preloadResponse| with undefined. + 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. + 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. + 1. Wait until |queue| is not empty. + 1. Set |response| to the result of [=dequeue=] |queue|. + 1. Return |response|. + 1. If |request| is a non-subresource request, |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`GET\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] fetch, and |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set, then: Note: If the above is true except |registration|'s [=active worker=]'s set of event types to handle **does not** contain fetch, then the user agent may wish to show a console warning, as the developer's intent isn't clear. @@ -3193,6 +3191,29 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. 1. [=fetch controller/Abort=] |preloadFetchController| with |deserializedError|. 1. Else, resolve |preloadResponse| with undefined. + 1. Set |response| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. + 1. Retrun |response|. +
+ +
+

Create Fetch Event and Dispatch

+ : Input + :: |request|, a [=/request=] + :: |registration|, a [=/service worker registration=] + :: |useHighResPerformanceTimers|, a boolean + :: |timingInfo|, a [=service worker timing info=]. + :: |workerRealm|, a [=relevant realm=] of the [=service worker/global object=]. + :: |reservedClient|, a [=request/reserved client=]. + :: |preloadResponse| a [=promise=]. + : Output + :: |response|, a [=/response=] + + 1. Let |eventCanceled| be false. + 1. Let |client| be |request|'s [=request/client=]. + 1. Let |activeWorker| be |registration|'s active worker. + 1. Let |eventHandled| be null. + 1. Let |handleFetchFailed| be false. + 1. Let |respondWithEntered| be false. 1. Let |shouldSoftUpdate| be true if any of the following are true, and false otherwise: * |request| is a [=non-subresource request=]. * |request| is a [=subresource request=] and |registration| is [=stale=]. @@ -3237,9 +3258,6 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Else, [=ReadableStream/cancel=] |request|'s [=request/body=] with undefined. 1. If |response| is not null, then: 1. Set |response|'s [=response/service worker timing info=] to |timingInfo|. - 1. If |raceFetchController| is not null, then: - 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. - 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. 1. If |controller| [=fetch controller/state=] is "terminated" or "aborted", then: 1. Let |deserializedError| be a "{{AbortError}}" {{DOMException}}. From e18d7ea96ebf1525681a9aa1e93c4b9a2b2fb24e Mon Sep 17 00:00:00 2001 From: sisidovski Date: Tue, 6 Feb 2024 16:27:05 +0900 Subject: [PATCH 05/19] Fix id name and tags --- docs/index.bs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index fcf0b8eb..b5d7ebc0 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3155,13 +3155,17 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ Note: In order to avoid duplicated fetches to |request|, the user agent may reuse |raceNetworkRequestResponse| as the result of {{FetchEvent}}'s [=FetchEvent/potential response=], or the fallback request. 1. Let |queue| be an empty [=queue=] of [=/response=]. - 1. Run the following substeps [=in parallel=]: - 1. Let |raceFetchController| to the result of [=Fetch|fetching=] |request|. + 1. Let |raceFetchController| be null. + 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": + 1. Set |raceFetchController| to the result of [=Fetch|fetching=] |request|. 1. To [=fetch/processResponse=] for |raceNetworkRequestResponse|, run these substeps: 1. If |raceNetworkRequestResponse|'s [=response/type=] is "`error`", then: 1. Terminate these substeps. 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. + 1. [=If aborted=], then: + 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. + 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. 1. Run the following substeps [=in parallel=]: 1. Resolve |preloadResponse| with undefined. 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. @@ -3196,7 +3200,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/

-

Create Fetch Event and Dispatch

+

Create Fetch Event and Dispatch

: Input :: |request|, a [=/request=] :: |registration|, a [=/service worker registration=] From 210fd4f693145d91337a1e579e15a4254b1d89cf Mon Sep 17 00:00:00 2001 From: sisidovski Date: Tue, 6 Feb 2024 16:28:36 +0900 Subject: [PATCH 06/19] Restore old sentence --- docs/index.bs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index b5d7ebc0..b951e62b 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3260,8 +3260,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |response| is null, |request|'s [=request/body=] is not null, and |request|'s [=request/body=]'s [=body/source=] is null, then: 1. If |request|'s [=request/body=] is [=Body/unusable=], set |handleFetchFailed| to true. 1. Else, [=ReadableStream/cancel=] |request|'s [=request/body=] with undefined. - 1. If |response| is not null, then: - 1. Set |response|'s [=response/service worker timing info=] to |timingInfo|. + 1. If |response| is not null, then set |response|'s [=response/service worker timing info=] to |timingInfo|. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. 1. If |controller| [=fetch controller/state=] is "terminated" or "aborted", then: 1. Let |deserializedError| be a "{{AbortError}}" {{DOMException}}. From 8e087c89d9975fe647dc8d2e71f952a71a9ab2df Mon Sep 17 00:00:00 2001 From: sisidovski Date: Wed, 7 Feb 2024 00:26:53 +0900 Subject: [PATCH 07/19] Abort race request if not needed --- docs/index.bs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index b951e62b..3b92dc8c 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3163,12 +3163,15 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Terminate these substeps. 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. - 1. [=If aborted=], then: + 1. [=If aborted=] and |raceFetchController| is not null, then: 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. 1. Run the following substeps [=in parallel=]: 1. Resolve |preloadResponse| with undefined. 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. + 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, then: + 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. + 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. 1. Wait until |queue| is not empty. 1. Set |response| to the result of [=dequeue=] |queue|. From 2e868044b3cbc326669825b4e43a70f5ab792333 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Thu, 8 Feb 2024 09:38:25 +0900 Subject: [PATCH 08/19] Fixed passing the error to [=fetch controller/Abort=], indentation, 200 to [=ok status=], updated the caller for fetch |reqeuest| --- docs/index.bs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 3b92dc8c..87f6523a 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3157,21 +3157,13 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": - 1. Set |raceFetchController| to the result of [=Fetch|fetching=] |request|. - 1. To [=fetch/processResponse=] for |raceNetworkRequestResponse|, run these substeps: - 1. If |raceNetworkRequestResponse|'s [=response/type=] is "`error`", then: - 1. Terminate these substeps. - 1. If |raceNetworkRequestResponse|'s [=response/status=] is `200`, then: - 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. - 1. [=If aborted=] and |raceFetchController| is not null, then: - 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. - 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. + 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: + 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], [=queue/enqueue=] |raceNetworkRequestResponse| to |queue|. + 1. [=If aborted=] and |raceFetchController| is not null, [=fetch controller/Abort=] |raceFetchController|. + 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: - 1. Resolve |preloadResponse| with undefined. 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. - 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, then: - 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. - 1. [=fetch controller/Abort=] |raceFetchController| with |deserializedError|. + 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, [=fetch controller/Abort=] |raceFetchController|. 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. 1. Wait until |queue| is not empty. 1. Set |response| to the result of [=dequeue=] |queue|. From b9d6c63d4d8ab793effe038f671cc695b08c631c Mon Sep 17 00:00:00 2001 From: sisidovski Date: Fri, 9 Feb 2024 13:53:10 +0900 Subject: [PATCH 09/19] Collapse some redundant steps, make enum multiline, fixed abot, remove |response| --- docs/index.bs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 87f6523a..090c86b5 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1578,7 +1578,12 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ }; enum RunningStatus { "running", "not-running" }; - enum RouterSourceEnum { "cache", "fetch-event", "network", "race-network-and-fetch-handler" }; + enum RouterSourceEnum { + "cache", + "fetch-event", + "network", + "race-network-and-fetch-handler" + };
@@ -3106,9 +3111,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ :: |controller|, a [=fetch controller=] :: |useHighResPerformanceTimers|, a boolean : Output - :: |response|, a [=/response=] + :: a [=/response=] - 1. Let |response| be null. 1. Let |registration| be null. 1. Let |client| be |request|'s [=request/client=]. 1. Let |reservedClient| be |request|'s [=request/reserved client=]. @@ -3159,15 +3163,14 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], [=queue/enqueue=] |raceNetworkRequestResponse| to |queue|. - 1. [=If aborted=] and |raceFetchController| is not null, [=fetch controller/Abort=] |raceFetchController|. + 1. [=If aborted=] and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. - 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, [=fetch controller/Abort=] |raceFetchController|. + 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. 1. Wait until |queue| is not empty. - 1. Set |response| to the result of [=dequeue=] |queue|. - 1. Return |response|. + 1. Return the result of [=dequeue=] |queue|. 1. If |request| is a non-subresource request, |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`GET\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] fetch, and |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set, then: Note: If the above is true except |registration|'s [=active worker=]'s set of event types to handle **does not** contain fetch, then the user agent may wish to show a console warning, as the developer's intent isn't clear. @@ -3190,8 +3193,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. 1. [=fetch controller/Abort=] |preloadFetchController| with |deserializedError|. 1. Else, resolve |preloadResponse| with undefined. - 1. Set |response| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. - 1. Retrun |response|. + 1. Return the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|.
@@ -3205,8 +3207,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ :: |reservedClient|, a [=request/reserved client=]. :: |preloadResponse| a [=promise=]. : Output - :: |response|, a [=/response=] + :: a [=/response=] + 1. Let |response| be null. 1. Let |eventCanceled| be false. 1. Let |client| be |request|'s [=request/client=]. 1. Let |activeWorker| be |registration|'s active worker. From 67561a63bd1e80cd5cbab798af1737ef1509a323 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Fri, 9 Feb 2024 17:59:39 +0900 Subject: [PATCH 10/19] Add fallback case --- docs/index.bs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 090c86b5..c7688dac 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3119,6 +3119,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |preloadResponse| be a new [=promise=]. 1. Let |workerRealm| be null. 1. Let |timingInfo| be a new [=service worker timing info=]. + 1. Let |raceResponse| be null. 1. Assert: |request|'s [=request/destination=] is not "serviceworker". 1. If |request|'s [=request/destination=] is either "embed" or "object", then: 1. Return null. @@ -3162,11 +3163,15 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |raceFetchController| be null. 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: - 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], [=queue/enqueue=] |raceNetworkRequestResponse| to |queue|. + 1. Set |raceResponse| to [=a new promise=]. + 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: + 1. Resolve |raceResponse| with |raceNetworkRequestResponse|. + 1. [=queue/enqueue=] |raceNetworkRequestResponse| to |queue|. + 1. Otherwise, reject |raceResponse| with a `TypeError`. 1. [=If aborted=] and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: - 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. + 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and |raceResponse|. 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. 1. Wait until |queue| is not empty. @@ -3193,7 +3198,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |deserializedError| be the result of [=deserialize a serialized abort reason=] given null and |workerRealm|. 1. [=fetch controller/Abort=] |preloadFetchController| with |deserializedError|. 1. Else, resolve |preloadResponse| with undefined. - 1. Return the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, and |preloadResponse|. + 1. Return the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and |raceResponse|.
@@ -3206,6 +3211,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ :: |workerRealm|, a [=relevant realm=] of the [=service worker/global object=]. :: |reservedClient|, a [=request/reserved client=]. :: |preloadResponse| a [=promise=]. + :: |raceResponse| a [=promise=]. : Output :: a [=/response=] @@ -3276,6 +3282,10 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |eventHandled| is not null, then [=reject=] |eventHandled| with a "{{NetworkError}}" {{DOMException}} in |workerRealm|. 2. Return a [=network error=]. 1. If |eventHandled| is not null, then [=resolve=] |eventHandled|. + 1. If |raceResponse| is not null, then: + 1. [=promise/React=] to |raceResponse|: + 1. If |raceResponse| was fulfilled with value |v|, return |v|. + 1. If |raceResponse| was rejected, return [=network error=]. 1. Return null. 1. If |handleFetchFailed| is true, then: 1. If |eventHandled| is not null, then [=reject=] |eventHandled| with a "{{NetworkError}}" {{DOMException}} in |workerRealm|. From f8a0d3df2f4037d1d067cf52a0a67f7759949d3a Mon Sep 17 00:00:00 2001 From: sisidovski Date: Wed, 14 Feb 2024 18:32:35 +0900 Subject: [PATCH 11/19] Add token and lookup algorithm --- docs/index.bs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index c7688dac..c67de67f 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1079,7 +1079,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ }; - A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. It is initially unset. + A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are strings and the [=map/values=] are promises. It is initially unset. Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a [=/service worker=] is started, kept alive and killed by their relationship to events, not [=/service worker clients=]. Any type of synchronous requests must not be initiated inside of a [=/service worker=]. @@ -3241,6 +3241,11 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Else: 1. Set |workerRealm| to the [=relevant realm=] of the |activeWorker|'s [=service worker/global object=]. 1. Set |eventHandled| to [=a new promise=] in |workerRealm|. + 1. If |raceResponse| is not null, then: + 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. + 1. Let |token| be the result of [=generating a random UUID=]. + 1. [=map/Set=] |map|[|token|] to |raceResponse|. + 1. Set |request|'s [=request/service-workers race token=] to |token|. 1. [=Queue a task=] |task| to run the following substeps: 1. Let |e| be the result of creating an event with {{FetchEvent}}. 1. Let |controller| be a [=new=] {{AbortController}} object with |workerRealm|. @@ -3923,6 +3928,29 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Return true. 1. Return false.
+ +
+

Lookup Race Response

+ + : Input + :: |key|, a string + :: |reservedClient|, [=request/reserved client=] + :: |url|, [=request/url=] + : Output + :: a [=promise=]. + + 1. If |reservedClient| is null, return null. + 1. Let |storage key| be the result of running [=obtain a storage key=] given |reservedClient|. + 1. Let |registration| be the result of running Match Service Worker Registration given |storage key| and |url|. + 1. If |registration| is null or |registration|'s active worker is null, return null. + 1. Else, let |activeWorker| be |registration|'s active worker. + 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. + 1. If |map|[|key|] [=map/exist=], then: + 1. Let |entry| be |map|[|key|]. + 1. [=map/Remove=] |map|[|key|]. + 1. Return |entry|. + 1. Otherwise, return null. +
From fd5b794bd14d63710303bc57ac2d2353ca538e33 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Wed, 14 Feb 2024 18:56:54 +0900 Subject: [PATCH 12/19] Drop incorrect note --- docs/index.bs | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index c67de67f..f0230ee2 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3156,9 +3156,6 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Return |response|. 1. Return null. 1. Else if |source| is {{RouterSourceEnum/"race-network-and-fetch-handler"}}, and |request|'s [=request/method=] is \`GET\` then: - - Note: In order to avoid duplicated fetches to |request|, the user agent may reuse |raceNetworkRequestResponse| as the result of {{FetchEvent}}'s [=FetchEvent/potential response=], or the fallback request. - 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": From aa42d5509f98f3e19c395cee51428193231c7fbd Mon Sep 17 00:00:00 2001 From: sisidovski Date: Thu, 15 Feb 2024 15:33:29 +0900 Subject: [PATCH 13/19] Fix incorrect format, update the map key to be request --- docs/index.bs | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index f0230ee2..001f271d 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1079,7 +1079,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ }; - A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are strings and the [=map/values=] are promises. It is initially unset. + A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are [=requests=] and the [=map/values=] are promises. It is initially unset. Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a [=/service worker=] is started, kept alive and killed by their relationship to events, not [=/service worker clients=]. Any type of synchronous requests must not be initiated inside of a [=/service worker=]. @@ -3162,13 +3162,13 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: 1. Set |raceResponse| to [=a new promise=]. 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: - 1. Resolve |raceResponse| with |raceNetworkRequestResponse|. - 1. [=queue/enqueue=] |raceNetworkRequestResponse| to |queue|. - 1. Otherwise, reject |raceResponse| with a `TypeError`. + 1. [=Resolve=] |raceResponse| with |raceNetworkRequestResponse|. + 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. + 1. Otherwise, [=reject=] |raceResponse| with a `TypeError`. 1. [=If aborted=] and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: - 1. Let |fetchHandlerResponse| to the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and |raceResponse|. + 1. Let |fetchHandlerResponse| be the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and |raceResponse|. 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. 1. Wait until |queue| is not empty. @@ -3204,11 +3204,11 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ :: |request|, a [=/request=] :: |registration|, a [=/service worker registration=] :: |useHighResPerformanceTimers|, a boolean - :: |timingInfo|, a [=service worker timing info=]. - :: |workerRealm|, a [=relevant realm=] of the [=service worker/global object=]. - :: |reservedClient|, a [=request/reserved client=]. - :: |preloadResponse| a [=promise=]. - :: |raceResponse| a [=promise=]. + :: |timingInfo|, a [=service worker timing info=] + :: |workerRealm|, a [=relevant realm=] of the [=service worker/global object=] + :: |reservedClient|, a [=request/reserved client=] + :: |preloadResponse|, a [=promise=] + :: |raceResponse|, a [=promise=] : Output :: a [=/response=] @@ -3240,8 +3240,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Set |eventHandled| to [=a new promise=] in |workerRealm|. 1. If |raceResponse| is not null, then: 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. - 1. Let |token| be the result of [=generating a random UUID=]. - 1. [=map/Set=] |map|[|token|] to |raceResponse|. + 1. [=map/Set=] |map|[|request|] to |raceResponse|. 1. Set |request|'s [=request/service-workers race token=] to |token|. 1. [=Queue a task=] |task| to run the following substeps: 1. Let |e| be the result of creating an event with {{FetchEvent}}. @@ -3930,21 +3929,19 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/

Lookup Race Response

: Input - :: |key|, a string - :: |reservedClient|, [=request/reserved client=] - :: |url|, [=request/url=] + :: |request|, a [=request=] : Output :: a [=promise=]. - 1. If |reservedClient| is null, return null. - 1. Let |storage key| be the result of running [=obtain a storage key=] given |reservedClient|. + 1. If |request|'s [=request/reserved client=] is null, return null. + 1. Let |storage key| be the result of running [=obtain a storage key=] given |request|'s [=request/reserved client=]. 1. Let |registration| be the result of running Match Service Worker Registration given |storage key| and |url|. 1. If |registration| is null or |registration|'s active worker is null, return null. 1. Else, let |activeWorker| be |registration|'s active worker. 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. - 1. If |map|[|key|] [=map/exist=], then: - 1. Let |entry| be |map|[|key|]. - 1. [=map/Remove=] |map|[|key|]. + 1. If |map|[|request|] [=map/exist=], then: + 1. Let |entry| be |map|[|request|]. + 1. [=map/Remove=] |map|[|request|]. 1. Return |entry|. 1. Otherwise, return null.
From 3245241bb096979e485fa2ef7a699cc028e3f6df Mon Sep 17 00:00:00 2001 From: sisidovski Date: Thu, 15 Feb 2024 15:55:19 +0900 Subject: [PATCH 14/19] Do not use promise to manage [=/response=] --- docs/index.bs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 001f271d..d9bbe473 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3158,14 +3158,16 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Else if |source| is {{RouterSourceEnum/"race-network-and-fetch-handler"}}, and |request|'s [=request/method=] is \`GET\` then: 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. + 1. Set |raceResponse| to "pending". 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: - 1. Set |raceResponse| to [=a new promise=]. 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: - 1. [=Resolve=] |raceResponse| with |raceNetworkRequestResponse|. + 1. Set |raceResponse| to |raceNetworkRequestResponse|. 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. - 1. Otherwise, [=reject=] |raceResponse| with a `TypeError`. - 1. [=If aborted=] and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. + 1. Otherwise, set |raceResponse| to a `TypeError`. + 1. [=If aborted=] and |raceFetchController| is not null, then: + 1. [=fetch controller/abort=] |raceFetchController|. + 1. Set |raceResponse| to null. 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: 1. Let |fetchHandlerResponse| be the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and |raceResponse|. @@ -3208,7 +3210,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ :: |workerRealm|, a [=relevant realm=] of the [=service worker/global object=] :: |reservedClient|, a [=request/reserved client=] :: |preloadResponse|, a [=promise=] - :: |raceResponse|, a [=promise=] + :: |raceResponse|, a null, "pending" or [=/response=] : Output :: a [=/response=] @@ -3241,7 +3243,6 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |raceResponse| is not null, then: 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. 1. [=map/Set=] |map|[|request|] to |raceResponse|. - 1. Set |request|'s [=request/service-workers race token=] to |token|. 1. [=Queue a task=] |task| to run the following substeps: 1. Let |e| be the result of creating an event with {{FetchEvent}}. 1. Let |controller| be a [=new=] {{AbortController}} object with |workerRealm|. @@ -3284,9 +3285,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 2. Return a [=network error=]. 1. If |eventHandled| is not null, then [=resolve=] |eventHandled|. 1. If |raceResponse| is not null, then: - 1. [=promise/React=] to |raceResponse|: - 1. If |raceResponse| was fulfilled with value |v|, return |v|. - 1. If |raceResponse| was rejected, return [=network error=]. + 1. Wait until |raceResponse| is not "pending" + 1. If |raceResponse| is [=/response=], return |raceResponse|. 1. Return null. 1. If |handleFetchFailed| is true, then: 1. If |eventHandled| is not null, then [=reject=] |eventHandled| with a "{{NetworkError}}" {{DOMException}} in |workerRealm|. From 01c0773ec35e9345606eb19247f3686da8e38799 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Thu, 15 Feb 2024 17:09:01 +0900 Subject: [PATCH 15/19] Added the race response struct --- docs/index.bs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index d9bbe473..c1315584 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1079,7 +1079,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ }; - A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are [=requests=] and the [=map/values=] are promises. It is initially unset. + A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are [=requests=] and the [=map/values=] are [=race response=]. It is initially unset. + + A race response is a [=struct=] used to contain the network response when {{RouterSourceEnum/"race-network-and-fetch-handler"}} performs. It has [=/response=], or "pending" as an [=struct/item=]. Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a [=/service worker=] is started, kept alive and killed by their relationship to events, not [=/service worker clients=]. Any type of synchronous requests must not be initiated inside of a [=/service worker=]. @@ -3164,7 +3166,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: 1. Set |raceResponse| to |raceNetworkRequestResponse|. 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. - 1. Otherwise, set |raceResponse| to a `TypeError`. + 1. Otherwise, set |raceResponse| to a [=network error=]. 1. [=If aborted=] and |raceFetchController| is not null, then: 1. [=fetch controller/abort=] |raceFetchController|. 1. Set |raceResponse| to null. @@ -3210,7 +3212,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ :: |workerRealm|, a [=relevant realm=] of the [=service worker/global object=] :: |reservedClient|, a [=request/reserved client=] :: |preloadResponse|, a [=promise=] - :: |raceResponse|, a null, "pending" or [=/response=] + :: |raceResponse|, a [=race response=] : Output :: a [=/response=] @@ -3931,7 +3933,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ : Input :: |request|, a [=request=] : Output - :: a [=promise=]. + :: a [=race response=]. 1. If |request|'s [=request/reserved client=] is null, return null. 1. Let |storage key| be the result of running [=obtain a storage key=] given |request|'s [=request/reserved client=]. From 6d43556ba8f779c050350a94c0fc8521091a0440 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Fri, 16 Feb 2024 03:02:52 +0900 Subject: [PATCH 16/19] Update race response struct --- docs/index.bs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index c1315584..6cb06210 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1081,7 +1081,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are [=requests=] and the [=map/values=] are [=race response=]. It is initially unset. - A race response is a [=struct=] used to contain the network response when {{RouterSourceEnum/"race-network-and-fetch-handler"}} performs. It has [=/response=], or "pending" as an [=struct/item=]. + A race response is a [=struct=] used to contain the network response when {{RouterSourceEnum/"race-network-and-fetch-handler"}} performs. It has a value, which is a [=/response=], "pending", or null. Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a [=/service worker=] is started, kept alive and killed by their relationship to events, not [=/service worker clients=]. Any type of synchronous requests must not be initiated inside of a [=/service worker=]. @@ -3121,7 +3121,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |preloadResponse| be a new [=promise=]. 1. Let |workerRealm| be null. 1. Let |timingInfo| be a new [=service worker timing info=]. - 1. Let |raceResponse| be null. + 1. Let |raceResponse| be a [=race response=] whose [=race response/value=] is null. 1. Assert: |request|'s [=request/destination=] is not "serviceworker". 1. If |request|'s [=request/destination=] is either "embed" or "object", then: 1. Return null. @@ -3160,16 +3160,16 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Else if |source| is {{RouterSourceEnum/"race-network-and-fetch-handler"}}, and |request|'s [=request/method=] is \`GET\` then: 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. - 1. Set |raceResponse| to "pending". + 1. Set |raceResponse|'s [=race response/value=] to "pending". 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: - 1. Set |raceResponse| to |raceNetworkRequestResponse|. + 1. Set |raceResponse|'s [=race response/value=] to |raceNetworkRequestResponse|. 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. - 1. Otherwise, set |raceResponse| to a [=network error=]. + 1. Otherwise, set |raceResponse|'s [=race response/value=] to a [=network error=]. 1. [=If aborted=] and |raceFetchController| is not null, then: 1. [=fetch controller/abort=] |raceFetchController|. - 1. Set |raceResponse| to null. + 1. Set |raceResponse| to a [=race response=] whose [=race response/value=] is null. 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: 1. Let |fetchHandlerResponse| be the result of [=Create Fetch Event and Dispatch=] with |request|, |registration|, |useHighResPerformanceTimers|, |timingInfo|, |workerRealm|, |reservedClient|, |preloadResponse|, and |raceResponse|. @@ -3242,7 +3242,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Else: 1. Set |workerRealm| to the [=relevant realm=] of the |activeWorker|'s [=service worker/global object=]. 1. Set |eventHandled| to [=a new promise=] in |workerRealm|. - 1. If |raceResponse| is not null, then: + 1. If |raceResponse|'s [=race response/value=] is not null, then: 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. 1. [=map/Set=] |map|[|request|] to |raceResponse|. 1. [=Queue a task=] |task| to run the following substeps: @@ -3286,9 +3286,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |eventHandled| is not null, then [=reject=] |eventHandled| with a "{{NetworkError}}" {{DOMException}} in |workerRealm|. 2. Return a [=network error=]. 1. If |eventHandled| is not null, then [=resolve=] |eventHandled|. - 1. If |raceResponse| is not null, then: - 1. Wait until |raceResponse| is not "pending" - 1. If |raceResponse| is [=/response=], return |raceResponse|. + 1. If |raceResponse|'s [=race response/value=] is not null, then: + 1. Wait until |raceResponse|'s [=race response/value=] is not "pending" + 1. If |raceResponse|'s [=race response/value=] is [=/response=], return |raceResponse|'s [=race response/value=]. 1. Return null. 1. If |handleFetchFailed| is true, then: 1. If |eventHandled| is not null, then [=reject=] |eventHandled| with a "{{NetworkError}}" {{DOMException}} in |workerRealm|. @@ -3933,7 +3933,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ : Input :: |request|, a [=request=] : Output - :: a [=race response=]. + :: a [=/response=], or null. 1. If |request|'s [=request/reserved client=] is null, return null. 1. Let |storage key| be the result of running [=obtain a storage key=] given |request|'s [=request/reserved client=]. @@ -3944,8 +3944,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |map|[|request|] [=map/exist=], then: 1. Let |entry| be |map|[|request|]. 1. [=map/Remove=] |map|[|request|]. - 1. Return |entry|. - 1. Otherwise, return null. + 1. Wait until |entry|'s [=race response/value=] is not "pending" + 1. If |entry|'s [=race response/value=] is [=/response=], return |entry|'s [=race response/value=]. + 1. Return null. From 27ccc75de6bb350830eb7f377b05ca3e114651e2 Mon Sep 17 00:00:00 2001 From: sisidovski Date: Fri, 16 Feb 2024 03:28:45 +0900 Subject: [PATCH 17/19] Remove unconsumed map entry --- docs/index.bs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 6cb06210..0a9ef958 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3161,6 +3161,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. 1. Set |raceResponse|'s [=race response/value=] to "pending". + 1. [=map/Set=] |activeWorker|'s [=service worker/global object=]'s [=race response map=][|request|] to |raceResponse|. 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: @@ -3226,6 +3227,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |shouldSoftUpdate| be true if any of the following are true, and false otherwise: * |request| is a [=non-subresource request=]. * |request| is a [=subresource request=] and |registration| is [=stale=]. + 1. Let |raceResponseMap| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. 1. If the result of running the [=Should Skip Event=] algorithm with "fetch" and |activeWorker| is true, then: 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. 1. Return null. @@ -3242,9 +3244,6 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Else: 1. Set |workerRealm| to the [=relevant realm=] of the |activeWorker|'s [=service worker/global object=]. 1. Set |eventHandled| to [=a new promise=] in |workerRealm|. - 1. If |raceResponse|'s [=race response/value=] is not null, then: - 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. - 1. [=map/Set=] |map|[|request|] to |raceResponse|. 1. [=Queue a task=] |task| to run the following substeps: 1. Let |e| be the result of creating an event with {{FetchEvent}}. 1. Let |controller| be a [=new=] {{AbortController}} object with |workerRealm|. @@ -3281,6 +3280,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Wait for |task| to have executed or for |handleFetchFailed| to be true. 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. + 1. If |raceResponseMap|[|request|] [=map/exists=], [=map/remove=] |raceResponseMap|[|request|]. 1. If |respondWithEntered| is false, then: 1. If |eventCanceled| is true, then: 1. If |eventHandled| is not null, then [=reject=] |eventHandled| with a "{{NetworkError}}" {{DOMException}} in |workerRealm|. @@ -3931,7 +3931,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/

Lookup Race Response

: Input - :: |request|, a [=request=] + :: |request|, a [=/request=] : Output :: a [=/response=], or null. @@ -3941,7 +3941,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |registration| is null or |registration|'s active worker is null, return null. 1. Else, let |activeWorker| be |registration|'s active worker. 1. Let |map| be |activeWorker|'s [=service worker/global object=]'s [=race response map=]. - 1. If |map|[|request|] [=map/exist=], then: + 1. If |map|[|request|] [=map/exists=], then: 1. Let |entry| be |map|[|request|]. 1. [=map/Remove=] |map|[|request|]. 1. Wait until |entry|'s [=race response/value=] is not "pending" From 1cd657af4188c36a1b3a9e9ae1d7a009c1d725ea Mon Sep 17 00:00:00 2001 From: sisidovski Date: Fri, 16 Feb 2024 10:43:22 +0900 Subject: [PATCH 18/19] Move adidng an entry after `run service worker` --- docs/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index 0a9ef958..6d4eed11 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3161,7 +3161,6 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. 1. Set |raceResponse|'s [=race response/value=] to "pending". - 1. [=map/Set=] |activeWorker|'s [=service worker/global object=]'s [=race response map=][|request|] to |raceResponse|. 1. Run the following substeps [=in parallel=], but [=abort when=] |controller|'s [=fetch controller/state=] is "terminated" or "aborted": 1. Set |raceFetchController| to the result of calling [=fetch=] given |request|, with [=fetch/processResponse=] set to the following steps given a [=/response=] |raceNetworkRequestResponse|: 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: @@ -3244,6 +3243,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Else: 1. Set |workerRealm| to the [=relevant realm=] of the |activeWorker|'s [=service worker/global object=]. 1. Set |eventHandled| to [=a new promise=] in |workerRealm|. + 1. If |raceResponse| is not null, [=map/set=] |raceResponseMap|[|request|] to |raceResponse|. 1. [=Queue a task=] |task| to run the following substeps: 1. Let |e| be the result of creating an event with {{FetchEvent}}. 1. Let |controller| be a [=new=] {{AbortController}} object with |workerRealm|. From bf4bdaf933b8b62c2ac4a8d8251b49b0e794752f Mon Sep 17 00:00:00 2001 From: sisidovski Date: Fri, 16 Feb 2024 12:59:07 +0900 Subject: [PATCH 19/19] Fix editorial issues --- docs/index.bs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 4fc1b4c0..a27c39d5 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1082,7 +1082,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ }; - A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are [=requests=] and the [=map/values=] are [=race response=]. It is initially unset. + A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). A {{ServiceWorkerGlobalScope}} object has an associated force bypass cache for import scripts flag. A {{ServiceWorkerGlobalScope}} object has an associated race response map which is an [=ordered map=] where the [=map/keys=] are [=/requests=] and the [=map/values=] are [=race response=]. It is initially unset. A race response is a [=struct=] used to contain the network response when {{RouterSourceEnum/"race-network-and-fetch-handler"}} performs. It has a value, which is a [=/response=], "pending", or null. @@ -3216,7 +3216,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. [=queue/Enqueue=] |raceNetworkRequestResponse| to |queue|. 1. Otherwise, set |raceResponse|'s [=race response/value=] to a [=network error=]. 1. [=If aborted=] and |raceFetchController| is not null, then: - 1. [=fetch controller/abort=] |raceFetchController|. + 1. [=fetch controller/Abort=] |raceFetchController|. 1. Set |raceResponse| to a [=race response=] whose [=race response/value=] is null. 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: @@ -3336,8 +3336,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 2. Return a [=network error=]. 1. If |eventHandled| is not null, then [=resolve=] |eventHandled|. 1. If |raceResponse|'s [=race response/value=] is not null, then: - 1. Wait until |raceResponse|'s [=race response/value=] is not "pending" - 1. If |raceResponse|'s [=race response/value=] is [=/response=], return |raceResponse|'s [=race response/value=]. + 1. Wait until |raceResponse|'s [=race response/value=] is not "pending". + 1. If |raceResponse|'s [=race response/value=] is a [=/response=], return |raceResponse|'s [=race response/value=]. 1. Return null. 1. If |handleFetchFailed| is true, then: 1. If |eventHandled| is not null, then [=reject=] |eventHandled| with a "{{NetworkError}}" {{DOMException}} in |workerRealm|. @@ -3985,7 +3985,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ : Input :: |request|, a [=/request=] : Output - :: a [=/response=], or null. + :: a [=/response=] or null 1. If |request|'s [=request/reserved client=] is null, return null. 1. Let |storage key| be the result of running [=obtain a storage key=] given |request|'s [=request/reserved client=].