From 778bf3bc84d9a348d94795f0b4a8aa4d5400d3fc Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Tue, 15 Apr 2025 22:31:00 -0700 Subject: [PATCH 1/6] add race-network-and-cache --- docs/index.bs | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 472b2cd4..957fe6fa 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1093,7 +1093,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 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=]. - 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. + A race response is a [=struct=] used to contain the network response when {{RouterSourceEnum/"race-network-and-fetch-handler"}} or {{RouterSourceEnum/"race-network-and-cache"}} 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=]. @@ -1591,6 +1591,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ dictionary RouterSourceDict { DOMString cacheName; + DOMString raceNetworkAndCacheCacheName; }; enum RunningStatus { "running", "not-running" }; @@ -1598,7 +1599,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" }; @@ -3258,6 +3260,38 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. 1. Wait until |queue| is not empty. 1. Return the result of [=dequeue=] |queue|. + 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, and |request|'s [=request/method=] is `GET`, then: + 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. + 1. Let |queue| be an empty [=queue=] of [=/response=]. + 1. Let |raceFetchController| be null. + 1. Let |raceResponse| be a [=race response=] whose [=race response/value=] is `pending`. + 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: + 1. Set |raceResponse|'s [=race response/value=] to |raceNetworkRequestResponse|. + 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. If |raceFetchController|'s [=fetch controller/state=] is not "terminated", [=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=]: + 1. [=map/For each=] |cacheName| → |cache| of the |registration|'s [=service worker registration/storage key=]'s [=name to cache map=]: + 1. If |source|["{{RouterSourceDict/raceNetworkAndCacheCacheName}}"] [=map/exists=] and |source|["{{RouterSourceDict/raceNetworkAndCacheCacheName}}"] [=string/is=] not |cacheName|, [=continue=]. + 1. Let |requestResponses| be the result of running [=Query Cache=] with |request|, a new {{CacheQueryOptions}}, and |cache|. + 1. Let |globalObject| be null. + 1. If |requestResponses| is not an empty [=list=], then: + 1. Let |requestResponse| be the first element of |requestResponses|. + 1. Let |response| be |requestResponse|'s response. + 1. If |response|'s [=response/type=] is "`opaque`", and |globalObject| is null: + 1. Set |globalObject| to the result of running [=Setup ServiceWorkerGlobalScope=] with |activeWorker|. + 1. If |globalObject| is null, [=continue=]. + 1. If |response|'s [=response/type=] is "`opaque`", and [=cross-origin resource policy check=] with |globalObject|'s [=environment settings object/origin=], |globalObject|, "", and |response|'s [=filtered response/internal response=] returns blocked, then [=continue=]. + 1. [=queue/Enqueue=] |response| to |queue|. + 1. If |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. + 1. Wait until |queue| is not empty. + 1. If |queue| is empty, return null. + 1. Return the result of [=dequeue=] |queue|. 1. Assert: |source| is "{{RouterSourceEnum/fetch-event}}" 1. If |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: From 50af98bc5ecd428d39fe8b212544ebd560ce9506 Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Tue, 15 Apr 2025 22:41:42 -0700 Subject: [PATCH 2/6] minor format fixes --- docs/index.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 957fe6fa..0d61767f 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3260,12 +3260,12 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. [=queue/Enqueue=] |fetchHandlerResponse| to |queue|. 1. Wait until |queue| is not empty. 1. Return the result of [=dequeue=] |queue|. - 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, and |request|'s [=request/method=] is `GET`, then: + 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, and |request|'s [=request/method=] is \`GET\`, then: 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. - 1. Let |raceResponse| be a [=race response=] whose [=race response/value=] is `pending`. - 1. Run the following substeps [=in parallel=], but [=abort when=] |fetchController|'s [=fetch controller/state=] is `terminated` or `aborted`: + 1. Let |raceResponse| be a [=race response=] whose [=race response/value=] is "pending". + 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: 1. Set |raceResponse|'s [=race response/value=] to |raceNetworkRequestResponse|. From 5b14fcd7e90fd43de5d3a39dedc5373c44c93dcf Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Wed, 16 Apr 2025 17:25:01 -0700 Subject: [PATCH 3/6] update failure cases --- docs/index.bs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 0d61767f..388f67e8 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3244,12 +3244,15 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Let |queue| be an empty [=queue=] of [=/response=]. 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: 1. Set |raceResponse|'s [=race response/value=] to |raceNetworkRequestResponse|. 1. [=queue/Enqueue=] |raceNetworkRequestResponse| 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. @@ -3258,19 +3261,24 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 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. + 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. Return the result of [=dequeue=] |queue|. 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, and |request|'s [=request/method=] is \`GET\`, then: 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. 1. Let |queue| be an empty [=queue=] of [=/response=]. 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 |cacheLookupCompleted| 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: 1. Set |raceResponse|'s [=race response/value=] to |raceNetworkRequestResponse|. 1. [=queue/Enqueue=] |raceNetworkRequestResponse| 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. If |raceFetchController|'s [=fetch controller/state=] is not "terminated", [=fetch controller/abort=] |raceFetchController|. 1. Set |raceResponse| to a [=race response=] whose [=race response/value=] is null. @@ -3289,7 +3297,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |response|'s [=response/type=] is "`opaque`", and [=cross-origin resource policy check=] with |globalObject|'s [=environment settings object/origin=], |globalObject|, "", and |response|'s [=filtered response/internal response=] returns blocked, then [=continue=]. 1. [=queue/Enqueue=] |response| to |queue|. 1. If |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. - 1. Wait until |queue| is not empty. + 1. Set |cacheLookupCompleted| to true. + 1. Wait until |queue| is not empty or (|networkFetchCompleted| is true and |cacheLookupCompleted| is true). 1. If |queue| is empty, return null. 1. Return the result of [=dequeue=] |queue|. 1. Assert: |source| is "{{RouterSourceEnum/fetch-event}}" From b69c7da68c454503ed322513ed35aebc62d2f7da Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Sun, 20 Apr 2025 08:21:11 -0700 Subject: [PATCH 4/6] Follow spec format --- docs/index.bs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 388f67e8..1973e17b 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3256,13 +3256,16 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 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. [=queue/Enqueue=] |fetchHandlerResponse| 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 |fetchHandlerCompleted| are true. 1. If |queue| is empty, return null. 1. Return the result of [=dequeue=] |queue|. 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, and |request|'s [=request/method=] is \`GET\`, then: @@ -3282,6 +3285,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. [=If aborted=] and |raceFetchController| is not null, then: 1. If |raceFetchController|'s [=fetch controller/state=] is not "terminated", [=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. [=map/For each=] |cacheName| → |cache| of the |registration|'s [=service worker registration/storage key=]'s [=name to cache map=]: @@ -3298,7 +3302,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. [=queue/Enqueue=] |response| to |queue|. 1. If |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. Set |cacheLookupCompleted| to true. - 1. Wait until |queue| is not empty or (|networkFetchCompleted| is true and |cacheLookupCompleted| 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. Return the result of [=dequeue=] |queue|. 1. Assert: |source| is "{{RouterSourceEnum/fetch-event}}" From 8b8c331c7831c627a8001aac125abeed931cd005 Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Sun, 20 Apr 2025 09:24:04 -0700 Subject: [PATCH 5/6] use helper algorithm --- docs/index.bs | 69 ++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 1973e17b..f1cff253 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3222,23 +3222,9 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Return null. 1. Else if |source| is {{RouterSourceEnum/"cache"}}, or |source|["{{RouterSourceDict/cacheName}}"] [=map/exists=], then: 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. - 1. [=map/For each=] |cacheName| → |cache| of the |registration|'s [=service worker registration/storage key=]'s [=name to cache map=]. - 1. If |source|["{{RouterSourceDict/cacheName}}"] [=map/exists=] and |source|["{{RouterSourceDict/cacheName}}"] [=string/is=] not |cacheName|, [=continue=]. - 1. Let |requestResponses| be the result of running [=Query Cache=] with |request|, a new {{CacheQueryOptions}}, and |cache|. - 1. If |requestResponses| is an empty [=list=], return null. - 1. Else: - 1. Let |requestResponse| be the first element of |requestResponses|. - 1. Let |response| be |requestResponse|'s response. - 1. Let |globalObject| be |activeWorker|'s [=service worker/global object=]. - 1. If |globalObject| is null: - 1. Set |globalObject| to the result of running [=Setup ServiceWorkerGlobalScope=] with |activeWorker|. - 1. If |globalObject| is null, return null. - - Note: This only creates a ServiceWorkerGlobalScope because CORS checks require that. It is not expected that implementations will actually create a ServiceWorkerGlobalScope here. - - 1. If |response|'s [=response/type=] is "`opaque`", and [=cross-origin resource policy check=] with |globalObject|'s [=environment settings object/origin=], |globalObject|, "", and |response|'s [=filtered response/internal response=] returns blocked, then return null. - 1. Return |response|. - 1. Return null. + 1. Let |response| be the result of running [=Query Static Router Cache for Response=] with |request|, |source|, "{{RouterSourceDict/cacheName}}", and |registration|. + 1. If |response| is null, return null. + 1. Return |response|. 1. Else if |source| is {{RouterSourceEnum/"race-network-and-fetch-handler"}}, and |request|'s [=request/method=] is \`GET\` then: 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. 1. Let |queue| be an empty [=queue=] of [=/response=]. @@ -3268,7 +3254,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Both |networkFetchCompleted| and |fetchHandlerCompleted| are true. 1. If |queue| is empty, return null. 1. Return the result of [=dequeue=] |queue|. - 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, and |request|'s [=request/method=] is \`GET\`, then: + 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, or |source|["{{RouterSourceDict/raceNetworkAndCacheCacheName}}"] [=map/exists=], and |request|'s [=request/method=] is \`GET\`, then: 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. 1. Let |queue| be an empty [=queue=] of [=/response=]. 1. Let |raceFetchController| be null. @@ -3288,19 +3274,10 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. Set |networkFetchCompleted| to true. 1. Resolve |preloadResponse| with undefined. 1. Run the following substeps [=in parallel=]: - 1. [=map/For each=] |cacheName| → |cache| of the |registration|'s [=service worker registration/storage key=]'s [=name to cache map=]: - 1. If |source|["{{RouterSourceDict/raceNetworkAndCacheCacheName}}"] [=map/exists=] and |source|["{{RouterSourceDict/raceNetworkAndCacheCacheName}}"] [=string/is=] not |cacheName|, [=continue=]. - 1. Let |requestResponses| be the result of running [=Query Cache=] with |request|, a new {{CacheQueryOptions}}, and |cache|. - 1. Let |globalObject| be null. - 1. If |requestResponses| is not an empty [=list=], then: - 1. Let |requestResponse| be the first element of |requestResponses|. - 1. Let |response| be |requestResponse|'s response. - 1. If |response|'s [=response/type=] is "`opaque`", and |globalObject| is null: - 1. Set |globalObject| to the result of running [=Setup ServiceWorkerGlobalScope=] with |activeWorker|. - 1. If |globalObject| is null, [=continue=]. - 1. If |response|'s [=response/type=] is "`opaque`", and [=cross-origin resource policy check=] with |globalObject|'s [=environment settings object/origin=], |globalObject|, "", and |response|'s [=filtered response/internal response=] returns blocked, then [=continue=]. - 1. [=queue/Enqueue=] |response| to |queue|. - 1. If |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. + 1. Let |response| be the result of running [=Query Static Router Cache for Response=] with |request|, |source|, "{{RouterSourceDict/raceNetworkAndCacheCacheName}}", and |registration|. + 1. If |response| is not null: + 1. [=queue/Enqueue=] |response| to |queue|. + 1. If |raceFetchController| is not null, [=fetch controller/abort=] |raceFetchController|. 1. Set |cacheLookupCompleted| to true. 1. Wait until any of the following are true: 1. |queue| is not empty. @@ -4146,6 +4123,36 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/ 1. If |entry|'s [=race response/value=] is [=/response=], return |entry|'s [=race response/value=]. 1. Return null. + +
+

Query Static Router Cache for Response

+ + : Input + :: |request|, a [=/request=] + :: |source|, a [=map=] + :: |cacheNameKey|, a [=string=] + :: |registration|, a [=/service worker registration=] + : Output + :: a [=/response=] or null + + 1. [=map/For each=] |cacheName| → |cache| of the |registration|'s [=service worker registration/storage key=]'s [=name to cache map=]. + 1. If |source|[|cacheNameKey|] [=map/exists=] and |source|[|cacheNameKey|] [=string/is=] not |cacheName|, [=continue=]. + 1. Let |requestResponses| be the result of running [=Query Cache=] with |request|, a new {{CacheQueryOptions}}, and |cache|. + 1. If |requestResponses| is an empty [=list=], return null. + 1. Else: + 1. Let |requestResponse| be the first element of |requestResponses|. + 1. Let |response| be |requestResponse|'s response. + 1. Let |globalObject| be |activeWorker|'s [=service worker/global object=]. + 1. If |globalObject| is null: + 1. Set |globalObject| to the result of running [=Setup ServiceWorkerGlobalScope=] with |activeWorker|. + 1. If |globalObject| is null, return null. + + Note: This only creates a ServiceWorkerGlobalScope because CORS checks require that. It is not expected that implementations will actually create a ServiceWorkerGlobalScope here. + + 1. If |response|'s [=response/type=] is "`opaque`", and [=cross-origin resource policy check=] with |globalObject|'s [=environment settings object/origin=], |globalObject|, "", and |response|'s [=filtered response/internal response=] returns blocked, then return null. + 1. Return |response|. + 1. Return null. +
From 3305a7f085dbc67b57576090c18b6a5f44cea439 Mon Sep 17 00:00:00 2001 From: Monica Chintala Date: Mon, 21 Apr 2025 23:07:40 -0700 Subject: [PATCH 6/6] use |raceResponse| when empty --- docs/index.bs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index f1cff253..d9309be6 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3252,7 +3252,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 |fetchHandlerCompleted| 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. Return the result of [=dequeue=] |queue|. 1. If |source| is {{RouterSourceEnum/"race-network-and-cache"}}, or |source|["{{RouterSourceDict/raceNetworkAndCacheCacheName}}"] [=map/exists=], and |request|'s [=request/method=] is \`GET\`, then: 1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|. @@ -3282,7 +3285,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. Return the result of [=dequeue=] |queue|. 1. Assert: |source| is "{{RouterSourceEnum/fetch-event}}" 1. If |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: