From f2d5c723cf7621a8b2f4d8860810fd3dd12ce659 Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Tue, 15 Apr 2025 22:31:00 -0700 Subject: [PATCH 01/11] add race-network-and-cache --- docs/index.bs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index bf094df7..79d6dd5d 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1600,6 +1600,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ dictionary RouterSourceDict { DOMString cacheName; + DOMString raceNetworkAndCacheCacheName; }; enum RunningStatus { "running", "not-running" }; @@ -1607,7 +1608,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ "cache", "fetch-event", "network", - "race-network-and-fetch-handler" + "race-network-and-fetch-handler", + "race-network-and-cache" }; From c39d796d67beb2e656ed8a967e50ce27fd03f1be Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Wed, 16 Apr 2025 17:25:01 -0700 Subject: [PATCH 02/11] update failure cases --- docs/index.bs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index 79d6dd5d..73bc4fe5 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3265,6 +3265,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |queue| be an empty [=queue=] of [=race result=]. 1. Let |raceFetchController| be null. 1. Let |raceResponse| be a [=race response=] whose [=race response/value=] is "pending". + 1. Let |networkFetchCompleted| be false. + 1. Let |fetchHandlerCompleted| be false. 1. Run the following substeps [=in parallel=], but [=abort when=] |fetchController|'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: @@ -3272,6 +3274,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |raceNetworkResult| be a [=race result=] whose [=race result/routed response=] is |raceNetworkRequestResponse| and [=race result/used route=] is {{RouterSourceEnum/"network"}}. 1. [=queue/Enqueue=] |raceNetworkResult| to |queue|. 1. Otherwise, set |raceResponse|'s [=race response/value=] to a [=network error=]. + 1. Set |networkFetchCompleted| to true. 1. [=If aborted=] and |raceFetchController| is not null, then: 1. [=fetch controller/Abort=] |raceFetchController|. 1. Set |raceResponse| to a [=race response=] whose [=race response/value=] is null. @@ -3281,7 +3284,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. Let |raceFetchHandlerResult| be a [=race result=] whose [=race result/routed response=] is |fetchHandlerResponse| and [=race result/used route=] is {{RouterSourceEnum/"fetch-event"}}. 1. [=queue/Enqueue=] |raceFetchHandlerResult| to |queue|. - 1. Wait until |queue| is not empty. + 1. Set |fetchHandlerCompleted| to true. + 1. Wait until |queue| is not empty or (|networkFetchCompleted| is true and |fetchHandlerCompleted| is true). + 1. If |queue| is empty, return null. 1. Let |result| be the result of [=dequeue=] |queue|. 1. Let |routedResponse| be |result|'s [=race result/routed response=]. 1. If |result|'s [=race result/used route=] is {{RouterSourceEnum/"network"}}, then: From f206baf6f0b8f500cad31394110b459492340368 Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Sun, 20 Apr 2025 08:21:11 -0700 Subject: [PATCH 03/11] Follow spec format --- docs/index.bs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index 73bc4fe5..bad3e654 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3285,7 +3285,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |raceFetchHandlerResult| be a [=race result=] whose [=race result/routed response=] is |fetchHandlerResponse| and [=race result/used route=] is {{RouterSourceEnum/"fetch-event"}}. 1. [=queue/Enqueue=] |raceFetchHandlerResult| to |queue|. 1. Set |fetchHandlerCompleted| to true. - 1. Wait until |queue| is not empty or (|networkFetchCompleted| is true and |fetchHandlerCompleted| is true). + 1. Wait until any of the following are true: + 1. |queue| is not empty. + 1. Both |networkFetchCompleted| and |cacheLookupCompleted| are true. 1. If |queue| is empty, return null. 1. Let |result| be the result of [=dequeue=] |queue|. 1. Let |routedResponse| be |result|'s [=race result/routed response=]. From 71029874af7347605aff2aba558e30da9ea5d3d1 Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Mon, 21 Apr 2025 23:07:40 -0700 Subject: [PATCH 04/11] use |raceResponse| when empty --- docs/index.bs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index bad3e654..dbd1717b 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3288,7 +3288,10 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Wait until any of the following are true: 1. |queue| is not empty. 1. Both |networkFetchCompleted| and |cacheLookupCompleted| are true. - 1. If |queue| is empty, return null. + 1. If |queue| is empty, then: + 1. If |raceResponse|'s [=race response/value=] is a [=/response=], return |raceResponse|'s [=race response/value=]. + 1. If |raceResponse|'s [=race response/value=] is a [=network error=], return a [=network error=]. + 1. Return null. 1. Let |result| be the result of [=dequeue=] |queue|. 1. Let |routedResponse| be |result|'s [=race result/routed response=]. 1. If |result|'s [=race result/used route=] is {{RouterSourceEnum/"network"}}, then: From c9a9907b10d2d342416f1751e0e1b23d8f1bd8f9 Mon Sep 17 00:00:00 2001 From: Yoshisato Yanagisawa Date: Tue, 10 Jun 2025 08:33:19 +0000 Subject: [PATCH 05/11] Remove race-network-and-cache source enum etc. I merged them by mistake. Let me remove. --- docs/index.bs | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index dbd1717b..4b868b40 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1600,7 +1600,6 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ dictionary RouterSourceDict { DOMString cacheName; - DOMString raceNetworkAndCacheCacheName; }; enum RunningStatus { "running", "not-running" }; @@ -1609,7 +1608,6 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ "fetch-event", "network", "race-network-and-fetch-handler", - "race-network-and-cache" }; From 9a145127ebc9459a9e0ba2ddefe8235c4aba6d04 Mon Sep 17 00:00:00 2001 From: Yoshisato Yanagisawa Date: Tue, 10 Jun 2025 08:34:23 +0000 Subject: [PATCH 06/11] Remove unnecessary change to the enum --- docs/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index 4b868b40..5b70bb87 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1607,7 +1607,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ "cache", "fetch-event", "network", - "race-network-and-fetch-handler", + "race-network-and-fetch-handler" }; From 8eec31ab7a899f811a093b5dd832ab135972ab0c Mon Sep 17 00:00:00 2001 From: Yoshisato Yanagisawa Date: Wed, 11 Jun 2025 16:37:28 +0900 Subject: [PATCH 07/11] Update docs/index.bs Apply the suggestion. Co-authored-by: Domenic Denicola --- docs/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 5b70bb87..5c0c3a13 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3284,8 +3284,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. [=queue/Enqueue=] |raceFetchHandlerResult| to |queue|. 1. Set |fetchHandlerCompleted| to true. 1. Wait until any of the following are true: - 1. |queue| is not empty. - 1. Both |networkFetchCompleted| and |cacheLookupCompleted| are true. + * |queue| is not empty; or + * both |networkFetchCompleted| and |cacheLookupCompleted| are true. 1. If |queue| is empty, then: 1. If |raceResponse|'s [=race response/value=] is a [=/response=], return |raceResponse|'s [=race response/value=]. 1. If |raceResponse|'s [=race response/value=] is a [=network error=], return a [=network error=]. From c02659f1d9fe359d54e76f4a609a02883f9a9a3e Mon Sep 17 00:00:00 2001 From: Yoshisato Yanagisawa Date: Wed, 11 Jun 2025 09:15:20 +0000 Subject: [PATCH 08/11] Assuming that the fetch event part always get queued Upon the discussion, I understand that the fetch event part will always be queued. However, we need to wait for the network response so that we can reuse it as response on error. We also need to set the proper |timingInfo| for that case. --- docs/index.bs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 5c0c3a13..5386a3cf 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3264,7 +3264,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |raceFetchController| be null. 1. Let |raceResponse| be a [=race response=] whose [=race response/value=] is "pending". 1. Let |networkFetchCompleted| be false. - 1. Let |fetchHandlerCompleted| be false. + 1. Let |networkFetchResult| be null. 1. Run the following substeps [=in parallel=], but [=abort when=] |fetchController|'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: @@ -3272,26 +3272,30 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |raceNetworkResult| be a [=race result=] whose [=race result/routed response=] is |raceNetworkRequestResponse| and [=race result/used route=] is {{RouterSourceEnum/"network"}}. 1. [=queue/Enqueue=] |raceNetworkResult| to |queue|. 1. Otherwise, set |raceResponse|'s [=race response/value=] to a [=network error=]. + 1. Set |networkFetchResult| to |raceNetworkRequestResponse|. 1. Set |networkFetchCompleted| to true. 1. [=If aborted=] and |raceFetchController| is not null, then: 1. [=fetch controller/Abort=] |raceFetchController|. 1. Set |raceResponse| to a [=race response=] whose [=race response/value=] is null. + 1. Set |networkFetchCompleted| to true. 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|. 1. If |fetchHandlerResponse| is not null and not a [=network error=], and |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. Let |raceFetchHandlerResult| be a [=race result=] whose [=race result/routed response=] is |fetchHandlerResponse| and [=race result/used route=] is {{RouterSourceEnum/"fetch-event"}}. 1. [=queue/Enqueue=] |raceFetchHandlerResult| to |queue|. - 1. Set |fetchHandlerCompleted| to true. - 1. Wait until any of the following are true: - * |queue| is not empty; or - * both |networkFetchCompleted| and |cacheLookupCompleted| are true. - 1. If |queue| is empty, then: - 1. If |raceResponse|'s [=race response/value=] is a [=/response=], return |raceResponse|'s [=race response/value=]. - 1. If |raceResponse|'s [=race response/value=] is a [=network error=], return a [=network error=]. - 1. Return null. + 1. Wait until |queue| is not empty. 1. Let |result| be the result of [=dequeue=] |queue|. 1. Let |routedResponse| be |result|'s [=race result/routed response=]. + 1. If |routedResponse| is null or a [=network error=], then: + + Note: the [=Create Fetch Event and Dispatch=] return value is queued regardless of its value. Failure response means the raced fetch handler failed. + + 1. Wait until |networkFetchCompleted| is true. + 1. If |networkFetchResult| is null: + 1. Return |timingInfo|. + 1. Set |networkFetchResult|'s [=service worker timing info=] to |timingInfo|. + 1. Return |networkFetchResult|. 1. If |result|'s [=race result/used route=] is {{RouterSourceEnum/"network"}}, then: 1. Set |routedResponse|'s [=service worker timing info=] be set to |timingInfo|. 1. Set |routedResponse|'s [=service worker timing info=]'s [=service worker timing info/worker final router source=] be set to |result|'s [=race result/used route=]. From e2a3f08212fca0ccece97626ccf9e2ee53762360 Mon Sep 17 00:00:00 2001 From: Yoshisato Yanagisawa Date: Thu, 12 Jun 2025 03:34:49 +0000 Subject: [PATCH 09/11] Flag flip if |networkFetchResult| is set. --- docs/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index 5386a3cf..eb9e913a 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3273,7 +3273,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. [=queue/Enqueue=] |raceNetworkResult| to |queue|. 1. Otherwise, set |raceResponse|'s [=race response/value=] to a [=network error=]. 1. Set |networkFetchResult| to |raceNetworkRequestResponse|. - 1. Set |networkFetchCompleted| to true. + 1. Set |networkFetchCompleted| to true. 1. [=If aborted=] and |raceFetchController| is not null, then: 1. [=fetch controller/Abort=] |raceFetchController|. 1. Set |raceResponse| to a [=race response=] whose [=race response/value=] is null. From 5006fff0caeb2a5214f9b7ea0ba3719df2461e22 Mon Sep 17 00:00:00 2001 From: Yoshisato Yanagisawa Date: Thu, 12 Jun 2025 07:12:24 +0000 Subject: [PATCH 10/11] Remove |networkFetchCompleted| and |networkFetchResult| As pointed out by the reviewer, the same algorithm can be realized without |networkFetchCompleted| and |networkFetchResult|. Let me remove them. --- docs/index.bs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index eb9e913a..771ca9dc 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3263,21 +3263,15 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |queue| be an empty [=queue=] of [=race result=]. 1. Let |raceFetchController| be null. 1. Let |raceResponse| be a [=race response=] whose [=race response/value=] is "pending". - 1. Let |networkFetchCompleted| be false. - 1. Let |networkFetchResult| be null. 1. Run the following substeps [=in parallel=], but [=abort when=] |fetchController|'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|'s [=race response/value=] to |raceNetworkRequestResponse|. 1. If |raceNetworkRequestResponse|'s [=response/status=] is [=ok status=], then: - 1. Set |raceResponse|'s [=race response/value=] to |raceNetworkRequestResponse|. 1. Let |raceNetworkResult| be a [=race result=] whose [=race result/routed response=] is |raceNetworkRequestResponse| and [=race result/used route=] is {{RouterSourceEnum/"network"}}. 1. [=queue/Enqueue=] |raceNetworkResult| to |queue|. - 1. Otherwise, set |raceResponse|'s [=race response/value=] to a [=network error=]. - 1. Set |networkFetchResult| to |raceNetworkRequestResponse|. - 1. Set |networkFetchCompleted| to true. 1. [=If aborted=] and |raceFetchController| is not null, then: 1. [=fetch controller/Abort=] |raceFetchController|. 1. Set |raceResponse| to a [=race response=] whose [=race response/value=] is null. - 1. Set |networkFetchCompleted| to true. 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|. @@ -3291,11 +3285,12 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ Note: the [=Create Fetch Event and Dispatch=] return value is queued regardless of its value. Failure response means the raced fetch handler failed. - 1. Wait until |networkFetchCompleted| is true. - 1. If |networkFetchResult| is null: + 1. Wait until |raceResponse|'s [=race response/value=] is not "pending". + 1. Let |fallbackResponse| be |raceResponse|'s [=race response/value=]. + 1. If |fallbackResponse| is null: 1. Return |timingInfo|. - 1. Set |networkFetchResult|'s [=service worker timing info=] to |timingInfo|. - 1. Return |networkFetchResult|. + 1. Set |fallbackResponse|'s [=service worker timing info=] to |timingInfo|. + 1. Return |fallbackResponse|. 1. If |result|'s [=race result/used route=] is {{RouterSourceEnum/"network"}}, then: 1. Set |routedResponse|'s [=service worker timing info=] be set to |timingInfo|. 1. Set |routedResponse|'s [=service worker timing info=]'s [=service worker timing info/worker final router source=] be set to |result|'s [=race result/used route=]. From 51832d82ffb5fd564541b305fe9ce889b3a90452 Mon Sep 17 00:00:00 2001 From: Yoshisato Yanagisawa Date: Thu, 12 Jun 2025 10:25:34 +0000 Subject: [PATCH 11/11] No need to wait for |raceResponse| Since `Create Fetch Event And Dispatch` plumb |raceResponse|'s `value` when it is given, we actually do not need to wait the value. However, I found that `Create Fetch Event And Dispatch` returns [=network error=] without the |timingInfo|, it should be propagated properly. --- docs/index.bs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 771ca9dc..8feebc45 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3281,16 +3281,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Wait until |queue| is not empty. 1. Let |result| be the result of [=dequeue=] |queue|. 1. Let |routedResponse| be |result|'s [=race result/routed response=]. - 1. If |routedResponse| is null or a [=network error=], then: - - Note: the [=Create Fetch Event and Dispatch=] return value is queued regardless of its value. Failure response means the raced fetch handler failed. - - 1. Wait until |raceResponse|'s [=race response/value=] is not "pending". - 1. Let |fallbackResponse| be |raceResponse|'s [=race response/value=]. - 1. If |fallbackResponse| is null: - 1. Return |timingInfo|. - 1. Set |fallbackResponse|'s [=service worker timing info=] to |timingInfo|. - 1. Return |fallbackResponse|. + 1. If |routedResponse| is null: + 1. Return |timingInfo|. 1. If |result|'s [=race result/used route=] is {{RouterSourceEnum/"network"}}, then: 1. Set |routedResponse|'s [=service worker timing info=] be set to |timingInfo|. 1. Set |routedResponse|'s [=service worker timing info=]'s [=service worker timing info/worker final router source=] be set to |result|'s [=race result/used route=]. @@ -3349,6 +3341,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |eventHandled| be null. 1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. + 1. Let |networkError| be a [=network error=]. + 1. If |raceResponse| is not null: + 1. Set |networkError|'s [=response/service worker timing info=] to |timingInfo|. 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=]. @@ -3408,15 +3403,15 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 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|. - 2. Return a [=network error=]. + 2. Return |networkError|. 1. If |eventHandled| is not null, then [=resolve=] |eventHandled|. - 1. If |raceResponse|'s [=race response/value=] is not null, then: + 1. If |raceResponse| is not null, and |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 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|. - 2. Return a [=network error=]. + 2. Return |networkError|. 1. If |eventHandled| is not null, then [=resolve=] |eventHandled|. 1. Return |response|.