From c3f8ecab48dad6f4596573761aa72c70f54d4610 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 3 Jun 2019 09:56:50 +0100 Subject: [PATCH 1/9] Remove repetition in respondWith --- docs/index.bs | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 8046157c..5812bd6c 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -518,12 +518,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
- Note: The {{ServiceWorkerRegistration/unregister()}} method unregisters the [=/service worker registration=]. It is important to note that the currently controlled [=/service worker client=]'s active service worker's containing service worker registration is effective until all the [=/service worker clients=] (including itself) using this [=/service worker registration=] unload. That is, the {{ServiceWorkerRegistration/unregister()}} method only affects subsequent navigations. + Note: The {{ServiceWorkerRegistration/unregister()}} method unregisters the [=/service worker registration=]. It is important to note that the currently [=controlled=] [=/service worker client=]'s [=active service worker=]'s [=containing service worker registration=] is effective until all the [=/service worker clients=] (including itself) using this [=/service worker registration=] unload. That is, the {{ServiceWorkerRegistration/unregister()}} method only affects subsequent [=navigate|navigations=]. unregister() method *must* run these steps: - 1. Let |promise| be a promise. - 1. Let |job| be the result of running Create Job with *unregister*, the [=service worker registration/scope url=] of the [=ServiceWorkerRegistration/service worker registration=], null, |promise|, and the context object's relevant settings object. + 1. Let |promise| be [=a new promise=]. + 1. Let |job| be the result of running [=Create Job=] with *unregister*, the [=service worker registration/scope url=] of the [=ServiceWorkerRegistration/service worker registration=], null, |promise|, and the context object's relevant settings object. 1. Invoke Schedule Job with |job|. 1. Return |promise|.
@@ -1336,28 +1336,35 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{ExtendableEvent/waitUntil()|event.waitUntil(f)}}

- {{ExtendableEvent/waitUntil()}} method extends the lifetime of the event. + Note: {{ExtendableEvent/waitUntil()}} method extends the lifetime of the event. waitUntil(|f|) method *must* run these steps: - 1. If the {{Event/isTrusted}} attribute is false, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. Let |event| be the [=context object=]. + 1. [=ExtendableEvent/Add lifetime promise=] |f| to |event|. +
+ +
+ To add lifetime promise |promise| (a [=promise=]) to |event| (an {{ExtendableEvent}}), run these steps: - 1. If not [=ExtendableEvent/active=], [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event|'s {{Event/isTrusted}} attribute is false, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event| is not [=ExtendableEvent/active=], [=throw=] an "{{InvalidStateError}}" {{DOMException}}. Note: If no lifetime extension promise has been added in the task that called the event handlers, calling {{ExtendableEvent/waitUntil()}} in subsequent asynchronous tasks will throw. - 1. Add |f| to the [=ExtendableEvent/extend lifetime promises=]. - 1. Increment the [=ExtendableEvent/pending promises count=] by one. + 1. Add |promise| to |event|'s [=ExtendableEvent/extend lifetime promises=]. + 1. Increment |event|'s [=ExtendableEvent/pending promises count=] by one. Note: The [=ExtendableEvent/pending promises count=] is incremented even if the given promise has already been settled. The corresponding count decrement is done in the microtask queued by the reaction to the promise. - 1. Upon [=upon fulfillment|fulfillment=] or [=upon rejection|rejection=] of |f|, [=queue a microtask=] to run these substeps: - 1. Decrement the [=ExtendableEvent/pending promises count=] by one. - 1. Let |registration| be the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. - 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. - 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. + 1. Upon [=upon fulfillment|fulfillment=] or [=upon rejection|rejection=] of |promise|, [=queue a microtask=] to run these substeps: + 1. Decrement |event|'s [=ExtendableEvent/pending promises count=] by one. + 1. If |event|'s [=ExtendableEvent/pending promises count=] is 0, then: + 1. Let |registration| be the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. + 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. + 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. - The user agent *should not* [=terminate service worker|terminate=] a [=/service worker=] if [=Service Worker Has No Pending Events=] returns false for that [=/service worker=]. + The user agent *should not* [=terminate service worker|terminate=] a [=/service worker=] if [=Service Worker Has No Pending Events=] returns false for that [=/service worker=].
[=/Service workers=] and extensions that define event handlers *may* define their own behaviors, allowing the [=ExtendableEvent/extend lifetime promises=] to suggest operation length, and the rejected state of any of the promise in [=ExtendableEvent/extend lifetime promises=] to suggest operation failure. @@ -1435,18 +1442,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe respondWith(|r|) method *must* run these steps: + 1. Let |event| be the [=context object=]. 1. If the dispatch flag is unset, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. 1. If the [=FetchEvent/respond-with entered flag=] is set, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. - 1. Add |r| to the extend lifetime promises. - 1. Increment the [=ExtendableEvent/pending promises count=] by one. - - Note: The [=ExtendableEvent/pending promises count=] is incremented even if the given promise has already been settled. The corresponding count decrement is done in the microtask queued by the reaction to the promise. - - 1. Upon [=upon fulfillment|fulfillment=] or [=upon rejection|rejection=] of |r|, [=queue a microtask=] to run these substeps: - 1. Decrement the [=ExtendableEvent/pending promises count=] by one. - 1. Let |registration| be the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. - 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. - 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. + 1. [=ExtendableEvent/Add lifetime promise=] |r| to |event|. Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil()|event.waitUntil(r)}} is called. From b622281ac3496725c6b68f93828754233c972473 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 3 Jun 2019 13:21:53 +0100 Subject: [PATCH 2/9] Kill resurrection (fixes #1204) --- docs/index.bs | 38 +++++++++++------------ docs/v1/index.bs | 81 ++++++++++++++++++++++++------------------------ 2 files changed, 59 insertions(+), 60 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 5812bd6c..aa037b43 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -210,8 +210,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker registration=] has an associated update via cache mode, which is "`imports`", "`all`", or "`none`". It is initially set to "`imports`". - A [=/service worker registration=] has an associated uninstalling flag. It is initially unset. - A [=/service worker registration=] has one or more task queues that back up the tasks from its active worker's event loop's corresponding [=/task queues=]. (The target task sources for this back up operation are the handle fetch task source and the handle functional event task source.) The user agent dumps the active worker's tasks to the [=/service worker registration=]'s [=service worker registration/task queues=] when the active worker is terminated and re-queues those tasks to the active worker's event loop's corresponding [=/task queues=] when the active worker spins off. Unlike the [=/task queues=] owned by event loops, the [=/service worker registration=]'s [=service worker registration/task queues=] are not processed by any event loops in and of itself. A [=/service worker registration=] has an associated {{NavigationPreloadManager}} object. @@ -220,6 +218,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker registration=] has an associated navigation preload header value, which is a [=byte sequence=]. It is initially set to \`true\`. + A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=]. +

Lifetime

@@ -678,7 +678,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Run the following steps [=in parallel=]: 1. Let |registrations| be a new [=list=]. 1. [=map/For each=] |scope| → |registration| of [=scope to registration map=]: - 1. If the [=url/origin=] of the result of [=URL parser|parsing=] |scope| is the [=same origin|same=] as |client|'s [=environment settings object/origin=], and |registration|'s [=uninstalling flag=] is unset, then [=append=] |registration| to |registrations|. + 1. If the [=url/origin=] of the result of [=URL parser|parsing=] |scope| is the [=same origin|same=] as |client|'s [=environment settings object/origin=], then [=append=] |registration| to |registrations|. 1. [=Queue a task=] on |promise|'s [=relevant settings object=]'s [=responsible event loop=], using the [=DOM manipulation task source=], to run the following steps: 1. Let |registrationObjects| be a new [=list=]. 1. [=list/For each=] |registration| of |registrations|, [=append=] the {{ServiceWorkerRegistration}} object associated with |registration| to |registrationObjects|. @@ -1297,6 +1297,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |client| is not a [=secure context=], [=continue=]. 1. Let |registration| be the result of running Match Service Worker Registration algorithm passing |client|'s creation URL as the argument. 1. If |registration| is not the [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration, [=continue=]. + + Note: |registration| will be null if the [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=] is [=service worker registration/unregistered=]. + 1. If |client|'s active service worker is not the [=ServiceWorkerGlobalScope/service worker=], then: 1. Invoke Handle Service Worker Client Unload with |client| as the argument. 1. Set |client|'s active service worker to [=ServiceWorkerGlobalScope/service worker=]. @@ -1360,8 +1363,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Upon [=upon fulfillment|fulfillment=] or [=upon rejection|rejection=] of |promise|, [=queue a microtask=] to run these substeps: 1. Decrement |event|'s [=ExtendableEvent/pending promises count=] by one. 1. If |event|'s [=ExtendableEvent/pending promises count=] is 0, then: - 1. Let |registration| be the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. - 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. + 1. Let |registration| be the [=current global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. + 1. If |registration| is [=service worker registration/unregistered=], invoke [=Try Clear Registration=] with |registration|. 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. The user agent *should not* [=terminate service worker|terminate=] a [=/service worker=] if [=Service Worker Has No Pending Events=] returns false for that [=/service worker=]. @@ -2434,7 +2437,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Invoke Finish Job with |job| and abort these steps. 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=job/scope url=] as the argument. 1. If |registration| is not null, then: - 1. If |registration|'s uninstalling flag is set, unset it. 1. Let |newestWorker| be the result of running the Get Newest Worker algorithm passing |registration| as the argument. 1. If |newestWorker| is not null, |job|'s [=job/script url=] [=url/equals=] |newestWorker|'s [=service worker/script url=], and |job|'s [=job/update via cache mode=]'s value equals |registration|'s [=service worker registration/update via cache mode=], then: 1. Invoke [=Resolve Job Promise=] with |job| and |registration|. @@ -2453,7 +2455,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: none 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=job/scope url=] as the argument. - 1. If |registration| is null or |registration|'s uninstalling flag is set, then: + 1. If |registration| is null or |registration| is [=service worker registration/unregistered=], then: 1. Invoke [=Reject Job Promise=] with |job| and `TypeError`. 1. Invoke Finish Job with |job| and abort these steps. 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as the argument. @@ -2604,7 +2606,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Run the Update Worker State algorithm passing |registration|'s installing worker and *installing* as the arguments. 1. Assert: |job|'s [=job/job promise=] is not null. 1. Invoke [=Resolve Job Promise=] with |job| and |registration|. - 1. Queue a task to fire an event named updatefound at all the {{ServiceWorkerRegistration}} objects for all the [=/service worker clients=] whose creation URL matches |registration|'s [=service worker registration/scope url=] and all the [=/service workers=] whose containing service worker registration is |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| 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. 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: @@ -2900,7 +2905,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: None - 1. Assert: [=scope to registration map=] contains a value equal to |registration|. 1. Assert: |registration|'s [=active worker=] is not null. 1. Let |activeWorker| be |registration|'s [=active worker=]. 1. If |activeWorker|'s [=set of event types to handle=] does not [=set/contain=] |eventName|, then return and run the following steps [=in parallel=]: @@ -2956,8 +2960,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |registration| be the [=/service worker registration=] used by |client|. 1. If |registration| is null, abort these steps. 1. If any other [=/service worker client=] is using |registration|, abort these steps. - 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. - 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. + 1. If |registration| is [=service worker registration/unregistered=], invoke [=Try Clear Registration=] with |registration|. + 1. Invoke [=Try Activate=] with |registration|.
@@ -3006,7 +3010,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |registration| is null, then: 1. Invoke Resolve Job Promise with |job| and false. 1. Invoke Finish Job with |job| and abort these steps. - 1. Set |registration|'s uninstalling flag. + 1. [=map/Remove=] [=scope to registration map=][|job|'s [=job/scope url=]]. 1. Invoke Resolve Job Promise with |job| and true. 1. Invoke [=Try Clear Registration=] with |registration|. @@ -3052,8 +3056,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 |scopeString| be |registration|'s [=URL serializer|serialized=] [=service worker registration/scope url=]. - 1. [=map/Remove=] scope to registration map[|scopeString|].
@@ -3176,7 +3178,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Set |matchingScope| to the result of parsing |matchingScopeString|. 1. Assert: |matchingScope|'s [=url/origin=] and |clientURL|'s [=url/origin=] are [=same origin=]. 1. Let |registration| be the result of running Get Registration algorithm passing |matchingScope| as the argument. - 1. If |registration| is not null and |registration|'s uninstalling flag is set, return null. 1. Return |registration|.
@@ -3186,15 +3187,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Input :: |scope|, a [=/URL=] : Output - :: |registration|, a [=/service worker registration=] + :: A [=/service worker registration=] 1. Run the following steps atomically. 1. Let |scopeString| be the empty string. 1. If |scope| is not null, set |scopeString| to [=URL serializer|serialized=] |scope| with the *exclude fragment flag* set. - 1. Let |registration| be null. 1. [=map/For each=] |key| → |value| of scope to registration map: - 1. If |scopeString| matches |key|, set |registration| to |value|. - 1. Return |registration|. + 1. If |scopeString| matches |key|, then return |value|. + 1. Return null.
diff --git a/docs/v1/index.bs b/docs/v1/index.bs index b3c7c7f8..95f011f8 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -199,10 +199,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker registration=] has an associated update via cache mode, which is "`imports`", "`all`", or "`none`". It is initially set to "`imports`". - A [=/service worker registration=] has an associated uninstalling flag. It is initially unset. - A [=/service worker registration=] has one or more task queues that back up the tasks from its active worker's event loop's corresponding [=/task queues=]. (The target task sources for this back up operation are the handle fetch task source and the handle functional event task source.) The user agent dumps the active worker's tasks to the [=/service worker registration=]'s [=service worker registration/task queues=] when the active worker is terminated and re-queues those tasks to the active worker's event loop's corresponding [=/task queues=] when the active worker spins off. Unlike the [=/task queues=] owned by event loops, the [=/service worker registration=]'s [=service worker registration/task queues=] are not processed by any event loops in and of itself. + A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=]. +

Lifetime

@@ -484,12 +484,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
- Note: The {{ServiceWorkerRegistration/unregister()}} method unregisters the [=/service worker registration=]. It is important to note that the currently controlled [=/service worker client=]'s active service worker's containing service worker registration is effective until all the [=/service worker clients=] (including itself) using this [=/service worker registration=] unload. That is, the {{ServiceWorkerRegistration/unregister()}} method only affects subsequent navigations. + Note: The {{ServiceWorkerRegistration/unregister()}} method unregisters the [=/service worker registration=]. It is important to note that the currently [=controlled=] [=/service worker client=]'s [=active service worker=]'s [=containing service worker registration=] is effective until all the [=/service worker clients=] (including itself) using this [=/service worker registration=] unload. That is, the {{ServiceWorkerRegistration/unregister()}} method only affects subsequent [=navigate|navigations=]. unregister() method *must* run these steps: - 1. Let |promise| be a promise. - 1. Let |job| be the result of running Create Job with *unregister*, the [=service worker registration/scope url=] of the [=ServiceWorkerRegistration/service worker registration=], null, |promise|, and the context object's relevant settings object. + 1. Let |promise| be [=a new promise=]. + 1. Let |job| be the result of running [=Create Job=] with *unregister*, the [=service worker registration/scope url=] of the [=ServiceWorkerRegistration/service worker registration=], null, |promise|, and the context object's relevant settings object. 1. Invoke Schedule Job with |job|. 1. Return |promise|.
@@ -665,7 +665,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Run the following steps [=in parallel=]: 1. Let |registrations| be a new [=list=]. 1. [=map/For each=] |scope| → |registration| of [=scope to registration map=]: - 1. If the [=url/origin=] of the result of [=URL parser|parsing=] |scope| is the [=same origin|same=] as |client|'s [=environment settings object/origin=], and |registration|'s [=uninstalling flag=] is unset, then [=append=] |registration| to |registrations|. + 1. If the [=url/origin=] of the result of [=URL parser|parsing=] |scope| is the [=same origin|same=] as |client|'s [=environment settings object/origin=], then [=append=] |registration| to |registrations|. 1. [=Queue a task=] on |promise|'s [=relevant settings object=]'s [=responsible event loop=], using the [=DOM manipulation task source=], to run the following steps: 1. Let |registrationObjects| be a new [=list=]. 1. [=list/For each=] |registration| of |registrations|, [=append=] the {{ServiceWorkerRegistration}} object associated with |registration| to |registrationObjects|. @@ -1209,6 +1209,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |client| is not a [=secure context=], [=continue=]. 1. Let |registration| be the result of running Match Service Worker Registration algorithm passing |client|'s creation URL as the argument. 1. If |registration| is not the [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration, [=continue=]. + + Note: |registration| will be null if the [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=] is [=service worker registration/unregistered=]. + 1. If |client|'s active service worker is not the [=ServiceWorkerGlobalScope/service worker=], then: 1. Invoke Handle Service Worker Client Unload with |client| as the argument. 1. Set |client|'s active service worker to [=ServiceWorkerGlobalScope/service worker=]. @@ -1248,28 +1251,35 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{ExtendableEvent/waitUntil()|event.waitUntil(f)}}

- {{ExtendableEvent/waitUntil()}} method extends the lifetime of the event. + Note: {{ExtendableEvent/waitUntil()}} method extends the lifetime of the event. waitUntil(|f|) method *must* run these steps: - 1. If the {{Event/isTrusted}} attribute is false, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. Let |event| be the [=context object=]. + 1. [=ExtendableEvent/Add lifetime promise=] |f| to |event|. +
+ +
+ To add lifetime promise |promise| (a [=promise=]) to |event| (an {{ExtendableEvent}}), run these steps: - 1. If not [=ExtendableEvent/active=], [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event|'s {{Event/isTrusted}} attribute is false, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event| is not [=ExtendableEvent/active=], [=throw=] an "{{InvalidStateError}}" {{DOMException}}. Note: If no lifetime extension promise has been added in the task that called the event handlers, calling {{ExtendableEvent/waitUntil()}} in subsequent asynchronous tasks will throw. - 1. Add |f| to the [=ExtendableEvent/extend lifetime promises=]. - 1. Increment the [=ExtendableEvent/pending promises count=] by one. + 1. Add |promise| to |event|'s [=ExtendableEvent/extend lifetime promises=]. + 1. Increment |event|'s [=ExtendableEvent/pending promises count=] by one. Note: The [=ExtendableEvent/pending promises count=] is incremented even if the given promise has already been settled. The corresponding count decrement is done in the microtask queued by the reaction to the promise. - 1. Upon [=upon fulfillment|fulfillment=] or [=upon rejection|rejection=] of |f|, [=queue a microtask=] to run these substeps: - 1. Decrement the [=ExtendableEvent/pending promises count=] by one. - 1. Let |registration| be the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. - 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. - 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. + 1. Upon [=upon fulfillment|fulfillment=] or [=upon rejection|rejection=] of |promise|, [=queue a microtask=] to run these substeps: + 1. Decrement |event|'s [=ExtendableEvent/pending promises count=] by one. + 1. If |event|'s [=ExtendableEvent/pending promises count=] is 0, then: + 1. Let |registration| be the [=current global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. + 1. If |registration| is [=service worker registration/unregistered=], invoke [=Try Clear Registration=] with |registration|. + 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. - The user agent *should not* [=terminate service worker|terminate=] a [=/service worker=] if [=Service Worker Has No Pending Events=] returns false for that [=/service worker=]. + The user agent *should not* [=terminate service worker|terminate=] a [=/service worker=] if [=Service Worker Has No Pending Events=] returns false for that [=/service worker=].
[=/Service workers=] and extensions that define event handlers *may* define their own behaviors, allowing the [=ExtendableEvent/extend lifetime promises=] to suggest operation length, and the rejected state of any of the promise in [=ExtendableEvent/extend lifetime promises=] to suggest operation failure. @@ -1323,18 +1333,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe respondWith(|r|) method *must* run these steps: + 1. Let |event| be the [=context object=]. 1. If the dispatch flag is unset, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. 1. If the [=FetchEvent/respond-with entered flag=] is set, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. - 1. Add |r| to the extend lifetime promises. - 1. Increment the [=ExtendableEvent/pending promises count=] by one. - - Note: The [=ExtendableEvent/pending promises count=] is incremented even if the given promise has already been settled. The corresponding count decrement is done in the microtask queued by the reaction to the promise. - - 1. Upon [=upon fulfillment|fulfillment=] or [=upon rejection|rejection=] of |r|, [=queue a microtask=] to run these substeps: - 1. Decrement the [=ExtendableEvent/pending promises count=] by one. - 1. Let |registration| be the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. - 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. - 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. + 1. [=ExtendableEvent/Add lifetime promise=] |r| to |event|. Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil()|event.waitUntil(r)}} is called. @@ -2246,7 +2248,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Invoke Finish Job with |job| and abort these steps. 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=job/scope url=] as the argument. 1. If |registration| is not null, then: - 1. If |registration|'s uninstalling flag is set, unset it. 1. Let |newestWorker| be the result of running the Get Newest Worker algorithm passing |registration| as the argument. 1. If |newestWorker| is not null, |job|'s [=job/script url=] [=url/equals=] |newestWorker|'s [=service worker/script url=], and |job|'s [=job/update via cache mode=]'s value equals |registration|'s [=service worker registration/update via cache mode=]'s value, then: 1. Invoke [=Resolve Job Promise=] with |job| and |registration|. @@ -2265,7 +2266,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: none 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=job/scope url=] as the argument. - 1. If |registration| is null or |registration|'s uninstalling flag is set, then: + 1. If |registration| is null or |registration| is [=service worker registration/unregistered=], then: 1. Invoke [=Reject Job Promise=] with |job| and `TypeError`. 1. Invoke Finish Job with |job| and abort these steps. 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as the argument. @@ -2409,7 +2410,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Run the Update Worker State algorithm passing |registration|'s installing worker and *installing* as the arguments. 1. Assert: |job|'s [=job/job promise=] is not null. 1. Invoke [=Resolve Job Promise=] with |job| and |registration|. - 1. Queue a task to fire an event named updatefound at all the {{ServiceWorkerRegistration}} objects for all the [=/service worker clients=] whose creation URL matches |registration|'s [=service worker registration/scope url=] and all the [=/service workers=] whose containing service worker registration is |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| 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. 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: @@ -2676,7 +2680,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: None - 1. Assert: [=scope to registration map=] contains a value equal to |registration|. 1. Assert: |registration|'s [=active worker=] is not null. 1. Let |activeWorker| be |registration|'s [=active worker=]. 1. If |activeWorker|'s [=set of event types to handle=] does not [=set/contain=] |eventName|, then return and run the following steps [=in parallel=]: @@ -2732,8 +2735,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |registration| be the [=/service worker registration=] used by |client|. 1. If |registration| is null, abort these steps. 1. If any other [=/service worker client=] is using |registration|, abort these steps. - 1. If |registration|'s [=uninstalling flag=] is set, invoke [=Try Clear Registration=] with |registration|. - 1. If |registration| is not null, invoke [=Try Activate=] with |registration|. + 1. If |registration| is [=service worker registration/unregistered=], invoke [=Try Clear Registration=] with |registration|. + 1. Invoke [=Try Activate=] with |registration|.
@@ -2782,7 +2785,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |registration| is null, then: 1. Invoke Resolve Job Promise with |job| and false. 1. Invoke Finish Job with |job| and abort these steps. - 1. Set |registration|'s uninstalling flag. + 1. [=map/Remove=] [=scope to registration map=][|job|'s [=job/scope url=]]. 1. Invoke Resolve Job Promise with |job| and true. 1. Invoke [=Try Clear Registration=] with |registration|. @@ -2828,8 +2831,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 |scopeString| be |registration|'s [=URL serializer|serialized=] [=service worker registration/scope url=]. - 1. [=map/Remove=] scope to registration map[|scopeString|].
@@ -2952,7 +2953,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Set |matchingScope| to the result of parsing |matchingScopeString|. 1. Assert: |matchingScope|'s [=url/origin=] and |clientURL|'s [=url/origin=] are [=same origin=]. 1. Let |registration| be the result of running Get Registration algorithm passing |matchingScope| as the argument. - 1. If |registration| is not null and |registration|'s uninstalling flag is set, return null. 1. Return |registration|.
@@ -2962,15 +2962,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Input :: |scope|, a [=/URL=] : Output - :: |registration|, a [=/service worker registration=] + :: A [=/service worker registration=] 1. Run the following steps atomically. 1. Let |scopeString| be the empty string. 1. If |scope| is not null, set |scopeString| to [=URL serializer|serialized=] |scope| with the *exclude fragment flag* set. - 1. Let |registration| be null. 1. [=map/For each=] |key| → |value| of scope to registration map: - 1. If |scopeString| matches |key|, set |registration| to |value|. - 1. Return |registration|. + 1. If |scopeString| matches |key|, then return |value|. + 1. Return null.
From 13fa43a86ce5768ea74d84b2087bb7f5a33bf059 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 3 Jun 2019 13:27:14 +0100 Subject: [PATCH 3/9] Better id --- docs/index.bs | 2 +- docs/v1/index.bs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index aa037b43..a336c6b6 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -218,7 +218,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker registration=] has an associated navigation preload header value, which is a [=byte sequence=]. It is initially set to \`true\`. - A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=]. + A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=].

Lifetime

diff --git a/docs/v1/index.bs b/docs/v1/index.bs index 95f011f8..41c886d9 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -201,7 +201,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker registration=] has one or more task queues that back up the tasks from its active worker's event loop's corresponding [=/task queues=]. (The target task sources for this back up operation are the handle fetch task source and the handle functional event task source.) The user agent dumps the active worker's tasks to the [=/service worker registration=]'s [=service worker registration/task queues=] when the active worker is terminated and re-queues those tasks to the active worker's event loop's corresponding [=/task queues=] when the active worker spins off. Unlike the [=/task queues=] owned by event loops, the [=/service worker registration=]'s [=service worker registration/task queues=] are not processed by any event loops in and of itself. - A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=]. + A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=].

Lifetime

From 29002b793a15c8461e2893beec8137453bef009d Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 3 Jun 2019 15:46:05 +0100 Subject: [PATCH 4/9] Addressing feedback --- docs/index.bs | 99 +++++++++++++++++++++++------------------------- docs/v1/index.bs | 98 +++++++++++++++++++++++------------------------ 2 files changed, 94 insertions(+), 103 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index a336c6b6..326ad99a 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -218,7 +218,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker registration=] has an associated navigation preload header value, which is a [=byte sequence=]. It is initially set to \`true\`. - A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=]. + A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][this [=/service worker registration=]'s [=service worker registration/scope url=]] is not this [=/service worker registration=].

Lifetime

@@ -1441,64 +1441,59 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{FetchEvent/respondWith(r)|event.respondWith(r)}}

- Note: Developers can set the argument |r| with either a promise that resolves with a {{Response}} object or a {{Response}} object (which is automatically cast to a promise). Otherwise, a network error is returned to [=/Fetch=]. Renderer-side security checks about tainting for cross-origin content are tied to the types of filtered responses defined in [=/Fetch=]. + Note: Developers can set the argument |r| with either a [=promise=] that resolves with a {{Response}} object or a {{Response}} object (which is automatically cast to a promise). Otherwise, a [=network error=] is returned to [=/Fetch=]. Renderer-side security checks about tainting for cross-origin content are tied to the types of [=filtered responses=] defined in [=/Fetch=]. respondWith(|r|) method *must* run these steps: 1. Let |event| be the [=context object=]. - 1. If the dispatch flag is unset, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. - 1. If the [=FetchEvent/respond-with entered flag=] is set, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event|'s [=dispatch flag=] is unset, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event|'s [=FetchEvent/respond-with entered flag=] is set, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. 1. [=ExtendableEvent/Add lifetime promise=] |r| to |event|. Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil()|event.waitUntil(r)}} is called. - 1. Set the stop propagation flag and stop immediate propagation flag. - 1. Set the [=FetchEvent/respond-with entered flag=]. - 1. Set the [=FetchEvent/wait to respond flag=]. - 1. Let |targetRealm| be the relevant Realm of the context object. - 1. Run the following substeps in parallel: - 1. Wait until |r| settles. - 1. If |r| rejected, then: - 1. Set the [=FetchEvent/respond-with error flag=]. - 1. If |r| resolved with |response|, then: - 1. If |response| is a {{Response}} object, then: - 1. If |response| is [=Body/disturbed=] or [=Body/locked=], then: - 1. Set the [=FetchEvent/respond-with error flag=]. - 1. Else: - 1. Let |bytes| be an empty byte sequence. - 1. Let |end-of-body| be false. - 1. Let |done| be false. - 1. Let |potentialResponse| be a copy of |response|'s associated [=Response/response=], except for its [=response/body=]. - 1. If |response|'s [=response/body=] is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|'s [=response/body=]'s stream. - 1. Let |highWaterMark| be a non-negative, non-NaN number, chosen by the user agent. - 1. Let |sizeAlgorithm| be an algorithm that accepts a [=chunk=] object and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. - 1. Let |pull| be an action that runs these subsubsteps: - 1. Let |promise| be the result of reading a chunk from |response|'s [=response/body=]'s stream with |reader|. - 1. When |promise| is fulfilled with an object whose done property is false and whose value property is a Uint8Array object, append the bytes represented by the value property to |bytes| and perform ! DetachArrayBuffer with the ArrayBuffer object wrapped by the value property. - 1. When |promise| is fulfilled with an object whose done property is true, set |end-of-body| to true. - 1. When |promise| is fulfilled with a value that matches with neither of the above patterns, or |promise| is rejected, [=ReadableStream/error=] |newStream| with a TypeError. - 1. Let |cancel| be an action that [=ReadableStream/cancels=] |response|'s [=response/body=]'s stream with |reader|. - 1. Let |newStream| be the result of [=ReadableStream/construct a ReadableStream object=] with |highWaterMark|, |sizeAlgorithm|, |pull|, and |cancel| in |targetRealm|. - 1. Set |potentialResponse|'s [=response/body=] to a new [=/body=] whose stream is |newStream|. - 1. Run these subsubsteps repeatedly in parallel while |done| is false: - 1. If |newStream| is errored, then set |done| to true. - 1. Otherwise, if |bytes| is empty and |end-of-body| is true, then [=ReadableStream/close=] |newStream| and set |done| to true. - 1. Otherwise, if |bytes| is not empty, run these subsubsubsteps: - 1. Let |chunk| be a subsequence of |bytes| starting from the beginning of |bytes|. - 1. Remove |chunk| from |bytes|. - 1. Let |buffer| be an ArrayBuffer object created in |targetRealm| and containing |chunk|. - 1. [=ReadableStream/Enqueue=] a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. - - Note: These substeps are meant to produce the observable equivalent of "piping" |response|'s [=response/body=]'s stream into |potentialResponse|. - - 1. Set the [=FetchEvent/potential response=] to |potentialResponse|. - 1. Else: - 1. Set the [=FetchEvent/respond-with error flag=]. + 1. Set |event|'s [=stop propagation flag=] and [=stop immediate propagation flag=]. + 1. Set |event|'s [=FetchEvent/respond-with entered flag=]. + 1. Set |event|'s [=FetchEvent/wait to respond flag=]. + 1. Let |targetRealm| be |event|'s [=relevant Realm=]. + 1. [=Upon rejection=] of |r|: + 1. Set |event|'s [=FetchEvent/respond-with error flag=]. + 1. Unset |event|'s [=FetchEvent/wait to respond flag=]. + 1. [=Upon fulfillment=] of |r| with |response|: + 1. If |response| is not a {{Response}} object, then set the [=FetchEvent/respond-with error flag=]. - Note: If the [=FetchEvent/respond-with error flag=] is set, a network error is returned to [=/Fetch=] through Handle Fetch algorithm. (See the step 21.1.) Otherwise, the value |response| is returned to [=/Fetch=] through Handle Fetch algorithm. (See the step 22.1.) + Note: If the [=FetchEvent/respond-with error flag=] is set, a [=network error=] is returned to [=/Fetch=] through [=Handle Fetch=] algorithm. (See the step 21.1.) Otherwise, the value |response| is returned to [=/Fetch=] through [=Handle Fetch=] algorithm. (See the step 22.1.) - 1. Unset the [=FetchEvent/wait to respond flag=]. + 1. Else: + 1. Let |bytes| be an empty byte sequence. + 1. Let |end-of-body| be false. + 1. Let |done| be false. + 1. Let |potentialResponse| be a copy of |response|'s associated [=Response/response=], except for its [=response/body=]. + 1. If |response|'s [=response/body=] is non-null, run these substeps: + 1. Let |reader| be the result of [=get a reader|getting a reader=] from |response|'s [=response/body=]'s [=stream=]. + 1. Let |highWaterMark| be a non-negative, non-NaN number, chosen by the user agent. + 1. Let |sizeAlgorithm| be an algorithm that accepts a [=chunk=] object and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. + 1. Let |pull| be an action that runs these subsubsteps: + 1. Let |promise| be the result of [=read a chunk|reading a chunk=] from |response|'s [=response/body=]'s [=stream=] with |reader|. + 1. When |promise| is fulfilled with an object whose `done` property is false and whose `value` property is a `Uint8Array` object, append the bytes represented by the `value` property to |bytes| and perform ! [=DetachArrayBuffer=] with the `ArrayBuffer` object wrapped by the `value` property. + 1. When |promise| is fulfilled with an object whose `done` property is true, set |end-of-body| to true. + 1. When |promise| is fulfilled with a value that matches with neither of the above patterns, or |promise| is rejected, [=ReadableStream/error=] |newStream| with a `TypeError`. + 1. Let |cancel| be an action that [=ReadableStream/cancels=] |response|'s [=response/body=]'s [=stream=] with |reader|. + 1. Let |newStream| be the result of [=ReadableStream/construct a ReadableStream object=] with |highWaterMark|, |sizeAlgorithm|, |pull|, and |cancel| in |targetRealm|. + 1. Set |potentialResponse|'s [=response/body=] to a new [=/body=] whose [=stream=] is |newStream|. + 1. Run these subsubsteps repeatedly [=in parallel=] while |done| is false: + 1. If |newStream| is [=errored=], then set |done| to true. + 1. Otherwise, if |bytes| is empty and |end-of-body| is true, then [=ReadableStream/close=] |newStream| and set |done| to true. + 1. Otherwise, if |bytes| is not empty, run these subsubsubsteps: + 1. Let |chunk| be a subsequence of |bytes| starting from the beginning of |bytes|. + 1. Remove |chunk| from |bytes|. + 1. Let |buffer| be an `ArrayBuffer` object created in |targetRealm| and containing |chunk|. + 1. [=ReadableStream/Enqueue=] a `Uint8Array` object created in |targetRealm| and wrapping |buffer| to |newStream|. + + Note: These substeps are meant to produce the observable equivalent of "piping" |response|'s [=response/body=]'s [=stream=] into |potentialResponse|. + + 1. Set |event|'s [=FetchEvent/potential response=] to |potentialResponse|. + 1. Unset |event|'s [=FetchEvent/wait to respond flag=].
@@ -2455,7 +2450,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: none 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=job/scope url=] as the argument. - 1. If |registration| is null or |registration| is [=service worker registration/unregistered=], then: + 1. If |registration| is null, then: 1. Invoke [=Reject Job Promise=] with |job| and `TypeError`. 1. Invoke Finish Job with |job| and abort these steps. 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as the argument. @@ -2607,7 +2602,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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| to run the following steps: + 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. @@ -3177,7 +3172,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |matchingScopeString| is not the empty string, then: 1. Set |matchingScope| to the result of parsing |matchingScopeString|. 1. Assert: |matchingScope|'s [=url/origin=] and |clientURL|'s [=url/origin=] are [=same origin=]. - 1. Let |registration| be the result of running Get Registration algorithm passing |matchingScope| as the argument. + 1. Return the result of running [=Get Registration=] algorithm passing |matchingScope| as the argument. 1. Return |registration|.
diff --git a/docs/v1/index.bs b/docs/v1/index.bs index 41c886d9..4bf0cc7e 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -201,7 +201,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker registration=] has one or more task queues that back up the tasks from its active worker's event loop's corresponding [=/task queues=]. (The target task sources for this back up operation are the handle fetch task source and the handle functional event task source.) The user agent dumps the active worker's tasks to the [=/service worker registration=]'s [=service worker registration/task queues=] when the active worker is terminated and re-queues those tasks to the active worker's event loop's corresponding [=/task queues=] when the active worker spins off. Unlike the [=/task queues=] owned by event loops, the [=/service worker registration=]'s [=service worker registration/task queues=] are not processed by any event loops in and of itself. - A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][[=service worker registration/scope url=]] is not this [=/service worker registration=]. + A [=/service worker registration=] is said to be unregistered if [=scope to registration map=][this [=/service worker registration=]'s [=service worker registration/scope url=]] is not this [=/service worker registration=].

Lifetime

@@ -1329,63 +1329,59 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{FetchEvent/respondWith(r)|event.respondWith(r)}}

- Note: Developers can set the argument |r| with either a promise that resolves with a {{Response}} object or a {{Response}} object (which is automatically cast to a promise). Otherwise, a network error is returned to [=/Fetch=]. Renderer-side security checks about tainting for cross-origin content are tied to the types of filtered responses defined in [=/Fetch=]. + Note: Developers can set the argument |r| with either a [=promise=] that resolves with a {{Response}} object or a {{Response}} object (which is automatically cast to a promise). Otherwise, a [=network error=] is returned to [=/Fetch=]. Renderer-side security checks about tainting for cross-origin content are tied to the types of [=filtered responses=] defined in [=/Fetch=]. respondWith(|r|) method *must* run these steps: 1. Let |event| be the [=context object=]. - 1. If the dispatch flag is unset, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. - 1. If the [=FetchEvent/respond-with entered flag=] is set, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event|'s [=dispatch flag=] is unset, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. + 1. If |event|'s [=FetchEvent/respond-with entered flag=] is set, [=throw=] an "{{InvalidStateError}}" {{DOMException}}. 1. [=ExtendableEvent/Add lifetime promise=] |r| to |event|. Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil()|event.waitUntil(r)}} is called. - 1. Set the stop propagation flag and stop immediate propagation flag. - 1. Set the [=FetchEvent/respond-with entered flag=]. - 1. Set the [=FetchEvent/wait to respond flag=]. - 1. Let |targetRealm| be the relevant Realm of the context object. - 1. Run the following substeps in parallel: - 1. Wait until |r| settles. - 1. If |r| rejected, then: - 1. Set the [=FetchEvent/respond-with error flag=]. - 1. If |r| resolved with |response|, then: - 1. If |response| is a {{Response}} object, then: - 1. If |response| is [=Body/disturbed=] or [=Body/locked=], then: - 1. Set the [=FetchEvent/respond-with error flag=]. - 1. Else: - 1. Let |bytes| be an empty byte sequence. - 1. Let |end-of-body| be false. - 1. Let |done| be false. - 1. Let |potentialResponse| be a copy of |response|'s associated [=Response/response=], except for its [=response/body=]. - 1. If |response|'s [=response/body=] is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|'s [=response/body=]'s stream. - 1. Let |strategy| be an object created in |targetRealm|. The user agent may choose any object. - 1. Let |pull| be an action that runs these subsubsteps: - 1. Let |promise| be the result of reading a chunk from |response|'s [=response/body=]'s stream with |reader|. - 1. When |promise| is fulfilled with an object whose done property is false and whose value property is a Uint8Array object, append the bytes represented by the value property to |bytes| and perform ! DetachArrayBuffer with the ArrayBuffer object wrapped by the value property. - 1. When |promise| is fulfilled with an object whose done property is true, set |end-of-body| to true. - 1. When |promise| is fulfilled with a value that matches with neither of the above patterns, or |promise| is rejected, [=ReadableStream/error=] |newStream| with a TypeError. - 1. Let |cancel| be an action that [=ReadableStream/cancels=] |response|'s [=response/body=]'s stream with |reader|. - 1. Let |newStream| be the result of [=ReadableStream/construct a ReadableStream object=] with |strategy|, |pull| and |cancel| in |targetRealm|. - 1. Set |potentialResponse|'s [=response/body=] to a new [=/body=] whose stream is |newStream|. - 1. Run these subsubsteps repeatedly in parallel while |done| is false: - 1. If |newStream| is errored, then set |done| to true. - 1. Otherwise, if |bytes| is empty and |end-of-body| is true, then [=ReadableStream/close=] |newStream| and set |done| to true. - 1. Otherwise, if |bytes| is not empty, run these subsubsubsteps: - 1. Let |chunk| be a subsequence of |bytes| starting from the beginning of |bytes|. - 1. Remove |chunk| from |bytes|. - 1. Let |buffer| be an ArrayBuffer object created in |targetRealm| and containing |chunk|. - 1. [=ReadableStream/Enqueue=] a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. - - Note: These substeps are meant to produce the observable equivalent of "piping" |response|'s [=response/body=]'s stream into |potentialResponse|. - - 1. Set the [=FetchEvent/potential response=] to |potentialResponse|. - 1. Else: - 1. Set the [=FetchEvent/respond-with error flag=]. + 1. Set |event|'s [=stop propagation flag=] and [=stop immediate propagation flag=]. + 1. Set |event|'s [=FetchEvent/respond-with entered flag=]. + 1. Set |event|'s [=FetchEvent/wait to respond flag=]. + 1. Let |targetRealm| be |event|'s [=relevant Realm=]. + 1. [=Upon rejection=] of |r|: + 1. Set |event|'s [=FetchEvent/respond-with error flag=]. + 1. Unset |event|'s [=FetchEvent/wait to respond flag=]. + 1. [=Upon fulfillment=] of |r| with |response|: + 1. If |response| is not a {{Response}} object, then set the [=FetchEvent/respond-with error flag=]. - Note: If the [=FetchEvent/respond-with error flag=] is set, a network error is returned to [=/Fetch=] through Handle Fetch algorithm. (See the step 21.1.) Otherwise, the value |response| is returned to [=/Fetch=] through Handle Fetch algorithm. (See the step 22.1.) + Note: If the [=FetchEvent/respond-with error flag=] is set, a [=network error=] is returned to [=/Fetch=] through [=Handle Fetch=] algorithm. (See the step 21.1.) Otherwise, the value |response| is returned to [=/Fetch=] through [=Handle Fetch=] algorithm. (See the step 22.1.) - 1. Unset the [=FetchEvent/wait to respond flag=]. + 1. Else: + 1. Let |bytes| be an empty byte sequence. + 1. Let |end-of-body| be false. + 1. Let |done| be false. + 1. Let |potentialResponse| be a copy of |response|'s associated [=Response/response=], except for its [=response/body=]. + 1. If |response|'s [=response/body=] is non-null, run these substeps: + 1. Let |reader| be the result of [=get a reader|getting a reader=] from |response|'s [=response/body=]'s [=stream=]. + 1. Let |highWaterMark| be a non-negative, non-NaN number, chosen by the user agent. + 1. Let |sizeAlgorithm| be an algorithm that accepts a [=chunk=] object and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. + 1. Let |pull| be an action that runs these subsubsteps: + 1. Let |promise| be the result of [=read a chunk|reading a chunk=] from |response|'s [=response/body=]'s [=stream=] with |reader|. + 1. When |promise| is fulfilled with an object whose `done` property is false and whose `value` property is a `Uint8Array` object, append the bytes represented by the `value` property to |bytes| and perform ! [=DetachArrayBuffer=] with the `ArrayBuffer` object wrapped by the `value` property. + 1. When |promise| is fulfilled with an object whose `done` property is true, set |end-of-body| to true. + 1. When |promise| is fulfilled with a value that matches with neither of the above patterns, or |promise| is rejected, [=ReadableStream/error=] |newStream| with a `TypeError`. + 1. Let |cancel| be an action that [=ReadableStream/cancels=] |response|'s [=response/body=]'s [=stream=] with |reader|. + 1. Let |newStream| be the result of [=ReadableStream/construct a ReadableStream object=] with |highWaterMark|, |sizeAlgorithm|, |pull|, and |cancel| in |targetRealm|. + 1. Set |potentialResponse|'s [=response/body=] to a new [=/body=] whose [=stream=] is |newStream|. + 1. Run these subsubsteps repeatedly [=in parallel=] while |done| is false: + 1. If |newStream| is [=errored=], then set |done| to true. + 1. Otherwise, if |bytes| is empty and |end-of-body| is true, then [=ReadableStream/close=] |newStream| and set |done| to true. + 1. Otherwise, if |bytes| is not empty, run these subsubsubsteps: + 1. Let |chunk| be a subsequence of |bytes| starting from the beginning of |bytes|. + 1. Remove |chunk| from |bytes|. + 1. Let |buffer| be an `ArrayBuffer` object created in |targetRealm| and containing |chunk|. + 1. [=ReadableStream/Enqueue=] a `Uint8Array` object created in |targetRealm| and wrapping |buffer| to |newStream|. + + Note: These substeps are meant to produce the observable equivalent of "piping" |response|'s [=response/body=]'s [=stream=] into |potentialResponse|. + + 1. Set |event|'s [=FetchEvent/potential response=] to |potentialResponse|. + 1. Unset |event|'s [=FetchEvent/wait to respond flag=].
@@ -2266,7 +2262,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: none 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=job/scope url=] as the argument. - 1. If |registration| is null or |registration| is [=service worker registration/unregistered=], then: + 1. If |registration| is null, then: 1. Invoke [=Reject Job Promise=] with |job| and `TypeError`. 1. Invoke Finish Job with |job| and abort these steps. 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as the argument. @@ -2411,7 +2407,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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| to run the following steps: + 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. @@ -2952,7 +2948,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |matchingScopeString| is not the empty string, then: 1. Set |matchingScope| to the result of parsing |matchingScopeString|. 1. Assert: |matchingScope|'s [=url/origin=] and |clientURL|'s [=url/origin=] are [=same origin=]. - 1. Let |registration| be the result of running Get Registration algorithm passing |matchingScope| as the argument. + 1. Return the result of running [=Get Registration=] algorithm passing |matchingScope| as the argument. 1. Return |registration|.
From 88f1b6a3996747dff2dfbbd5b6f7b6302ca84ab6 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Mon, 3 Jun 2019 15:48:36 +0100 Subject: [PATCH 5/9] Oops --- docs/index.bs | 1 - docs/v1/index.bs | 1 - 2 files changed, 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 326ad99a..009467ff 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3173,7 +3173,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Set |matchingScope| to the result of parsing |matchingScopeString|. 1. Assert: |matchingScope|'s [=url/origin=] and |clientURL|'s [=url/origin=] are [=same origin=]. 1. Return the result of running [=Get Registration=] algorithm passing |matchingScope| as the argument. - 1. Return |registration|.
diff --git a/docs/v1/index.bs b/docs/v1/index.bs index 4bf0cc7e..9fad59f4 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -2949,7 +2949,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Set |matchingScope| to the result of parsing |matchingScopeString|. 1. Assert: |matchingScope|'s [=url/origin=] and |clientURL|'s [=url/origin=] are [=same origin=]. 1. Return the result of running [=Get Registration=] algorithm passing |matchingScope| as the argument. - 1. Return |registration|.
From a1992611547535613850bf774c4de93555a7701d Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 4 Jun 2019 14:21:48 +0100 Subject: [PATCH 6/9] Creating a central algorithm for updating service worker state and registrations --- docs/index.bs | 223 ++++++++++++++++++++--------------------------- docs/v1/index.bs | 213 +++++++++++++++++++------------------------- 2 files changed, 187 insertions(+), 249 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 009467ff..8f72f43d 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1303,7 +1303,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |client|'s active service worker is not the [=ServiceWorkerGlobalScope/service worker=], then: 1. Invoke Handle Service Worker Client Unload with |client| as the argument. 1. Set |client|'s active service worker to [=ServiceWorkerGlobalScope/service worker=]. - 1. Invoke Notify Controller Change algorithm with |client| as the argument. + 1. [=Queue a task=] on |client|'s [=responsible event loop=] using the [=DOM manipulation task source=] to [=fire an event=] named `controllerchange` at the {{ServiceWorkerContainer}} object that |client| is [=ServiceWorkerContainer/service worker client|associated=] with. 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -2589,53 +2589,45 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Install

: Input - :: |job|, a job + :: |job|, a [=job=] :: |worker|, a [=/service worker=] :: |registration|, a [=/service worker registration=] : Output :: none 1. Let |installFailed| be false. - 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. - 1. Run the Update Registration State algorithm passing |registration|, "installing" and |worker| as the arguments. - 1. Run the Update Worker State algorithm passing |registration|'s installing worker and *installing* as the arguments. + 1. Let |newestWorker| be the result of running [=Get Newest Worker=] algorithm passing |registration| as its argument. + 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. 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. Let |installingWorker| be |registration|'s [=installing worker=]. + 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. @@ -2650,12 +2642,10 @@ 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. @@ -2669,9 +2659,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: @@ -2681,7 +2668,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* ]».
@@ -3039,18 +3026,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: None 1. Run the following steps atomically. - 1. If |registration|'s installing worker is not null, then: - 1. [=Terminate Service Worker|Terminate=] |registration|'s [=installing worker=]. - 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 |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|.
@@ -3068,88 +3051,74 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
-

Update Registration State

+

Update State

- : Input - :: |registration|, a [=/service worker registration=] - :: |target|, a string (one of "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. -
- -
-

Update Worker State

+ Note: This algorithm updates the state of [=/service workers=] and their position within a [=/service worker registration=]. It ensures related events are dispatched at a consistent time and in a consistent order. : Input - :: |worker|, a [=/service worker=] - :: |state|, a [=/service worker=]'s state + :: |workerUpdates|, a [=/map=] where the [=map/keys=] are [=/service workers=] and the [=map/values=] are [=service worker/states=] : Output :: None - 1. Set |worker|'s state to |state|. - 1. Let |workerObjects| be an array containing all the {{ServiceWorker}} objects associated with |worker|. - 1. For each |workerObject| in |workerObjects|: - 1. Queue a task to run these substeps: - 1. Set the {{ServiceWorker/state}} attribute of |workerObject| to the value (in {{ServiceWorkerState}} enumeration) corresponding to the first matching statement, switching on |worker|'s state: - : *installing* - :: {{"installing"}} - - Note: The [=/service worker=] in this state is considered an installing worker. During this state, {{ExtendableEvent/waitUntil()}} can be called inside the {{ServiceWorkerGlobalScope/oninstall}} event handler to extend the life of the installing worker until the passed promise resolves successfully. This is primarily used to ensure that the [=/service worker=] is not active until all of the core caches are populated. - - : *installed* - :: {{"installed"}} + 1. If |workerUpdates| [=map/is empty=], then return. + 1. Assert: Every [=map/value=] in |workerUpdates| has the same [=service worker/containing service worker registration=]. + 1. Let |registration| be the [=service worker/containing service worker registration=] of any [=map/value=] in |workerUpdates|. + 1. Let |updateFound| be false. + 1. Let |newActiveWorker| be false. + 1. Let |newestWorker| be the result of invoking [=Get Newest Worker=] with |registration|. + 1. [=map/For each=] |worker| → |state| of |workerUpdates|: + 1. Set |worker|'s [=service worker/state=] to |state|. + 1. Switch on |state|: + : *installing* + :: + 1. If |newestWorker| is not null, |worker| is not null, then set |updateFound| to true. + 1. Set |registration|'s [=service worker registration/installing worker=] to |worker|. + : *installed* + :: + 1. Set |registration|'s [=service worker registration/waiting worker=] to |worker|. + 1. If |registration|'s [=service worker registration/installing worker=] is |worker|, then set |registration|'s [=service worker registration/installing worker=] to null. + : *activating* + :: + 1. If |worker| is not null and |registration|'s [=service worker registration/active worker=] is not null, then set |newActiveWorker| to true. + 1. Set |registration|'s [=service worker registration/active worker=] to |worker|. + 1. If |registration|'s [=service worker registration/waiting worker=] is |worker|, then set |registration|'s [=service worker registration/waiting worker=] to null. + : *redundant* + :: + 1. If |registration|'s [=service worker registration/installing worker=] is |worker|, then set |registration|'s [=service worker registration/installing worker=] to null. + 1. Else, if |registration|'s [=service worker registration/waiting worker=] is |worker|, then set |registration|'s [=service worker registration/waiting worker=] to null. + 1. Else, if |registration|'s [=service worker registration/active worker=] is |worker|, then set |registration|'s [=service worker registration/active worker=] to null. + 1. [=Terminate Service Worker|Terminate=] |worker|. + 1. Let |installingWorker| be |registration|'s [=service worker registration/installing worker=]. + 1. Let |waitingWorker| be |registration|'s [=service worker registration/waiting worker=]. + 1. Let |activeWorker| be |registration|'s [=service worker registration/active worker=]. + + Note: These values are 'cached' as the actual values on |registration| may have changed by the time we queue a task. - Note: The [=/service worker=] in this state is considered a waiting worker. - - : *activating* - :: {{"activating"}} - - Note: The [=/service worker=] in this state is considered an active worker. During this state, {{ExtendableEvent/waitUntil()}} can be called inside the {{ServiceWorkerGlobalScope/onactivate}} event handler to extend the life of the active worker until the passed promise resolves successfully. No functional events are dispatched until the state becomes *activated*. - - : *activated* - :: {{"activated"}} - - Note: The [=/service worker=] in this state is considered an active worker ready to handle functional events. - - : *redundant* - :: {{"redundant"}} - - Note: A new [=/service worker=] is replacing the current [=/service worker=], or the current [=/service worker=] is being discarded due to an install failure. - - 1. Fire an event named statechange at |workerObject|. - - The task *must* use |workerObject|'s relevant settings object's responsible event loop and the DOM manipulation task source. -
- -
-

Notify Controller Change

- - : Input - :: |client|, a [=/service worker client=] - : Output - :: None - - 1. Assert: |client| is not null. - 1. If |client| is an [=environment settings object=], queue a task to [=fire an event=] named 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=].
@@ -3158,7 +3127,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Input :: |clientURL|, a [=/URL=] : Output - :: |registration|, a [=/service worker registration=] + :: A [=/service worker registration=] 1. Run the following steps atomically. 1. Let |clientURLString| be serialized |clientURL|. diff --git a/docs/v1/index.bs b/docs/v1/index.bs index 9fad59f4..7cf26382 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -1215,7 +1215,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |client|'s active service worker is not the [=ServiceWorkerGlobalScope/service worker=], then: 1. Invoke Handle Service Worker Client Unload with |client| as the argument. 1. Set |client|'s active service worker to [=ServiceWorkerGlobalScope/service worker=]. - 1. Invoke Notify Controller Change algorithm with |client| as the argument. + 1. [=Queue a task=] on |client|'s [=responsible event loop=] using the [=DOM manipulation task source=] to [=fire an event=] named `controllerchange` at the {{ServiceWorkerContainer}} object that |client| is [=ServiceWorkerContainer/service worker client|associated=] with. 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -2394,29 +2394,24 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Install

: Input - :: |job|, a job + :: |job|, a [=job=] :: |worker|, a [=/service worker=] :: |registration|, a [=/service worker registration=] : Output :: none 1. Let |installFailed| be false. - 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. - 1. Run the Update Registration State algorithm passing |registration|, "installing" and |worker| as the arguments. - 1. Run the Update Worker State algorithm passing |registration|'s installing worker and *installing* as the arguments. + 1. Let |newestWorker| be the result of running [=Get Newest Worker=] algorithm passing |registration| as its argument. + 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. 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. Let |installingWorker| be |registration|'s [=installing worker=]. + 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. @@ -2425,16 +2420,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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. 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 [=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 |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 queued by Update Worker State invoked in this algorithm to have executed. 1. Invoke [=Try Activate=] with |registration|. @@ -2451,12 +2443,10 @@ 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. @@ -2470,9 +2460,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: @@ -2482,7 +2469,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* ]».
@@ -2815,18 +2802,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: None 1. Run the following steps atomically. - 1. If |registration|'s installing worker is not null, then: - 1. [=Terminate Service Worker|Terminate=] |registration|'s [=installing worker=]. - 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 |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|.
@@ -2844,88 +2827,74 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
-

Update Registration State

+

Update State

- : Input - :: |registration|, a [=/service worker registration=] - :: |target|, a string (one of "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. -
- -
-

Update Worker State

+ Note: This algorithm updates the state of [=/service workers=] and their position within a [=/service worker registration=]. It ensures related events are dispatched at a consistent time and in a consistent order. : Input - :: |worker|, a [=/service worker=] - :: |state|, a [=/service worker=]'s state + :: |workerUpdates|, a [=/map=] where the [=map/keys=] are [=/service workers=] and the [=map/values=] are [=service worker/states=] : Output :: None - 1. Set |worker|'s state to |state|. - 1. Let |workerObjects| be an array containing all the {{ServiceWorker}} objects associated with |worker|. - 1. For each |workerObject| in |workerObjects|: - 1. Queue a task to run these substeps: - 1. Set the {{ServiceWorker/state}} attribute of |workerObject| to the value (in {{ServiceWorkerState}} enumeration) corresponding to the first matching statement, switching on |worker|'s state: - : *installing* - :: {{"installing"}} - - Note: The [=/service worker=] in this state is considered an installing worker. During this state, {{ExtendableEvent/waitUntil()}} can be called inside the {{ServiceWorkerGlobalScope/oninstall}} event handler to extend the life of the installing worker until the passed promise resolves successfully. This is primarily used to ensure that the [=/service worker=] is not active until all of the core caches are populated. - - : *installed* - :: {{"installed"}} + 1. If |workerUpdates| [=map/is empty=], then return. + 1. Assert: Every [=map/value=] in |workerUpdates| has the same [=service worker/containing service worker registration=]. + 1. Let |registration| be the [=service worker/containing service worker registration=] of any [=map/value=] in |workerUpdates|. + 1. Let |updateFound| be false. + 1. Let |newActiveWorker| be false. + 1. Let |newestWorker| be the result of invoking [=Get Newest Worker=] with |registration|. + 1. [=map/For each=] |worker| → |state| of |workerUpdates|: + 1. Set |worker|'s [=service worker/state=] to |state|. + 1. Switch on |state|: + : *installing* + :: + 1. If |newestWorker| is not null, |worker| is not null, then set |updateFound| to true. + 1. Set |registration|'s [=service worker registration/installing worker=] to |worker|. + : *installed* + :: + 1. Set |registration|'s [=service worker registration/waiting worker=] to |worker|. + 1. If |registration|'s [=service worker registration/installing worker=] is |worker|, then set |registration|'s [=service worker registration/installing worker=] to null. + : *activating* + :: + 1. If |worker| is not null and |registration|'s [=service worker registration/active worker=] is not null, then set |newActiveWorker| to true. + 1. Set |registration|'s [=service worker registration/active worker=] to |worker|. + 1. If |registration|'s [=service worker registration/waiting worker=] is |worker|, then set |registration|'s [=service worker registration/waiting worker=] to null. + : *redundant* + :: + 1. If |registration|'s [=service worker registration/installing worker=] is |worker|, then set |registration|'s [=service worker registration/installing worker=] to null. + 1. Else, if |registration|'s [=service worker registration/waiting worker=] is |worker|, then set |registration|'s [=service worker registration/waiting worker=] to null. + 1. Else, if |registration|'s [=service worker registration/active worker=] is |worker|, then set |registration|'s [=service worker registration/active worker=] to null. + 1. [=Terminate Service Worker|Terminate=] |worker|. + 1. Let |installingWorker| be |registration|'s [=service worker registration/installing worker=]. + 1. Let |waitingWorker| be |registration|'s [=service worker registration/waiting worker=]. + 1. Let |activeWorker| be |registration|'s [=service worker registration/active worker=]. + + Note: These values are 'cached' as the actual values on |registration| may have changed by the time we queue a task. - Note: The [=/service worker=] in this state is considered a waiting worker. - - : *activating* - :: {{"activating"}} - - Note: The [=/service worker=] in this state is considered an active worker. During this state, {{ExtendableEvent/waitUntil()}} can be called inside the {{ServiceWorkerGlobalScope/onactivate}} event handler to extend the life of the active worker until the passed promise resolves successfully. No functional events are dispatched until the state becomes *activated*. - - : *activated* - :: {{"activated"}} - - Note: The [=/service worker=] in this state is considered an active worker ready to handle functional events. - - : *redundant* - :: {{"redundant"}} - - Note: A new [=/service worker=] is replacing the current [=/service worker=], or the current [=/service worker=] is being discarded due to an install failure. - - 1. Fire an event named statechange at |workerObject|. - - The task *must* use |workerObject|'s relevant settings object's responsible event loop and the DOM manipulation task source. -
- -
-

Notify Controller Change

- - : Input - :: |client|, a [=/service worker client=] - : Output - :: None - - 1. Assert: |client| is not null. - 1. If |client| is an [=environment settings object=], queue a task to [=fire an event=] named 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=].
@@ -2934,7 +2903,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Input :: |clientURL|, a [=/URL=] : Output - :: |registration|, a [=/service worker registration=] + :: A [=/service worker registration=] 1. Run the following steps atomically. 1. Let |clientURLString| be serialized |clientURL|. From 3146d707d9d87161b9e756b669b10219acc3e2f3 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 4 Jun 2019 14:34:24 +0100 Subject: [PATCH 7/9] Set active worker in task --- docs/index.bs | 5 +++-- docs/v1/index.bs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 8f72f43d..1e22eaaa 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1302,8 +1302,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |client|'s active service worker is not the [=ServiceWorkerGlobalScope/service worker=], then: 1. Invoke Handle Service Worker Client Unload with |client| as the argument. - 1. Set |client|'s active service worker to [=ServiceWorkerGlobalScope/service worker=]. - 1. [=Queue a task=] on |client|'s [=responsible event loop=] using the [=DOM manipulation task source=] to [=fire an event=] named `controllerchange` at the {{ServiceWorkerContainer}} object that |client| is [=ServiceWorkerContainer/service worker client|associated=] with. + 1. [=Queue a task=] on |client|'s [=responsible event loop=] using the [=DOM manipulation task source=] to run the following steps: + 1. Set |client|'s [=active service worker=] to [=ServiceWorkerGlobalScope/service worker=]. + 1. [=Fire an event=] named `controllerchange` on the {{ServiceWorkerContainer}} object that |client| is [=ServiceWorkerContainer/service worker client|associated=] with. 1. Resolve |promise| with undefined. 1. Return |promise|.
diff --git a/docs/v1/index.bs b/docs/v1/index.bs index 7cf26382..cc56d1e1 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -1214,8 +1214,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |client|'s active service worker is not the [=ServiceWorkerGlobalScope/service worker=], then: 1. Invoke Handle Service Worker Client Unload with |client| as the argument. - 1. Set |client|'s active service worker to [=ServiceWorkerGlobalScope/service worker=]. - 1. [=Queue a task=] on |client|'s [=responsible event loop=] using the [=DOM manipulation task source=] to [=fire an event=] named `controllerchange` at the {{ServiceWorkerContainer}} object that |client| is [=ServiceWorkerContainer/service worker client|associated=] with. + 1. [=Queue a task=] on |client|'s [=responsible event loop=] using the [=DOM manipulation task source=] to run the following steps: + 1. Set |client|'s [=active service worker=] to [=ServiceWorkerGlobalScope/service worker=]. + 1. [=Fire an event=] named `controllerchange` on the {{ServiceWorkerContainer}} object that |client| is [=ServiceWorkerContainer/service worker client|associated=] with. 1. Resolve |promise| with undefined. 1. Return |promise|. From abcc1d954fb2ab56f27be35f028a5fbbb904d19b Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 4 Jun 2019 14:39:07 +0100 Subject: [PATCH 8/9] Don't need to handle the ready promise here anymore. --- docs/index.bs | 3 --- docs/v1/index.bs | 3 --- 2 files changed, 6 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 1e22eaaa..6809cd26 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -2651,9 +2651,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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. diff --git a/docs/v1/index.bs b/docs/v1/index.bs index cc56d1e1..08b5bd1c 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -2452,9 +2452,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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. From 300460b4f95f9d2ee9e89571328a843a2ae64660 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 4 Jun 2019 14:56:17 +0100 Subject: [PATCH 9/9] Fixing broken anchor --- docs/index.bs | 4 ++-- docs/v1/index.bs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 6809cd26..33709429 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -629,7 +629,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).)
@@ -3116,7 +3116,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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=]. + 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=].
diff --git a/docs/v1/index.bs b/docs/v1/index.bs index 08b5bd1c..de79bf4b 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -595,7 +595,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).)
@@ -2892,7 +2892,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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=]. + 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=].