Skip to content

Commit 4931734

Browse files
authored
Don't fail update upon error fetching the incumbent worker's import s… (#1377)
* Don't fail update upon error fetching the incumbent worker's import scripts. To include imported scripts in the byte-for-byte comparison, the Update algorithm fetches the incumbent worker's scripts in order to detect if there is a difference. But it would abort the update upon MIME type error if fetching the script failed. This is undesirable because the new worker might not use these scripts at all, e.g., the scripts may have legitimately been removed from the server. I considered setting the Updated flag on failure, but it turns out Firefox treats the failure as "no change" and Chrome's WIP implementation was also doing that. The consensus at #1374 is to just consider network errors to be "no change", so do that.
1 parent 77cab40 commit 4931734

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

docs/index.bs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
163163

164164
A [=/service worker=] has an associated <dfn export id="dfn-script-resource-map">script resource map</dfn> which is an <a>ordered map</a> where the keys are [=/URLs=] and the values are [=/responses=].
165165

166+
A [=/service worker=] has an associated <dfn export id="dfn-set-of-used-scripts">set of used scripts</dfn> (a [=ordered set|set=]) whose [=list/item=] is a [=/URL=]. It is initially a new [=ordered set|set=].
167+
168+
Note: The [=set of used scripts=] is only used to prune unused resources from a new worker's map after installation, that were populated based on the old worker's map during the update check.
169+
166170
A [=/service worker=] has an associated <dfn export id="dfn-skip-waiting-flag">skip waiting flag</dfn>. Unless stated otherwise it is unset.
167171

168172
A [=/service worker=] has an associated <dfn export id="dfn-classic-scripts-imported-flag">classic scripts imported flag</dfn>. It is initially unset.
169173

170-
A [=/service worker=] has an associated <dfn export id="dfn-set-of-event-types-to-handle">set of event types to handle</dfn> (a [=ordered set|set=]) whose [=list/item=] is an <a>event listener</a>'s event type. It is initially an empty set.
174+
A [=/service worker=] has an associated <dfn export id="dfn-set-of-event-types-to-handle">set of event types to handle</dfn> (a [=ordered set|set=]) whose [=list/item=] is an <a>event listener</a>'s event type. It is initially a new [=ordered set|set=].
171175

172-
A [=/service worker=] has an associated <dfn export id="dfn-set-of-extended-events">set of extended events</dfn> (a [=ordered set|set=]) whose [=list/item=] is an {{ExtendableEvent}}. It is initially an empty set.
176+
A [=/service worker=] has an associated <dfn export id="dfn-set-of-extended-events">set of extended events</dfn> (a [=ordered set|set=]) whose [=list/item=] is an {{ExtendableEvent}}. It is initially a new [=ordered set|set=].
173177

174178
<section>
175179
<h4 id="service-worker-lifetime">Lifetime</h4>
@@ -2063,8 +2067,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
20632067
When the <dfn method for="ServiceWorkerGlobalScope" id="importscripts-method"><code>importScripts(|urls|)</code></dfn> method is called on a {{ServiceWorkerGlobalScope}} object, the user agent *must* <a>import scripts into worker global scope</a>, given this {{ServiceWorkerGlobalScope}} object and |urls|, and with the following steps to [=fetching scripts/perform the fetch=] given the [=/request=] |request|:
20642068

20652069
1. Let |serviceWorker| be |request|'s [=request/client=]'s [=environment settings object/global object=]'s [=ServiceWorkerGlobalScope/service worker=].
2066-
1. If |serviceWorker|'s [=script resource map=][|request|'s [=request/url=]] [=map/exists=], return the [=map/entry=]'s [=map/value=].
2067-
1. If |serviceWorker|'s [=state=] is not *parsed* or *installing*, return a [=network error=].
2070+
1. Let |map| be |serviceWorker|'s [=script resource map=].
2071+
1. Let |url| be |request|'s [=request/url=].
2072+
1. If |serviceWorker|'s [=state=] is not *parsed* or *installing*:
2073+
1. Return |map|[|url|] if it [=map/exists=] and a [=network error=] otherwise.
2074+
1. If |map|[|url|] [=map/exists=]:
2075+
1. [=set/Append=] |url| to |serviceWorker|'s [=set of used scripts=].
2076+
1. Return |map|[|url|].
20682077
1. Let |registration| be |serviceWorker|'s [=containing service worker registration=].
20692078
1. Set |request|'s [=service-workers mode=] to "`none`".
20702079
1. Set |request|'s [=request/cache mode=] to "`no-cache`" if any of the following are true:
@@ -2074,7 +2083,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
20742083
1. Let |response| be the result of [=fetch|fetching=] |request|.
20752084
1. If |response|’s [=response/cache state=] is not "`local`", set |registration|’s [=service worker registration/last update check time=] to the current time.
20762085
1. If |response|'s [=unsafe response=] is a [=bad import script response=], then return a [=network error=].
2077-
1. [=map/Set=] |serviceWorker|'s [=script resource map=][|request|'s [=request/url=]] to |response|.
2086+
1. [=map/Set=] |map|[|url|] to |response|.
2087+
1. [=set/Append=] |url| to |serviceWorker|'s [=set of used scripts=].
20782088
1. Set |serviceWorker|'s [=classic scripts imported flag=].
20792089
1. Return |response|.
20802090
</section>
@@ -2404,7 +2414,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
24042414
1. Invoke [=Reject Job Promise=] with |job| and `TypeError`.
24052415
1. Invoke <a>Finish Job</a> with |job| and abort these steps.
24062416
1. Let |newestWorker| be the result of running <a>Get Newest Worker</a> algorithm passing |registration| as the argument.
2407-
1. If |job|'s <a>job type</a> is *update*, and |newestWorker|'s [=service worker/script url=] does not [=url/equal=] |job|'s [=job/script url=], then:
2417+
1. If |job|'s <a>job type</a> is *update*, and |newestWorker| is not null and its [=service worker/script url=] does not [=url/equal=] |job|'s [=job/script url=], then:
24082418
1. Invoke [=Reject Job Promise=] with |job| and `TypeError`.
24092419
1. Invoke <a>Finish Job</a> with |job| and abort these steps.
24102420
1. Let |httpsState| be "<code>none</code>".
@@ -2458,9 +2468,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
24582468
1. Else:
24592469
1. Invoke [=Reject Job Promise=] with |job| and "{{SecurityError}}" {{DOMException}}.
24602470
1. Asynchronously complete these steps with a <a>network error</a>.
2461-
1. Set |updatedResourceMap|[|request|'s [=request/url=]] to |response|.
2471+
1. Let |url| be |request|'s [=request/url=].
2472+
1. Set |updatedResourceMap|[|url|] to |response|.
24622473
1. If |response|'s [=response/cache state=] is not "`local`", set |registration|'s [=last update check time=] to the current time.
2463-
1. If |newestWorker| is null, or |newestWorker|'s [=script resource map=][|request|'s [=request/url=]]'s [=response/body=] is not byte-for-byte identical with |response|'s [=response/body=], set |hasUpdatedResources| to true.
2474+
1. Let |map| be |newestWorker|'s [=script resource map=] if |newestWorker| is not null, and null otherwise.
2475+
1. If |map| is null or |map|[|url|]'s [=response/body=] is not byte-for-byte identical with |response|'s [=response/body=], set |hasUpdatedResources| to true.
24642476
1. Else if |newestWorker|'s [=classic scripts imported flag=] is set, then:
24652477

24662478
Note: The following checks to see if an imported script has been updated, since the main script has not changed.
@@ -2476,7 +2488,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
24762488
1. Set |updatedResourceMap|[|importRequest|'s [=request/url=]] to |fetchedResponse|.
24772489
1. Set |fetchedResponse| to |fetchedResponse|'s [=unsafe response=].
24782490
1. If |fetchedResponse|'s [=response/cache state=] is not "`local`", set |registration|’s [=last update check time=] to the current time.
2479-
1. If |fetchedResponse| is a [=bad import script response=], then asynchronously complete these steps with a [=network error=].
2491+
1. If |fetchedResponse| is a [=bad import script response=], continue.
2492+
2493+
Note: Bad responses for <a>importScripts()</a> are ignored for the purpose of the byte-to-byte check. Only good responses for the incumbent worker and good responses for the potential update worker are considered. See <a href="https://github.com/w3c/ServiceWorker/issues/1374">issue #1374</a> for some rationale.
2494+
24802495
1. If |fetchedResponse|'s [=response/body=] is not byte-for-byte identical with |storedResponse|'s [=unsafe response=]'s [=response/body=], set |hasUpdatedResources| to true.
24812496

24822497
Note: The control does not break the loop in this step to continue with all the imported scripts to populate the cache.
@@ -2496,9 +2511,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
24962511
1. Invoke [=Resolve Job Promise=] with |job| and |registration|.
24972512
1. Invoke [=Finish Job=] with |job| and abort these steps.
24982513
1. Let |worker| be a new [=/service worker=].
2499-
1. Set |worker|'s [=service worker/script url=] to |job|'s [=job/script url=], |worker|'s <a>script resource</a> to |script|, and |worker|'s [=service worker/type=] to |job|'s <a>worker type</a>.
2500-
1. [=map/For each=] |url| → |response| of |updatedResourceMap|:
2501-
1. Set |worker|'s [=script resource map=][|url|] to |response|.
2514+
1. Set |worker|'s [=service worker/script url=] to |job|'s [=job/script url=], |worker|'s [=script resource=] to |script|, |worker|'s [=service worker/type=] to |job|'s [=worker type=], and |worker|'s [=script resource map=] to |updatedResourceMap|.
2515+
1. Append |url| to |worker|'s [=set of used scripts=].
25022516
1. Set |worker|'s <a>script resource</a>'s <a>HTTPS state</a> to |httpsState|.
25032517
1. Set |worker|'s <a>script resource</a>'s [=script resource/referrer policy=] to |referrerPolicy|.
25042518
1. Invoke [=Run Service Worker=] algorithm given |worker|, with the *force bypass cache for importscripts flag* set if |job|'s [=job/force bypass cache flag=] is set, and with the following callback steps given |evaluationStatus|:
@@ -2567,6 +2581,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
25672581
1. Run the <a>Update Registration State</a> algorithm passing |registration|, "<code>installing</code>" and null as the arguments.
25682582
1. If |newestWorker| is null, invoke <a>Clear Registration</a> algorithm passing |registration| as its argument.
25692583
1. Invoke <a>Finish Job</a> with |job| and abort these steps.
2584+
1. Let |map| be |registration|'s [=installing worker=]'s [=script resource map=].
2585+
1. Let |usedSet| be |registration|'s [=installing worker=]'s [=set of used scripts=].
2586+
1. [=map/For each=] |url| of |map|:
2587+
1. If |usedSet| does not [=list/contain=] |url|, then [=map/remove=] |map|[|url|].
25702588
1. If |registration|'s <a>waiting worker</a> is not null, then:
25712589
1. [=Terminate Service Worker|Terminate=] |registration|'s [=waiting worker=].
25722590
1. Run the [=Update Worker State=] algorithm passing |registration|'s [=waiting worker=] and *redundant* as the arguments.

0 commit comments

Comments
 (0)