From a03e4c6fb1ce3f35b75795bc1b6ce50c54982ca0 Mon Sep 17 00:00:00 2001 From: Jungkee Song Date: Fri, 3 Feb 2017 15:44:52 +0900 Subject: [PATCH 1/3] Improve Activate with Try Activate This adds concepts and algorithms to track events (all service worker events: lifecycle events, functional events, extendable message events) that have pending extension promises so they can be used to check if the registration's waiting worker can be promoted. This also changes Install algorithm and related steps to match to the implementations behavior. That is, instead of waiting for the promotion condition in Install algorithm, newly introduced Try Activate algorithm just tries to activate depending on the condition and return. Try Activate is called when: - A service worker is installed. - The last client controlled by the existing active worker is unloaded. - skipWaiting() is called. - The extend lifetime promises for the existing active worker settle. Related issue: #916. --- docs/index.bs | 91 ++++++-- docs/index.html | 566 ++++++++++++++++++++++++++++----------------- docs/v1/index.bs | 82 +++++-- docs/v1/index.html | 520 +++++++++++++++++++++++++---------------- 4 files changed, 815 insertions(+), 444 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 6792b0a7..a191dcef 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -168,6 +168,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A [=/service worker=] has an associated set of event types to handle (a [=ordered set|set=]) whose [=item=] is an event listener's event type. It is initially an empty set. + A [=/service worker=] has an associated set of extended events (a [=ordered set|set=]) whose [=item=] is an [=event=]. It is initially an empty set. + A [=/service worker=] has an associated list of foreign fetch scopes whose element type is a [=/URL=]. It is initially empty. A [=/service worker=] has an associated list of foreign fetch origins whose element type is a [=/URL=]. It is initially empty. @@ -364,6 +366,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Else, let it be initialized to a new {{Client}} object that represents the worker associated with |incumbentGlobal|. 1. Let the {{ExtendableMessageEvent/ports}} attribute of |e| be initialized to |newPorts|. 1. Dispatch |e| at |destination|. + 1. Invoke [=Update Service Worker Extended Events Set=] with |serviceWorker| and |e|. The task *must* use the DOM manipulation task source. @@ -903,7 +906,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. Set [=/service worker=]'s skip waiting flag. + 1. Set [=ServiceWorkerGlobalScope/service worker=]'s skip waiting flag. + 1. Invoke [=Try Activate=] with [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. 1. Resolve |promise| with undefined. 1. Return |promise|. @@ -1313,11 +1317,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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. Increase the [=ExtendableEvent/pending promises count=] by one. + 1. Increment the [=ExtendableEvent/pending promises count=] by one. - Note: The [=ExtendableEvent/pending promises count=] is increased even if the given promise has already been settled. The corresponding count decrease is done in the microtask queued by the reaction to the promise. + 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 decrease the [=ExtendableEvent/pending promises count=] by one. + 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. Invoke [=Try Activate=] with the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. The user agent *should not* terminate the [=/service worker=] associated with |event|'s relevant settings object's [=environment settings object/global object=] when |event|'s [=dispatch flag=] is set or |event|'s [=ExtendableEvent/pending promises count=] is not zero. However, the user agent *may* impose a time limit to this lifetime extension. @@ -1462,11 +1468,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. 1. Add |r| to the extend lifetime promises. - 1. Increase the [=ExtendableEvent/pending promises count=] by one. + 1. Increment the [=ExtendableEvent/pending promises count=] by one. - Note: The [=ExtendableEvent/pending promises count=] is increased even if the given promise has already been settled. The corresponding count decrease is done in the microtask queued by the reaction to the promise. + 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 decrease the [=ExtendableEvent/pending promises count=] by one. + 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. Invoke [=Try Activate=] with the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil()|event.waitUntil(r)}} is called. @@ -1578,11 +1586,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. 1. Add |r| to the extend lifetime promises. - 1. Increase the [=ExtendableEvent/pending promises count=] by one. + 1. Increment the [=ExtendableEvent/pending promises count=] by one. - Note: The [=ExtendableEvent/pending promises count=] is increased even if the given promise has already been settled. The corresponding count decrease is done in the microtask queued by the reaction to the promise. + 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 decrease the [=ExtendableEvent/pending promises count=] by one. + 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. Invoke [=Try Activate=] with the [=context object=]'s [=relevant global object=]'s associated [=ServiceWorkerGlobalScope/service worker=]'s [=containing service worker registration=]. Note: {{ForeignFetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil()|event.waitUntil(r)}} is called. @@ -2721,15 +2731,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |registration|'s waiting worker is not null, then: 1. Set |redundantWorker| to |registration|'s waiting worker. 1. Terminate |redundantWorker|. - 1. The user agent *may* abort in-flight requests triggered by |redundantWorker|. 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. 1. Invoke Finish Job with |job|. 1. Wait for all the tasks queued by Update Worker State invoked in this algorithm have executed. - 1. Wait until no [=/service worker client=] is using |registration| or |registration|'s waiting worker's skip waiting flag is set. - 1. If |registration|'s waiting worker is not null, invoke Activate algorithm with |registration| as its argument. + 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, and the [=extend lifetime promises=] for the existing [=active worker=] settle.
@@ -2742,10 +2752,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |registration|'s waiting worker is null, abort these steps. 1. Let |redundantWorker| be null. - 1. If |registration|'s active worker is not null, then: - 1. Set |redundantWorker| to |registration|'s active worker. - 1. Wait for |redundantWorker| to finish handling any in-progress requests. - 1. Terminate |redundantWorker|. + 1. If |registration|'s [=active worker=] is not null, |redundantWorker| be |registration|'s [=active worker=]. 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. @@ -2774,6 +2781,18 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Run the Update Worker State algorithm passing |registration|'s active worker and *activated* as the arguments.
+
+

Try Activate

+ + : Input + :: |registration|, a [=/service worker registration=] + : Output + :: None + + 1. Assert: |registration|'s [=waiting worker=] is not null. + 1. If |registration|'s [=active worker=] is null, or if the result of running [=Service Worker Has No Pending Events=] with |registration|'s [=active worker=] is true, and no [=/service worker client=] is [=using=] |registration| or |registration|’s [=waiting worker=]'s [=skip waiting flag=] is set, then invoke [=Activate=] with |registration|. +
+

Run Service Worker

@@ -2934,6 +2953,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s [=request/target client id=], and to the empty string otherwise. 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s [=request/client=] is a window client and the event was dispatched with the user's intention for the page reload, and false otherwise. 1. Dispatch |e| at |activeWorker|'s [=service worker/global object=]. + 1. Invoke [=Update Service Worker Extended Events Set=] with |activeWorker| and |e|. 1. If |e|'s [=FetchEvent/respond-with entered flag=] is set, set |respondWithEntered| to true. 1. If |e|'s [=FetchEvent/wait to respond flag=] is set, then: 1. Wait until |e|'s [=FetchEvent/wait to respond flag=] is unset. @@ -2997,6 +3017,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Initialize |e|’s {{ForeignFetchEvent/request}} attribute to |r|. 1. Initialize |e|’s {{ForeignFetchEvent/origin}} attribute to the Unicode serialization of |request|'s [=request/origin=]. 1. Dispatch |e| at |activeWorker|'s [=service worker/global object=]. + 1. Invoke [=Update Service Worker Extended Events Set=] with |activeWorker| and |e|. 1. If |e|'s [=ForeignFetchEvent/respond-with entered flag=] is set, set |respondWithEntered| to true. 1. If |e|'s wait to respond flag is set, wait until |e|'s wait to respond flag is unset. 1. Let |internalResponse| be |e|'s [=ForeignFetchEvent/potential response=]. @@ -3058,6 +3079,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run these substeps: 1. Invoke |callbackSteps| with |activeWorker|'s [=service worker/global object=] as its argument. + 1. Invoke [=Update Service Worker Extended Events Set=] with |activeWorker| and |event|. The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. @@ -3080,7 +3102,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 Clear Registration algorithm passing |registration| as its argument and abort these steps. - 1. If |registration|'s waiting worker is not null, run Activate algorithm with |registration| as the argument. + 1. If |registration|'s waiting worker is not null, invoke [=Try Activate=] with |registration|.
@@ -3099,6 +3121,21 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Invoke Activate with |registration|.
+
+

Update Service Worker Extended Events Set

+ + : Input + :: |worker|, a [=/service worker=] + :: |event|, an [=event=] + : Output + :: None + + 1. Assert: |event|'s [=dispatch flag=] is unset. + 1. For each |item| of |worker|'s [=set of extended events=]: + 1. If |item|'s [=pending promises count=] is zero, [=set/remove=] |item| from |worker|'s [=set of extended events=]. + 1. If |event|'s [=pending promises count=] is not zero, [=set/append=] |event| to |worker|'s [=set of extended events=]. +
+

Unregister

@@ -3152,19 +3189,16 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |registration|'s installing worker is not null, then: 1. Set |redundantWorker| to |registration|'s installing worker. 1. Terminate |redundantWorker|. - 1. The user agent *may* abort in-flight requests triggered by |redundantWorker|. 1. Run the Update Registration State algorithm passing |registration|, "installing" and null as the arguments. 1. Run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. 1. If |registration|'s waiting worker is not null, then: 1. Set |redundantWorker| to |registration|'s waiting worker. 1. Terminate |redundantWorker|. - 1. The user agent *may* abort in-flight requests triggered by |redundantWorker|. 1. Run the Update Registration State algorithm passing |registration|, "waiting" and null as the arguments. 1. Run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. 1. If |registration|'s active worker is not null, then: 1. Set |redundantWorker| to |registration|'s active worker. 1. Terminate |redundantWorker|. - 1. The user agent *may* abort in-flight requests triggered by |redundantWorker|. 1. Run the Update Registration State algorithm passing |registration|, "active" and null as the arguments. 1. Run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. 1. Let |scopeString| be serialized |registration|'s [=service worker registration/scope url=] with the *exclude fragment flag* set. @@ -3332,6 +3366,21 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Return |newestWorker|.
+
+

Service Worker Has No Pending Events

+ + : Input + :: |worker|, a [=/service worker=] + : Output + :: True or false, a boolean + + 1. Let |sum| be zero. + 1. For each |item| of |worker|'s [=set of extended events=]: + 1. Add |item|'s [=pending promises count=] to |sum|. + 1. If |sum| is zero, return true. + 1. Else, return false. +
+

Create Client

diff --git a/docs/index.html b/docs/index.html index 4354f2e8..c703f5f7 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1177,7 +1177,7 @@ } } - + - + - + - + - + - +