diff --git a/docs/index.bs b/docs/index.bs
index a109ed3c..b0f5e3f3 100644
--- a/docs/index.bs
+++ b/docs/index.bs
@@ -632,7 +632,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
1. If |registration| is not null, and |registration|'s [=active worker=] is not null, [=queue a task=] on |readyPromise|'s [=relevant settings object=]'s [=responsible event loop=], using the [=DOM manipulation task source=], to resolve |readyPromise| with the {{ServiceWorkerRegistration}} object that represents |registration| in |readyPromise|'s [=relevant Realm=].
1. Return |readyPromise|.
- Note: The returned [=ServiceWorkerContainer/ready promise=] will never reject. If it does not resolve in this algorithm, it will eventually resolve when a matching [=/service worker registration=] is registered and its [=active worker=] is set. (See the relevant [Activate algorithm step](#activate-resolve-ready-step).)
+ Note: The returned [=ServiceWorkerContainer/ready promise=] will never reject. If it does not resolve in this algorithm, it will eventually resolve when a matching [=/service worker registration=] is registered and its [=active worker=] is set. (See the relevant [Update State step](#update-state-resolve-ready-step).)
installing
" and |worker| as the arguments.
- 1. Run the Update Worker State algorithm passing |registration|'s installing worker and *installing* as the arguments.
+ 1. Invoke [=Update State=] with «[ |worker| → *installing* ]».
1. Assert: |job|'s [=job/job promise=] is not null.
1. Invoke [=Resolve Job Promise=] with |job| and |registration|.
- 1. Let |settingsObjects| be all [=environment settings objects=] whose [=environment settings object/origin=] is |registration|'s [=service worker registration/scope url=]'s origin.
- 1. For each |settingsObject| of |settingsObjects|, [=queue a task=] on |settingsObject|'s [=responsible event loop=] in the [=DOM manipulation task source=] to run the following steps:
- 1. Let |registrationObjects| be every {{ServiceWorkerRegistration}} object in |settingsObject|'s [=environment settings object/realm execution context=], whose [=ServiceWorkerRegistration/service worker registration=] is |registration|.
- 1. For each |registrationObject| of |registrationObjects|, [=fire an event=] on |registrationObject| named `updatefound`.
- 1. Let |installingWorker| be |registration|'s installing worker.
+ 1. Let |installingWorker| be |registration|'s [=installing worker=].
1. If the result of running the [=Should Skip Event=] algorithm with |installingWorker| and "install" is false, then:
- 1. Invoke Run Service Worker algorithm given |installingWorker|, and with the *force bypass cache for importscripts flag* set if |job|'s [=job/force bypass cache flag=] is set.
- 1. Queue a task |task| to run the following substeps:
- 1. Let |e| be the result of creating an event with {{ExtendableEvent}}.
+ 1. Invoke [=Run Service Worker=] algorithm given |installingWorker|, and with the *force bypass cache for importscripts flag* set if |job|'s [=job/force bypass cache flag=] is set.
+ 1. [=Queue a task=] |task| to run the following substeps:
+ 1. Let |e| be the result of [=creating an event=] with {{ExtendableEvent}}.
1. Initialize |e|’s {{Event/type}} attribute to {{install!!event}}.
- 1. Dispatch |e| at |installingWorker|'s [=service worker/global object=].
- 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel:
+ 1. [=Dispatch=] |e| at |installingWorker|'s [=service worker/global object=].
+ 1. *WaitForAsynchronousExtensions*: Run the following substeps [=in parallel=]:
1. Wait until |e| is not [=ExtendableEvent/active=].
1. If |e|'s [=ExtendableEvent/timed out flag=] is set, or the result of [=waiting for all=] of |e|'s [=extend lifetime promises=] rejected, set |installFailed| to true.
- If |task| is discarded or the script has been aborted by the termination of |installingWorker|, set |installFailed| to true.
+ If |task| is discarded or the script has been aborted by the [=Terminate Service Worker|termination=] of |installingWorker|, set |installFailed| to true.
1. Wait for |task| to have executed or been discarded.
1. Wait for the step labeled *WaitForAsynchronousExtensions* to complete.
1. If |installFailed| is true, then:
- 1. Run the Update Worker State algorithm passing |registration|'s [=installing worker=] and *redundant* as the arguments.
- 1. Run the Update Registration State algorithm passing |registration|, "installing
" and null as the arguments.
- 1. If |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument.
- 1. Invoke Finish Job with |job| and abort these steps.
- 1. Let |map| be |registration|'s [=installing worker=]'s [=script resource map=].
- 1. Let |usedSet| be |registration|'s [=installing worker=]'s [=set of used scripts=].
+ 1. Invoke [=Update State=] with «[ |worker| → *redundant* ]».
+ 1. If |newestWorker| is null, invoke [=Clear Registration=] algorithm passing |registration| as its argument.
+ 1. Invoke [=Finish Job=] with |job| and abort these steps.
+ 1. Let |map| be |worker|'s [=script resource map=].
+ 1. Let |usedSet| be |worker|'s [=set of used scripts=].
1. [=map/For each=] |url| of |map|:
1. If |usedSet| does not [=list/contain=] |url|, then [=map/remove=] |map|[|url|].
- 1. If |registration|'s waiting worker is not null, then:
- 1. [=Terminate Service Worker|Terminate=] |registration|'s [=waiting worker=].
- 1. Run the [=Update Worker State=] algorithm passing |registration|'s [=waiting worker=] and *redundant* as the arguments.
- 1. Run the Update Registration State algorithm passing |registration|, "waiting
" and |registration|'s installing worker as the arguments.
- 1. Run the Update Registration State algorithm passing |registration|, "installing
" and null as the arguments.
- 1. Run the Update Worker State algorithm passing |registration|'s waiting worker and *installed* as the arguments.
- 1. Invoke Finish Job with |job|.
- 1. Wait for all the tasks queued by Update Worker State invoked in this algorithm to have executed.
+ 1. Let |newState| be «[ |worker| → *installed* ]».
+ 1. If |registration|'s [=waiting worker=] is not null, then:
+ 1. Set |newState|[|registration|'s [=waiting worker=]] to *redundant*.
+ 1. Invoke [=Update State=] with |newState|.
+ 1. Invoke [=Finish Job=] with |job|.
+ 1. Wait for all the [=tasks=] [=queue a task|queued=] by [=Update State=] invoked in this algorithm to have executed.
1. Invoke [=Try Activate=] with |registration|.
Note: If [=Try Activate=] does not trigger [=Activate=] here, [=Activate=] is tried again when the last client controlled by the existing [=active worker=] is [=Handle Service Worker Client Unload|unloaded=], {{ServiceWorkerGlobalScope/skipWaiting()}} is asynchronously called, or the [=extend lifetime promises=] for the existing [=active worker=] settle.
@@ -2658,28 +2651,20 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
:: None
1. If |registration|'s waiting worker is null, abort these steps.
+ 1. Let |newState| be «[ |registration|'s [=waiting worker=] → *activating* ]».
1. If |registration|'s [=active worker=] is not null, then:
- 1. [=Terminate Service Worker|Terminate=] |registration|'s [=active worker=].
- 1. Run the [=Update Worker State=] algorithm passing |registration|'s [=active worker=] and *redundant* as the arguments.
- 1. Run the Update Registration State algorithm passing |registration|, "active
" and |registration|'s waiting worker as the arguments.
- 1. Run the Update Registration State algorithm passing |registration|, "waiting
" and null as the arguments.
- 1. Run the Update Worker State algorithm passing |registration|'s active worker and *activating* as the arguments.
+ 1. Set |newState|[|registration|'s [=active worker=]] to *redundant*.
+ 1. Invoke [=Update State=] with |newState|.
Note: Once an active worker is activating, neither a runtime script error nor a force termination of the active worker prevents the active worker from getting activated.
1. Let |matchedClients| be a [=list=] of [=/service worker clients=] whose creation URL matches |registration|'s [=service worker registration/scope url=].
- 1. [=list/For each=] |client| of |matchedClients|, [=queue a task=] on |client|'s [=responsible event loop=], using the [=DOM manipulation task source=], to run the following substeps:
- 1. Let |readyPromise| be |client|'s [=environment settings object/global object=]'s {{ServiceWorkerContainer}} object's [=ServiceWorkerContainer/ready promise=].
- 1. If |readyPromise| is pending, resolve |readyPromise| with the {{ServiceWorkerRegistration}} object that represents |registration| in |readyPromise|'s [=relevant Realm=].
1. [=list/For each=] |client| of |matchedClients|:
1. If |client| is a window client, unassociate |client|'s responsible document from its application cache, if it has one.
1. Else if |client| is a shared worker client, unassociate |client|'s [=environment settings object/global object=] from its application cache, if it has one.
Note: Resources will now use the service worker registration instead of the existing application cache.
- 1. For each [=/service worker client=] |client| who is using |registration|:
- 1. Set |client|'s active worker to |registration|'s active worker.
- 1. Invoke Notify Controller Change algorithm with |client| as the argument.
1. Let |activeWorker| be |registration|'s active worker.
1. If the result of running the [=Should Skip Event=] algorithm with |activeWorker| and "activate" is false, then:
1. Invoke Run Service Worker algorithm with |activeWorker| as the argument.
@@ -2690,7 +2675,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
1. *WaitForAsynchronousExtensions*: Wait, [=in parallel=], until |e| is not [=ExtendableEvent/active=].
1. Wait for |task| to have executed or been discarded, or the script to have been aborted by the termination of |activeWorker|.
1. Wait for the step labeled *WaitForAsynchronousExtensions* to complete.
- 1. Run the Update Worker State algorithm passing |registration|'s active worker and *activated* as the arguments.
+ 1. Invoke [=Update State=] with «[ |registration|'s [=active worker=] → *activated* ]».
installing
" and null as the arguments.
- 1. If |registration|'s waiting worker is not null, then:
- 1. [=Terminate Service Worker|Terminate=] |registration|'s [=waiting worker=].
- 1. Run the Update Worker State algorithm passing |registration|'s [=waiting worker=] and *redundant* as the arguments.
- 1. Run the Update Registration State algorithm passing |registration|, "waiting
" and null as the arguments.
- 1. If |registration|'s active worker is not null, then:
- 1. [=Terminate Service Worker|Terminate=] |registration|'s [=active worker=].
- 1. Run the Update Worker State algorithm passing |registration|'s [=active worker=] and *redundant* as the arguments.
- 1. Run the Update Registration State algorithm passing |registration|, "active
" and null as the arguments.
+ 1. Let |newState| be a new [=/map=].
+ 1. If |registration|'s [=installing worker=] is not null, then:
+ 1. Set |newState|[|registration|'s [=installing worker=]] to *redundant*.
+ 1. If |registration|'s [=waiting worker=] is not null, then:
+ 1. Set |newState|[|registration|'s [=waiting worker=]] to *redundant*.
+ 1. If |registration|'s [=active worker=] is not null, then:
+ 1. Set |newState|[|registration|'s [=active worker=]] to *redundant*.
+ 1. Invoke [=Update State=] with |newState|.
installing
", "waiting
", and "active
")
- :: |source|, a [=/service worker=] or null
- : Output
- :: None
-
- 1. Let |registrationObjects| be an array containing all the {{ServiceWorkerRegistration}} objects associated with |registration|.
- 1. If |target| is "installing
", then:
- 1. Set |registration|'s installing worker to |source|.
- 1. For each |registrationObject| in |registrationObjects|:
- 1. Queue a task to set the {{ServiceWorkerRegistration/installing}} attribute of |registrationObject| to the {{ServiceWorker}} object that represents |registration|’s installing worker, or null if |registration|’s installing worker is null.
- 1. Else if |target| is "waiting
", then:
- 1. Set |registration|'s waiting worker to |source|.
- 1. For each |registrationObject| in |registrationObjects|:
- 1. Queue a task to set the {{ServiceWorkerRegistration/waiting}} attribute of |registrationObject| to the {{ServiceWorker}} object that represents |registration|’s waiting worker, or null if |registration|’s waiting worker is null.
- 1. Else if |target| is "active
", then:
- 1. Set |registration|'s [=service worker registration/active worker=] to |source|.
- 1. For each |registrationObject| in |registrationObjects|:
- 1. Queue a task to set the {{ServiceWorkerRegistration/active}} attribute of |registrationObject| to the {{ServiceWorker}} object that represents |registration|’s [=service worker registration/active worker=], or null if |registration|’s [=service worker registration/active worker=] is null.
-
- The task *must* use |registrationObject|'s relevant settings object's responsible event loop and the DOM manipulation task source.
- statechange
at |workerObject|.
-
- The task *must* use |workerObject|'s relevant settings object's responsible event loop and the DOM manipulation task source.
- controllerchange
at the {{ServiceWorkerContainer}} object that |client| is [=ServiceWorkerContainer/service worker client|associated=] with.
-
- The task *must* use |client|'s responsible event loop and the DOM manipulation task source.
+ 1. Let |settingsObjects| be all [=environment settings objects=] whose [=environment settings object/origin=] is |registration|'s [=service worker registration/scope url=]'s origin.
+ 1. For each |settingsObject| of |settingsObjects|, [=queue a task=] on |settingsObject|'s [=responsible event loop=] in the [=DOM manipulation task source=] to run the following steps:
+ 1. Let |changedWorkers| be an empty [=/list=].
+ 1. Let |registrationObjects| be a [=/list=] of every {{ServiceWorkerRegistration}} object in |settingsObject|'s [=environment settings object/realm execution context=], whose [=ServiceWorkerRegistration/service worker registration=] is |registration|.
+ 1. [=map/For each=] |worker| → |state| of |workerUpdates|:
+ 1. Let |workerObject| be the {{ServiceWorker}} that represents |worker| within |settingsObject|'s [=environment settings object/realm execution context=].
+ 1. If |workerObject|'s {{ServiceWorker/state}} is not |state|, then:
+ 1. Set |workerObject|'s {{ServiceWorker/state}} to |state|.
+ 1. If |state| is not *installing*, then [=list/append=] |workerObject| to |changedWorkers|.
+
+ Note: *installing* is the initial script-exposed state, so it doesn't count as a change.
+
+ 1. [=list/For each=] |registrationObject| of |registrationObjects|:
+ 1. Set |registrationObject|'s {{ServiceWorkerRegistration/installing}} to null if |installingWorker| is null, otherwise set it to the {{ServiceWorker}} that represents |installingWorker| within |settingsObject|'s [=environment settings object/realm execution context=].
+ 1. Set |registrationObject|'s {{ServiceWorkerRegistration/waiting}} to null if |waitingWorker| is null, otherwise set it to the {{ServiceWorker}} that represents |waitingWorker| within |settingsObject|'s [=environment settings object/realm execution context=].
+ 1. Set |registrationObject|'s {{ServiceWorkerRegistration/active}} to null if |activeWorker| is null, otherwise set it to the {{ServiceWorker}} that represents |activeWorker| within |settingsObject|'s [=environment settings object/realm execution context=].
+ 1. [=list/For each=] |workerObject| of |changedWorkers|, [=fire an event=] on |workerObject| named `statechange`.
+ 1. If `updateFound` is true, then [=list/for each=] |registrationObject| of |registrationObjects|, [=fire an event=] on |registrationObject| named `updatefound`.
+ 1. If |newActiveWorker| is true:
+ 1. Let |container| be the {{ServiceWorkerContainer}} object within |settingsObject|'s [=environment settings object/realm execution context=].
+ 1. Let |readyPromise| be |container|'s [=ServiceWorkerContainer/ready promise=].
+ 1. If |settingsObject| [=/uses=] |registration|, then:
+ 1. Set |settingsObject|'s [=environment/active service worker=] to |activeWorker|.
+ 1. [=fire an event=] named `controllerchange` on |container|.
+ 1. If the [=Match Service Worker Registration|matching=] [=/service worker registration=] for |settingsObject|'s [=environment/creation URL=] is |registration|, and |readyPromise| is pending, then [=/resolve=] |readyPromise| with a new {{ServiceWorkerRegistration}} object representing |registration| in |readyPromise|'s [=relevant Realm=].