From 8ac7cb5acb4a30c63879445ce29616af812df30b Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 22 Nov 2016 16:48:05 +0000 Subject: [PATCH 01/17] =?UTF-8?q?Re-importing=20the=20spec,=20making=20use?= =?UTF-8?q?=20of=20as=20many=20bikeshed=20features=20as=20I=20know.=20The?= =?UTF-8?q?=20whole=20spec=20isn=E2=80=99t=20here=20yet.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/index.bs | 1638 ++++++++++++++++++++----------------------------- 1 file changed, 649 insertions(+), 989 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index b2bc26c4..2c426e01 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -16,9 +16,8 @@ Abstract: This specification describes a method that enables applications to tak Abstract: Abstract: The core of this system is an event-driven Web Worker, which responds to events dispatched from documents and other sources. A system for managing installation, versions, and upgrades is provided. Abstract: -Abstract: The service worker is a generic entry point for event-driven background processing in the Web Platform that is extensible by other specifications. -Ignored Terms: javascript global environment, worker environment, worker environments, document environment, document environments, referrer source, script execution environment, script execution environments, code entry-point, jump to a code entry point, used flag, process response body, http equivalent codes -Markup Shorthands: css no +Abstract: The service worker is a generic entry point for event-driven background processing in the Web Platform that is . +Markup Shorthands: css no, markdown yes
@@ -33,258 +32,175 @@ Markup Shorthands: css no
 }
 
- - -
-spec: DOM; urlPrefix: https://dom.spec.whatwg.org/
-    type: dfn; text: ASCII case-insensitive; url: ascii-case-insensitive
-
-spec: ecma-262; urlPrefix: http://tc39.github.io/ecma262/
-    type: dfn
-        text: Assert; url: sec-algorithm-conventions
-        text: [[Call]]; url: sec-ecmascript-function-objects-call-thisargument-argumentslist
-        text: map objects; url: sec-map-objects
-        text: promise; url: sec-promise-objects
-        url: sec-list-and-record-specification-type
-            text: List
-            text: Record
-
-spec: csp2; urlPrefix: https://w3c.github.io/webappsec-csp/2/
-    type: dfn
-        text: enforce
-        text: monitor
-
-spec: fetch; urlPrefix: https://fetch.spec.whatwg.org/
-    type: dfn
-        text: cancel a ReadableStream; url: concept-cancel-readablestream
-        text: close ReadableStream; url: concept-close-readablestream
-        text: construct a ReadableStream; url: concept-construct-readablestream
-        text: disturbed; url: concept-body-disturbed
-        text: empty; url: concept-empty-readablestream
-        text: enqueue a chunk to ReadableStream; url: concept-enqueue-readablestream
-        text: error ReadableStream; url: concept-error-readablestream
-        text: errored; url: concept-readablestream-errored
-        text: fetch; url: concept-fetch
-        text: get a reader; url: concept-get-reader
-        text: http fetch; url: concept-http-fetch
-        text: HTTPS state value; url: concept-https-state-value
-        text: internal response; url: concept-internal-response
-        text: locked; url: concept-body-locked
-        text: opaque filtered response; url: concept-filtered-response-opaque
-        text: opaque-redirect filtered response; url: concept-filtered-response-opaque-redirect
-        text: potential-navigation-or-subresource request
-        text: process response
-        text: process response end-of-file
-        text: read a chunk from a ReadableStream; url: concept-read-chunk-from-readablestream
-        text: read all bytes; url: concept-read-all-bytes-from-readablestream
-        text: ReadableStream; url: concept-readablestream
-        text: request; for: fetch; url: concept-request
-        text: response; for: fetch; url: concept-response
-        text: skip service worker flag
-        text: stream; url: concept-body-stream
-        text: terminate; url: concept-fetch-terminate
-        text: guard; for: headers; url: concept-headers-guard
-        for: Body; urlPrefix: #concept-body-
-            text: body
-        for: header; urlPrefix: #concept-header-
-            text: name
-            text: parsing; url: parse
-        for: request; urlPrefix: #concept-request-
-            text: request
-            text: origin
-        for: response; urlPrefix: #concept-response-
-            text: response
-
-spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
-    type: dfn
-        urlPrefix: browsers.html
-            text: ancestor origins array; for: Location; url: concept-location-ancestor-origins-array
-            text: origin; for: resource; url: origin-2
-
-spec: page-visibility; urlPrefix: https://www.w3.org/TR/page-visibility/
-    type: enum; text: VisibilityState; url: VisibilityState
-    type: attribute; text: visibilityState; for: Document; url: dom-document-visibilitystate
-
-spec: secure-contexts; urlPrefix: https://w3c.github.io/webappsec-secure-contexts/#
-    type: dfn
-        text: is origin potentially trustworthy; url: is-origin-trustworthy
-        text: potentially trustworthy url; url: potentially-trustworthy-url
-        text: risks associated with insecure contexts; url: threat-risks
-        text: secure context
-
-spec: quota-api; urlPrefix: http://www.w3.org/TR/quota-api/
-    type: attribute; for: ServiceWorkerGlobalScope
-        text: onbeforeevicted; url: widl-ServiceWorkerGlobalScope-onbeforeevicted
-        text: onevicted; url: widl-ServiceWorkerGlobalScope-onevicted
-
-spec: rfc5988; urlPrefix: https://tools.ietf.org/html/rfc5988
-    type: dfn
-        text: context IRI; url: section-5.2
-        text: target attribute; url: section-5.4
-        text: target IRI; url: section-5.1
-
-spec: rfc7230; urlPrefix: https://tools.ietf.org/html/rfc7230
-    type: dfn
-        text: field-value; for: http; url: section-3.2
-
-spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
-    type: dfn
-        text: Vary; url: section-7.1.4
-
-
-

Motivations

- - This section is non-normative. +

Motivations

-

Web Applications traditionally assume that the network is reachable. This assumption pervades the platform. HTML documents are loaded over HTTP and traditionally fetch all of their sub-resources via subsequent HTTP requests. This places web content at a disadvantage versus other technology stacks.

+ *This section is non-normative.* + + Web Applications traditionally assume that the network is reachable. This assumption pervades the platform. HTML documents are loaded over HTTP and traditionally fetch all of their sub-resources via subsequent HTTP requests. This places web content at a disadvantage versus other technology stacks. -

The service worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the service worker, conceptually, between the network and a document renderer, allowing the service worker to provide content for documents, even while offline.

+ The service worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the service worker, conceptually, between the network and a document renderer, allowing the service worker to provide content for documents, even while offline. -

Web developers familiar with previous attempts to solve the offline problem have reported a deficit of flexibility in those solutions. As a result, the service worker is highly procedural, providing a maximum of flexibility at the price of additional complexity for developers. Part of this complexity arises from the need to keep service workers responsive in the face of a single-threaded execution model. As a result, APIs exposed by service workers are almost entirely asynchronous, a pattern familiar in other JavaScript contexts but accentuated here by the need to avoid blocking document and resource loading.

+ Web developers familiar with previous attempts to solve the offline problem have reported a deficit of flexibility in those solutions. As a result, the service worker is highly procedural, providing a maximum of flexibility at the price of additional complexity for developers. Part of this complexity arises from the need to keep service workers responsive in the face of a single-threaded execution model. As a result, APIs exposed by service workers are almost entirely asynchronous, a pattern familiar in other JavaScript contexts but accentuated here by the need to avoid blocking document and resource loading. -

Developers using the HTML5 Application Cache have also reported that several attributes of the design contribute to unrecoverable errors. A key design principle of the service worker is that errors should always be recoverable. Many details of the update process of service workers are designed to avoid these hazards.

+ Developers using the HTML5 Application Cache have also reported that several attributes of the design contribute to unrecoverable errors. A key design principle of the service worker is that errors should *always* be recoverable. Many details of the update process of service workers are designed to avoid these hazards. -

Service workers are started and kept alive by their relationship to events, not documents. This design borrows heavily from developer and vendor experience with Shared Workers and Chrome Background Pages. A key lesson from these systems is the necessity to time-limit the execution of background processing contexts, both to conserve resources and to ensure that background context loss and restart is top-of-mind for developers. As a result, service workers bear more than a passing resemblance to Chrome Event Pages, the successor to Background Pages. Service workers may be started by user agents without an attached document and may be killed by the user agent at nearly any time. Conceptually, service workers can be thought of as Shared Workers that can start, process events, and die without ever handling messages from documents. Developers are advised to keep in mind that service workers may be started and killed many times a second.

+ Service workers are started and kept alive by their relationship to events, not documents. This design borrows heavily from developer and vendor experience with Shared Workers and Chrome Background Pages. A key lesson from these systems is the necessity to time-limit the execution of background processing contexts, both to conserve resources and to ensure that background context loss and restart is top-of-mind for developers. As a result, service workers bear more than a passing resemblance to Chrome Event Pages, the successor to Background Pages. Service workers may be started by user agents *without an attached document* and may be killed by the user agent at nearly any time. Conceptually, service workers can be thought of as Shared Workers that can start, process events, and die without ever handling messages from documents. Developers are advised to keep in mind that service workers may be started and killed many times a second. -

Service workers are generic, event-driven, time-limited script contexts that run at an origin. These properties make them natural endpoints for a range of runtime services that may outlive the context of a particular document, e.g. handling push notifications, background data synchronization, responding to resource requests from other origins, or receiving centralized updates to expensive-to-calculate data (e.g., geolocation or gyroscope).

+ Service workers are generic, event-driven, time-limited script contexts that run at an origin. These properties make them natural endpoints for a range of runtime services that may outlive the context of a particular document, e.g. handling push notifications, background data synchronization, responding to resource requests from other origins, or receiving centralized updates to expensive-to-calculate data (e.g., geolocation or gyroscope).

Model

-
+

Service Worker

-

A service worker is a type of web worker. A service worker executes in the registering service worker client's origin.

-

A service worker has an associated state, which is one of parsed, installing, installed, activating, activated, and redundant. It is initially parsed.

-

A service worker has an associated script url (a URL).

-

A service worker has an associated type which is either "classic" or "module". Unless stated otherwise, it is "classic".

-

A service worker has an associated containing service worker registration (a service worker registration), which contains itself.

-

A service worker has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration.

-

A service worker has an associated global object (a {{ServiceWorkerGlobalScope}} object or null).

-

A service worker is dispatched a set of lifecycle events, install and activate, and functional events including fetch.

-

A service worker has an associated script resource (a script), which represents its own script resource. It is initially set to null. A script resource has an associated has ever been evaluated flag. It is initially unset. A script resource has an associated HTTPS state (an HTTPS state value). It is initially "none". A script resource has an associated referrer policy (a referrer policy). It is initially the empty string.

-

A service worker has an associated script resource map which is a List of the Record {\[[key]], \[[value]]} where \[[key]] is a URL and \[[value]] is a response.

-

A service worker has an associated skip waiting flag. Unless stated otherwise it is unset.

-

A service worker has an associated imported scripts updated flag. It is initially unset.

-

A service worker has an associated set of event types to handle whose element type is an event listener's event type. It is initially set to null.

-

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.

+ A service worker is a type of web worker. A service worker executes in the registering service worker client's origin. + + A service worker has an associated state, which is one of *parsed*, *installing*, *installed*, *activating*, *activated*, and *redundant*. It is initially *parsed*. + + A service worker has an associated script url (a URL). + + A service worker has an associated type which is either "classic" or "module". Unless stated otherwise, it is "classic". + + A service worker has an associated containing service worker registration (a service worker registration), which contains itself. + + A service worker has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration. + + A service worker has an associated global object (a {{ServiceWorkerGlobalScope}} object or null). + + A service worker is dispatched a set of lifecycle events, install and activate, and functional events including fetch. + + A service worker has an associated script resource (a script), which represents its own script resource. It is initially set to null. + + A script resource has an associated has ever been evaluated flag. It is initially unset. + + A script resource has an associated HTTPS state (an HTTPS state value). It is initially "none". + + A script resource has an associated referrer policy (a referrer policy). It is initially the empty string. + + A service worker has an associated script resource map which is an ordered map where the keys are URLs and the values are responses. + + A service worker has an associated skip waiting flag. Unless stated otherwise it is unset. + + A service worker has an associated imported scripts updated flag. It is initially unset. + + A service worker has an associated set of event types to handle whose element type is an event listener's event type. It is initially set to null. + + 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.

Lifetime

-

The lifetime of a service worker is tied to the execution lifetime of events and not references held by service worker clients to the {{ServiceWorker}} object.

-

A user agent may terminate service workers at any time it:

-
    -
  • Has no event to handle.
  • -
  • Detects abnormal operation: such as infinite loops and tasks exceeding imposed time limits (if any) while handling the events.
  • -
+ The lifetime of a service worker is tied to the execution lifetime of events and not references held by service worker clients to the {{ServiceWorker}} object. + + A user agent *may* terminate service workers at any time it: + + * Has no event to handle. + * Detects abnormal operation: such as infinite loops and tasks exceeding imposed time limits (if any) while handling the events.

Service Worker Registration

-

A service worker registration is a tuple of a scope url and a set of service workers, an installing worker, a waiting worker, and an active worker. A user agent may enable many service worker registrations at a single origin so long as the scope url of the service worker registration differs. A service worker registration of an identical scope url when one already exists in the user agent causes the existing service worker registration to be replaced.

-

A service worker registration has an associated scope url (a URL).

-

A service worker registration has an associated registering script url (a URL).

-

A service worker registration has an associated installing worker (a service worker or null) whose state is installing. It is initially set to null.

-

A service worker registration has an associated waiting worker (a service worker or null) whose state is installed. It is initially set to null.

-

A service worker registration has an associated active worker (a service worker or null) whose state is either activating or activated. It is initially set to null.

-

A service worker registration has an associated last update check time. It is initially set to null.

-

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 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 task queues are not processed by any event loops in and of itself.

+ A service worker registration is a tuple of a scope url and a set of service workers, an installing worker, a waiting worker, and an active worker. A user agent *may* enable many service worker registrations at a single origin so long as the scope url of the service worker registration differs. A service worker registration of an identical scope url when one already exists in the user agent causes the existing service worker registration to be replaced. + + A service worker registration has an associated scope url (a URL). + + A service worker registration has an associated registering script url (a URL). + + A service worker registration has an associated installing worker (a service worker or null) whose state is *installing*. It is initially set to null. + + A service worker registration has an associated waiting worker (a service worker or null) whose state is *installed*. It is initially set to null. + + A service worker registration has an associated active worker (a service worker or null) whose state is either *activating* or *activated*. It is initially set to null. + + A service worker registration has an associated last update check time. It is initially set to null. + + 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 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 task queues are not processed by any event loops in and of itself.

Lifetime

- -

A user agent must persistently keep a list of registered service worker registrations unless otherwise they are explicitly unregistered. A user agent has a scope to registration map that stores the entries of the tuple of service worker registration's scope url and the corresponding service worker registration. The lifetime of service worker registrations is beyond that of the {{ServiceWorkerRegistration}} objects which represent them within the lifetime of their corresponding service worker clients.

+ + A user agent *must* persistently keep a list of registered service worker registrations unless otherwise they are explicitly unregistered. A user agent has a scope to registration map that stores the entries of the tuple of service worker registration's scope url and the corresponding service worker registration. The lifetime of service worker registrations is beyond that of the {{ServiceWorkerRegistration}} objects which represent them within the lifetime of their corresponding service worker clients.

Service Worker Client

-

A service worker client is a type of environment or environment settings object.

-

A service worker client has an algorithm defined as the origin that returns the service worker client's creation URL's origin if the service worker client is a type of environment, and the service worker client's origin otherwise.

+ A service worker client is a type of environment or environment settings object. -

A window client is a service worker client whose global object is a {{Window}} object.

+ A service worker client has an algorithm defined as the origin that returns the service worker client's creation URL's origin if the service worker client is a type of environment, and the service worker client's origin otherwise. -

A dedicated worker client is a service worker client whose global object is a {{DedicatedWorkerGlobalScope}} object.

+ A window client is a service worker client whose global object is a {{Window}} object. -

A shared worker client is a service worker client whose global object is a {{SharedWorkerGlobalScope}} object.

+ A dedicated worker client is a service worker client whose global object is a {{DedicatedWorkerGlobalScope}} object. -

A worker client is either a dedicated worker client or a shared worker client.

+ A shared worker client is a service worker client whose global object is a {{SharedWorkerGlobalScope}} object. + + A worker client is either a dedicated worker client or a shared worker client.

Selection and Use

-

A service worker client independently selects and uses a service worker registration for its own loading and its subresources. The selection of a service worker registration, upon a non-subresource request, is a process of either matching a service worker registration from scope to registration map or inheriting an existing service worker registration from its parent or owner context depending on the request's url.

+ A service worker client independently selects and uses a service worker registration for its own loading and its subresources. The selection of a service worker registration, upon a non-subresource request, is a process of either matching a service worker registration from scope to registration map or inheriting an existing service worker registration from its parent or owner context depending on the request's url. -

When the request's url is not local, a service worker client matches a service worker registration from scope to registration map. That is, the service worker client attempts to consult a service worker registration whose scope url matches its creation URL.

+ When the request's url is not local, a service worker client matches a service worker registration from scope to registration map. That is, the service worker client attempts to consult a service worker registration whose scope url matches its creation URL. -

When the request's url is local, if the service worker client's responsible browsing context is a nested browsing context or the service worker client is a worker client, the service worker client inherits the service worker registration from its parent browsing context's environment or one of the worker's Documents' environment, respectively, if it exists.

+ When the request's url is local, if the service worker client's responsible browsing context is a nested browsing context or the service worker client is a worker client, the service worker client inherits the service worker registration from its parent browsing context's environment or one of the worker's Documents' environment, respectively, if it exists. -

If the selection was successful, the selected service worker registration's active worker starts to control the service worker client. Otherwise, the flow returns to fetch where it falls back to the default behavior. When a service worker client is controlled by an active worker, it is considered that the service worker client is using the active worker's containing service worker registration.

+ If the selection was successful, the selected service worker registration's active worker starts to control the service worker client. Otherwise, the flow returns to fetch where it falls back to the default behavior. When a service worker client is controlled by an active worker, it is considered that the service worker client is using the active worker's containing service worker registration.

Task Sources

-

The following additional task sources are used by service workers.

- -
-
The handle fetch task source
-
This task source is used for dispatching fetch events to service workers.
-
The handle functional event task source
-
This task source is used for features that dispatch other functional events, e.g. push events, to service workers. -

A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events. For instance, a user agent may use a different task source for task events from other task sources.

-
-
+ The following additional task sources are used by service workers. + + : The handle fetch task source + :: This task source is used for dispatching fetch events to service workers. + : The handle functional event task source + :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. + + Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events. For instance, a user agent may use a different task source for task events from other task sources.

User Agent Shutdown

-

A user agent must maintain the state of its stored service worker registrations across restarts with the following rules: -

-

+ A user agent *must* maintain the state of its stored service worker registrations across restarts with the following rules: -

To attain this, the user agent must invoke Handle User Agent Shutdown when it terminates.

+ * An installing worker does not persist but discarded. If the installing worker was the only service worker for the service worker registration, the service worker registration is discarded. + * A waiting worker promotes to an active worker. + + To attain this, the user agent *must* invoke Handle User Agent Shutdown when it terminates.
-

Client Context

- Bootstrapping with a ServiceWorker: + Bootstrapping with a service worker: -
+    
       // scope defaults to the path the script sits in
       // "/" in this example
-      navigator.serviceWorker.register("/serviceworker.js").then(
-        function(registration) {
-          console.log("success!");
-          if (registration.installing) {
-            registration.installing.postMessage("Howdy from your installing page.");
-          }
-        },
-        function(why) {
-          console.error("Installing the worker failed!:", why);
-        });
+      navigator.serviceWorker.register("/serviceworker.js").then(registration => {
+        console.log("success!");
+        if (registration.installing) {
+          registration.installing.postMessage("Howdy from your installing page.");
+        }
+      }, err => {
+        console.error("Installing the worker failed!", err);
+      });
     
@@ -312,68 +228,64 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

A {{ServiceWorker}} object represents a service worker. Each {{ServiceWorker}} object is associated with a service worker. Multiple separate objects implementing the {{ServiceWorker}} interface across documents and workers can all be associated with the same service worker simultaneously.

+ A {{ServiceWorker}} object represents a service worker. Each {{ServiceWorker}} object is associated with a service worker. Multiple separate objects implementing the {{ServiceWorker}} interface across documents and workers can all be associated with the same service worker simultaneously. -

A {{ServiceWorker}} object has an associated {{ServiceWorkerState}} object which is itself associated with service worker's state.

+ A {{ServiceWorker}} object has an associated {{ServiceWorkerState}} object which is itself associated with service worker's state.

{{ServiceWorker/scriptURL}}

-

The scriptURL attribute must return the service worker's serialized script url.

+ The scriptURL attribute *must* return the service worker's serialized script url.
-

For example, consider a document created by a navigation to https://example.com/app.html which matches via the following registration call which has been previously executed:

+ For example, consider a document created by a navigation to https://example.com/app.html which matches via the following registration call which has been previously executed: -
+        
           // Script on the page https://example.com/app.html
-          navigator.serviceWorker.register("/service_worker.js", { scope: "/" });
+          navigator.serviceWorker.register("/service_worker.js");
         
-

The value of navigator.serviceWorker.controller.scriptURL will be "https://example.com/service_worker.js".

+ The value of navigator.serviceWorker.controller.scriptURL will be "https://example.com/service_worker.js".

{{ServiceWorker/state}}

-

The state attribute must return the value (in {{ServiceWorkerState}} enumeration) to which it was last set.

+ The state attribute *must* return the value (in {{ServiceWorkerState}} enumeration) to which it was last set.

{{ServiceWorker/postMessage(message, transfer)}}

-

The postMessage(message, transfer) method must run these steps:

- -
    -
  1. If the {{ServiceWorker/state}} attribute value of the context object is "redundant", throw an "{{InvalidStateError}}" exception and abort these steps.
  2. -
  3. Let serviceWorker be the service worker represented by the context object.
  4. -
  5. Invoke Run Service Worker algorithm with serviceWorker as the argument.
  6. -
  7. Let destination be the {{ServiceWorkerGlobalScope}} object associated with serviceWorker.
  8. -
  9. Let targetRealm be destination's Realm.
  10. -
  11. Let incumbentSettings be the incumbent settings object, and incumbentGlobal its global object.
  12. -
  13. Let cloneRecord be StructuredCloneWithTransfer(message, transfer, targetRealm). If this throws an exception, rethrow that exception and abort these steps.
  14. -
  15. Let clonedMessage be cloneRecord.\[[Clone]].
  16. -
  17. Let newPorts be a new frozen array consisting of all {{MessagePort}} objects in cloneRecord.\[[TransferList]], if any, maintaining their relative order.
  18. -
  19. Queue a task that runs the following steps: -
      -
    1. Create an event e that uses the {{ExtendableMessageEvent}} interface, with the event type {{message!!event}}, which does not bubble and is not cancelable.
    2. -
    3. Let the {{ExtendableMessageEvent/data}} attribute of e be initialized to clonedMessage.
    4. -
    5. Let the {{ExtendableMessageEvent/origin}} attribute of e be initialized to the Unicode serialization of incumbentSettings's origin.
    6. -
    7. If incumbentGlobal is a {{ServiceWorkerGlobalScope}} object, let the {{ExtendableMessageEvent/source}} attribute of e be initialized to a new {{ServiceWorker}} object that represents incumbentGlobal's service worker.
    8. -
    9. Else if incumbentGlobal is a {{Window}} object, let the {{ExtendableMessageEvent/source}} attribute of e be initialized to a new {{WindowClient}} object that represents incumbentGlobal's browsing context.
    10. -
    11. Else, let it be initialized to a new {{Client}} object that represents the worker associated with incumbentGlobal.
    12. -
    13. Let the {{ExtendableMessageEvent/ports}} attribute of e be initialized to newPorts.
    14. -
    15. Dispatch e at destination.
    16. -
    -

    The task must use the DOM manipulation task source.

    -
  20. -
+ The postMessage(|message|, |transfer|) method *must* run these steps: + + 1. If the {{ServiceWorker/state}} attribute value of the context object is "redundant", throw an "{{InvalidStateError}}" exception and abort these steps. + 1. Let |serviceWorker| be the service worker represented by the context object. + 1. Invoke Run Service Worker algorithm with |serviceWorker| as the argument. + 1. Let |destination| be the {{ServiceWorkerGlobalScope}} object associated with |serviceWorker|. + 1. Let |targetRealm| be |destination|'s Realm. + 1. Let |incumbentSettings| be the incumbent settings object, and |incumbentGlobal| its global object. + 1. Let |cloneRecord| be StructuredCloneWithTransfer(|message|, |transfer|, |targetRealm|). If this throws an exception, rethrow that exception and abort these steps. + 1. Let |clonedMessage| be |cloneRecord|.\[[Clone]]. + 1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order. + 1. Queue a task that runs the following steps: + 1. Create an event |e| that uses the {{ExtendableMessageEvent}} interface, with the event type {{message!!event}}, which does not bubble and is not cancelable. + 1. Let the {{ExtendableMessageEvent/data}} attribute of |e| be initialized to |clonedMessage|. + 1. Let the {{ExtendableMessageEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |incumbentSettings|'s origin. + 1. If |incumbentGlobal| is a {{ServiceWorkerGlobalScope}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{ServiceWorker}} object that represents |incumbentGlobal|'s service worker. + 1. Else if |incumbentGlobal| is a {{Window}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{WindowClient}} object that represents |incumbentGlobal|'s browsing context. + 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|. + + The task *must* use the DOM manipulation task source.

Event handler

-

The following is the event handler (and its corresponding event handler event type) that must be supported, as event handler IDL attributes, by all objects implementing {{ServiceWorker}} interface:

+ The following is the event handler (and its corresponding event handler event type) that *must* be supported, as event handler IDL attributes, by all objects implementing {{ServiceWorker}} interface: @@ -412,77 +324,75 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

A {{ServiceWorkerRegistration}} object represents a service worker registration. Each {{ServiceWorkerRegistration}} object is associated with a service worker registration (a service worker registration). Multiple separate objects implementing the {{ServiceWorkerRegistration}} interface across documents and workers can all be associated with the same service worker registration simultaneously.

+ A {{ServiceWorkerRegistration}} object represents a service worker registration. Each {{ServiceWorkerRegistration}} object is associated with a service worker registration (a service worker registration). Multiple separate objects implementing the {{ServiceWorkerRegistration}} interface across documents and workers can all be associated with the same service worker registration simultaneously.
-

installing attribute must return the value to which it was last set.

+ installing attribute *must* return the value to which it was last set. -

The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.

+ Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.
-

waiting attribute must return the value to which it was last set.

+ waiting attribute *must* return the value to which it was last set. -

The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.

+ Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.
-

active attribute must return the value to which it was last set.

+ active attribute *must* return the value to which it was last set. -

The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.

+ Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.

{{ServiceWorkerRegistration/scope}}

-

The scope attribute must return service worker registration's serialized scope url.

+ The scope attribute *must* return service worker registration's serialized scope url. -

In the example in section 3.1.1, the value of registration.scope, obtained from navigator.serviceWorker.ready.then(function(registration) { console.log(registration.scope); }) for example, will be "https://example.com/".

+
+ In the example in section 3.1.1, the value of registration.scope, obtained from navigator.serviceWorker.ready.then(registration => console.log(registration.scope)) for example, will be "https://example.com/". +

{{ServiceWorkerRegistration/update()}}

-

update() method must run these steps:

+ update() method *must* run these steps: -
    -
  1. Let p be a promise.
  2. -
  3. Let registration be the service worker registration.
  4. -
  5. Let newestWorker be the result of running Get Newest Worker algorithm passing registration as its argument.
  6. -
  7. If newestWorker is null, reject p with an "{{InvalidStateError}}" exception and abort these steps.
  8. -
  9. If the context object's relevant settings object's global object globalObject is a {{ServiceWorkerGlobalScope}} object, and globalObject's associated service worker's state is installing, reject p with an "{{InvalidStateError}}" exception and abort these steps.
  10. -
  11. Let job be the result of running Create Job with update, registration's scope url, newestWorker's script url, p, and the context object's relevant settings object client.
  12. -
  13. Set job's worker type to newestWorker's type.
  14. -
  15. Invoke Schedule Job with job.
  16. -
  17. Return p.
  18. -
+ 1. Let |p| be a promise. + 1. Let |registration| be the service worker registration. + 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. + 1. If |newestWorker| is null, reject |p| with an "{{InvalidStateError}}" exception and abort these steps. + 1. If the context object's relevant settings object's global object |globalObject| is a {{ServiceWorkerGlobalScope}} object, and |globalObject|'s associated service worker's state is *installing*, reject |p| with an "{{InvalidStateError}}" exception and abort these steps. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, |p|, and the context object's relevant settings object |client|. + 1. Set |job|'s worker type to |newestWorker|'s type. + 1. Invoke Schedule Job with |job|. + 1. Return |p|.
-

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 navigations. -

unregister() method must run these steps:

+ unregister() method *must* run these steps: -
    -
  1. Let p be a promise.
  2. -
  3. Let job be the result of running Create Job with unregister, the scope url of the service worker registration, null, p, and the context object's relevant settings object client.
  4. -
  5. Invoke Schedule Job with job.
  6. -
  7. Return p.
  8. -
+ 1. Let |p| be a promise. + 1. Let |job| be the result of running Create Job with *unregister*, the scope url of the service worker registration, null, |p|, and the context object's relevant settings object |client|. + 1. Invoke Schedule Job with |job|. + 1. Return |p|.

Event handler

-

The following is the event handler (and its corresponding event handler event type) that must be supported, as event handler IDL attributes, by all objects implementing {{ServiceWorkerRegistration}} interface:

+ The following is the event handler (and its corresponding event handler event type) that *must* be supported, as event handler IDL attributes, by all objects implementing {{ServiceWorkerRegistration}} interface:
@@ -494,7 +404,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - +
onupdatefoundupdatefoundupdatefound
@@ -514,7 +424,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

The serviceWorker attribute must return the {{ServiceWorkerContainer}} object that is associated with the context object.

+ The serviceWorker attribute *must* return the {{ServiceWorkerContainer}} object that is associated with the context object.
@@ -546,146 +456,114 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

The user agent must create a {{ServiceWorkerContainer}} object when a {{Navigator}} object or a {{WorkerNavigator}} object is created and associate it with that object.

+ The user agent *must* create a {{ServiceWorkerContainer}} object when a {{Navigator}} object or a {{WorkerNavigator}} object is created and associate it with that object. -

A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the service worker registrations, and provides access to the state of the service worker registrations and their associated service workers.

+ A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the service worker registrations, and provides access to the state of the service worker registrations and their associated service workers. -

A {{ServiceWorkerContainer}} has an associated service worker client, which is a service worker client whose global object is associated with the {{Navigator}} object or the {{WorkerNavigator}} object that the {{ServiceWorkerContainer}} is retrieved from.

+ A {{ServiceWorkerContainer}} has an associated service worker client, which is a service worker client whose global object is associated with the {{Navigator}} object or the {{WorkerNavigator}} object that the {{ServiceWorkerContainer}} is retrieved from. -

A {{ServiceWorkerContainer}} object has an associated ready promise (a promise). It is initially set to a new promise.

+ A {{ServiceWorkerContainer}} object has an associated ready promise (a promise). It is initially set to a new promise. -

A {{ServiceWorkerContainer}} object has a task source called the client message queue, initially empty. A client message queue can be enabled or disabled, and is initially disabled. When a {{ServiceWorkerContainer}} object's client message queue is enabled, the event loop must use it as one of its task sources. When the {{ServiceWorkerContainer}} object's relevant global object is a {{Window}} object, all tasks queued on its client message queue must be associated with its relevant settings object's responsible document.

+ A {{ServiceWorkerContainer}} object has a task source called the client message queue, initially empty. A client message queue can be enabled or disabled, and is initially disabled. When a {{ServiceWorkerContainer}} object's client message queue is enabled, the event loop *must* use it as one of its task sources. When the {{ServiceWorkerContainer}} object's relevant global object is a {{Window}} object, all tasks queued on its client message queue *must* be associated with its relevant settings object's responsible document.
-

controller attribute must run these steps:

+ controller attribute *must* run these steps: -
    -
  1. Let client be the context object's service worker client.
  2. -
  3. Return the {{ServiceWorker}} object that represents client's active service worker.
  4. -
+ 1. Let |client| be the context object's service worker client. + 1. Return the {{ServiceWorker}} object that represents |client|'s active service worker. -

{{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.

+ Note: {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. +
-
+
+ -
- + ready attribute *must* run these steps: -

ready attribute must run these steps:

+ + 1. If the context object's ready promise is settled, return the context object's ready promise. + 1. Let |client| be the context object's service worker client. + 1. Let |registration| be null. + 1. Let |clientURL| be |client|'s creation URL. + 1. Run the following substeps in parallel: + 1. *CheckRegistration*: If the result of running Match Service Worker Registration algorithm with |clientURL| as its argument is not null, then: + 1. Set |registration| to the result value. + 1. Else: + 1. Wait until scope to registration map has a new entry. + 1. Jump to the step labeled *CheckRegistration*. + 1. If |registration|'s active worker is null, wait until |registration|'s active worker changes. + + Note: Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm. + + 1. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Return context object's ready promise. + -
    -
  1. If the context object's ready promise is settled, return the context object's ready promise.
  2. -
  3. Let client be the context object's service worker client.
  4. -
  5. Let registration be null.
  6. -
  7. Let clientURL be client's creation URL.
  8. -
  9. Run the following substeps in parallel: -
      -
    1. CheckRegistration: If the result of running Match Service Worker Registration algorithm with clientURL as its argument is not null, then: -
        -
      1. Set registration to the result value.
      2. -
      -
    2. -
    3. Else: -
        -
      1. Wait until scope to registration map has a new entry.
      2. -
      3. Jump to the step labeled CheckRegistration.
      4. -
      -
    4. -
    5. If registration's active worker is null, wait until registration's active worker changes. -

      Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm.

      -
    6. -
    7. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents registration.
    8. -
    -
  10. -
  11. Return context object's ready promise.
  12. -
- -

When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker.

+ Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker.
-

The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a service worker registration for the given scope url. If successful, a service worker registration ties the provided scriptURL to a scope url, which is subsequently used for navigation matching.

+ Note: The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a service worker registration for the given scope url. If successful, a service worker registration ties the provided |scriptURL| to a scope url, which is subsequently used for navigation matching. -

register(scriptURL, options) method must run these steps:

+ register(|scriptURL|, |options|) method *must* run these steps: -
    -
  1. Let p be a promise.
  2. -
  3. Let client be the context object's service worker client.
  4. -
  5. Let scriptURL be the result of parsing scriptURL with the context object's relevant settings object's API base URL.
  6. -
  7. Let scopeURL be null.
  8. -
  9. If options.{{RegistrationOptions/scope}} is present, set scopeURL to the result of parsing options.{{RegistrationOptions/scope}} with the context object's relevant settings object's API base URL.
  10. -
  11. Invoke [[#start-register-algorithm]] with scopeURL, scriptURL, p, client, client's creation URL and options.{{RegistrationOptions/type}}.
  12. -
  13. Return p.
  14. -
+ 1. Let |p| be a promise. + 1. Let |client| be the context object's service worker client. + 1. Let |scriptURL| be the result of parsing |scriptURL| with the context object's relevant settings object's API base URL. + 1. Let |scopeURL| be null. + 1. If |options|.{{RegistrationOptions/scope}} is present, set |scopeURL| to the result of parsing |options|.{{RegistrationOptions/scope}} with the context object's relevant settings object's API base URL. + 1. Invoke [[#start-register-algorithm]] with |scopeURL|, |scriptURL|, |p|, |client|, |client|'s creation URL and |options|.{{RegistrationOptions/type}}. + 1. Return |p|.
-

getRegistration(clientURL) method must run these steps:

+ getRegistration(|clientURL|) method *must* run these steps: -
    -
  1. Let client be the context object's service worker client.
  2. -
  3. Let clientURL be the result of parsing clientURL with the context object's relevant settings object's API base URL.
  4. -
  5. If clientURL is failure, return a promise rejected with a TypeError.
  6. -
  7. If the origin of clientURL is not client's origin, return a promise rejected with a "{{SecurityError}}" exception.
  8. -
  9. Let promise be a new promise.
  10. -
  11. Run the following substeps in parallel: -
      -
    1. Let registration be the result of running Match Service Worker Registration algorithm with clientURL as its argument.
    2. -
    3. If registration is not null, then: -
        -
      1. Resolve promise with the {{ServiceWorkerRegistration}} object which represents registration.
      2. -
      -
    4. -
    5. Else: -
        -
      1. Resolve promise with undefined.
      2. -
      -
    6. -
    -
  12. -
  13. Return promise.
  14. -
+ 1. Let |client| be the context object's service worker client. + 1. Let |clientURL| be the result of parsing |clientURL| with the context object's relevant settings object's API base URL. + 1. If |clientURL| is failure, return a promise rejected with a TypeError. + 1. If the origin of |clientURL| is not |client|'s origin, return a |promise| rejected with a "{{SecurityError}}" exception. + 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. Let |registration| be the result of running Match Service Worker Registration algorithm with |clientURL| as its argument. + 1. If |registration| is not null, then: + 1. Resolve |promise| with the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Else: + 1. Resolve |promise| with undefined. + 1. Return |promise|.
-

getRegistrations() method must run these steps:

+ getRegistrations() method *must* run these steps: -
    -
  1. Let client be the context object's service worker client.
  2. -
  3. Let promise be a new promise.
  4. -
  5. Run the following substeps in parallel: -
      -
    1. Let array be an empty array.
    2. -
    3. For each Record {\[[key]], \[[value]]} entry of scope to registration map: -
        -
      1. If the origin of the result of parsing entry.\[[key]] is the same as client's origin, and entry.\[[value]]'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with entry.\[[value]] to the array.
      2. -
      -
    4. -
    5. Resolve promise with array.
    6. -
    -
  6. -
  7. Return promise.
  8. -
+ 1. Let |client| be the context object's service worker client. + 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. Let |array| be an empty array. + 1. For each Record {\[[key]], \[[value]]} |entry| of scope to registration map: + 1. If the origin of the result of parsing |entry|.\[[key]] is the same as |client|'s origin, and |entry|.\[[value]]'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |entry|.\[[value]] to the |array|. + 1. Resolve |promise| with |array|. + 1. Return |promise|.
-

startMessages() method must enable the context object's client message queue if it is not enabled.

+ startMessages() method *must* enable the context object's client message queue if it is not enabled.

Event handlers

-

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerContainer}} interface:

+ The following are the event handlers (and their corresponding event handler event types) that *must* be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerContainer}} interface: @@ -697,23 +575,22 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - + - +
oncontrollerchangecontrollerchangecontrollerchange
onmessagemessagemessage
-

The first time the context object's {{ServiceWorkerContainer/onmessage}} IDL attribute is set, its client message queue must be enabled.

+ The first time the context object's {{ServiceWorkerContainer/onmessage}} IDL attribute is set, its client message queue *must* be enabled.
-

Events

-

The following event is dispatched on {{ServiceWorker}} object:

+ The following event is dispatched on {{ServiceWorker}} object: @@ -732,7 +609,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
-

The following event is dispatched on {{ServiceWorkerRegistration}} object:

+ The following event is dispatched on {{ServiceWorkerRegistration}} object: @@ -746,12 +623,12 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - +
updatefound {{Event}}The service worker registration's installing worker changes. (See step 8 of the Install algorithm.)The service worker registration's installing worker changes. (See step 8 of the Install algorithm.)
-

The following events are dispatched on {{ServiceWorkerContainer}} object:

+ The following events are dispatched on {{ServiceWorkerContainer}} object: @@ -765,7 +642,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - +
controllerchange {{Event}}The service worker client's active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a service worker causes activation of the service worker registration to occur while service worker clients are using the service worker registration, {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the service worker that controls the service worker client.)The service worker client's active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a service worker causes activation of the service worker registration to occur while service worker clients are using the service worker registration, {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the service worker that controls the service worker client.)
@@ -778,12 +655,12 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
Serving Cached Resources: -
+    
       // caching.js
-      this.addEventListener("install", function(e) {
-        e.waitUntil(
+      self.addEventListener("install", event => {
+        event.waitUntil(
           // Open a cache of resources.
-          caches.open("shell-v1").then(function(cache) {
+          caches.open("shell-v1").then(cache => {
             // Begins the process of fetching them.
             // The coast is only clear when all the resources are ready.
             return cache.addAll([
@@ -797,16 +674,16 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
         );
       });
 
-      this.addEventListener("fetch", function(e) {
+      self.addEventListener("fetch", event => {
         // No "fetch" events are dispatched to the service worker until it
         // successfully installs and activates.
 
         // All operations on caches are async, including matching URLs, so we use
         // promises heavily. e.respondWith() even takes promises to enable this:
-        e.respondWith(
-          caches.match(e.request).then(function(response) {
+        event.respondWith(
+          caches.match(e.request).then(response => {
             return response || fetch(e.request);
-          }).catch(function() {
+          }).catch(() => {
             return caches.match("/fallback.html");
           })
         );
@@ -837,50 +714,42 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
       };
     
-

A {{ServiceWorkerGlobalScope}} object represents the global execution context of a service worker. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a service worker).

+ A {{ServiceWorkerGlobalScope}} object represents the global execution context of a service worker. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a service worker). -

{{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a service worker is started, kept alive and killed by their relationship to events, not service worker clients. Any type of synchronous requests must not be initiated inside of a service worker.

+ Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a service worker is started, kept alive and killed by their relationship to events, not service worker clients. Any type of synchronous requests must not be initiated inside of a service worker.

{{ServiceWorkerGlobalScope/clients}}

-

clients attribute must return the {{Clients}} object that is associated with the context object.

+ clients attribute *must* return the {{Clients}} object that is associated with the context object.

{{ServiceWorkerGlobalScope/registration}}

-

The registration attribute must return the {{ServiceWorkerRegistration}} object that represents the service worker's containing service worker registration.

+ The registration attribute *must* return the {{ServiceWorkerRegistration}} object that represents the service worker's containing service worker registration.

{{ServiceWorkerGlobalScope/skipWaiting()}}

-

The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this service worker to progress from the registration's waiting position to active even while service worker clients are using the registration.

+ Note: The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this service worker to progress from the registration's waiting position to active even while service worker clients are using the registration. -

skipWaiting() method must run these steps:

+ skipWaiting() method *must* run these steps: -
    -
  1. Let promise be a new promise.
  2. -
  3. Run the following substeps in parallel: -
      -
    1. Set service worker's skip waiting flag.
    2. -
    3. If service worker's state is installed, then: -
        -
      1. Run Activate algorithm passing service worker's registration as the argument.
      2. -
      -
    4. -
    5. Resolve promise with undefined.
    6. -
    -
  4. -
  5. Return promise.
  6. -
+ 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. Set service worker's skip waiting flag. + 1. If service worker's state is installed, then: + 1. Run Activate algorithm passing service worker's registration as the argument. + 1. Resolve |promise| with undefined. + 1. Return |promise|.

Event handlers

-

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerGlobalScope}} interface:

+ The following are the event handlers (and their corresponding event handler event types) that *must* be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerGlobalScope}} interface: @@ -892,19 +761,19 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - + - + - + - + @@ -937,152 +806,128 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

A {{Client}} object has an associated service worker client (a service worker client).

+ A {{Client}} object has an associated service worker client (a service worker client). -

A {{Client}} object has an associated reserved state, which is either true or false.

+ A {{Client}} object has an associated reserved state, which is either true or false. -

A {{WindowClient}} object has an associated visibility state, which is one of {{Document/visibilityState}} attribute value.

+ A {{WindowClient}} object has an associated visibility state, which is one of {{Document/visibilityState}} attribute value. -

A {{WindowClient}} object has an associated focus state, which is either true or false (initially false).

+ A {{WindowClient}} object has an associated focus state, which is either true or false (initially false). -

A {{WindowClient}} object has an associated ancestor origins array.

+ A {{WindowClient}} object has an associated ancestor origins array.

{{Client/url}}

-

The url attribute must return the context object's associated service worker client's serialized creation URL.

+ The url attribute *must* return the context object's associated service worker client's serialized creation URL.

{{Client/id}}

-

The id attribute must return its associated service worker client's id.

+ The id attribute *must* return its associated service worker client's id.

{{Client/reserved}}

-

The reserved attribute must return the context object's associated reserved state.

+ The reserved attribute *must* return the context object's associated reserved state.

{{Client/postMessage(message, transfer)}}

-

The postMessage(message, transfer) method must run these steps:

+ The postMessage(|message|, |transfer|) method *must* run these steps: -
    -
  1. Let sourceSettings be the context object's relevant settings object.
  2. -
  3. Let destination be the {{ServiceWorkerContainer}} object whose service worker client is the context object's service worker client.
  4. -
  5. If destination is null, throw an "{{InvalidStateError}}" exception.
  6. -
  7. Let targetRealm be destination's relevant Realm.
  8. -
  9. Let cloneRecord be StructuredCloneWithTransfer(message, transfer, targetRealm). If this throws an exception, rethrow that exception and abort these steps.
  10. -
  11. Let clonedMessage be cloneRecord.\[[Clone]].
  12. -
  13. Let newPorts be a new frozen array consisting of all {{MessagePort}} objects in cloneRecord.\[[TransferList]], if any, maintaining their relative order.
  14. -
  15. Add a task that runs the following steps to destination's client message queue: -
      -
    1. Create an event e that uses the {{MessageEvent}} interface, with the event type message, which does not bubble and is not cancelable.
    2. -
    3. Let the data attribute of e be initialized to clonedMessage.
    4. -
    5. Let the origin attribute of e be initialized to the Unicode serialization of sourceSettings's origin.
    6. -
    7. Let the source attribute of e be initialized to a {{ServiceWorker}} object, which represents the service worker associated with sourceSettings's global object.
    8. -
    9. Let the ports attribute of e be initialized to newPorts.
    10. -
    11. Dispatch e at destination.
    12. -
    -
  16. -
+ 1. Let |sourceSettings| be the context object's relevant settings object. + 1. Let |destination| be the {{ServiceWorkerContainer}} object whose service worker client is the context object's service worker client. + 1. If |destination| is null, throw an "{{InvalidStateError}}" exception. + 1. Let |targetRealm| be |destination|'s relevant Realm. + 1. Let |cloneRecord| be StructuredCloneWithTransfer(|message|, |transfer|, |targetRealm|). If this throws an exception, rethrow that exception and abort these steps. + 1. Let |clonedMessage| be |cloneRecord|.\[[Clone]]. + 1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order. + 1. Add a task that runs the following steps to |destination|'s client message queue: + 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type message, which does not bubble and is not cancelable. + 1. Let the data attribute of |e| be initialized to |clonedMessage|. + 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s origin. + 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the service worker associated with |sourceSettings|'s global object. + 1. Let the ports attribute of |e| be initialized to |newPorts|. + 1. Dispatch |e| at |destination|.

{{WindowClient/visibilityState}}

-

The visibilityState attribute must return the context object's visibility state.

+ The visibilityState attribute *must* return the context object's visibility state.

{{WindowClient/focused}}

-

The focused attribute must return the context object's focus state.

+ The focused attribute *must* return the context object's focus state.

{{WindowClient/ancestorOrigins}}

-

The ancestorOrigins attribute must return the context object's associated service worker client's ancestor origins array.

+ The ancestorOrigins attribute *must* return the context object's associated service worker client's ancestor origins array.

{{WindowClient/focus()}}

-

The focus() method must run these steps:

- -
    -
  1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception.
  2. -
  3. Let promise be a new promise.
  4. -
  5. Run these substeps in parallel: -
      -
    1. Let browsingContext be the context object's associated service worker client's global object's browsing context.
    2. -
    3. Let visibilityState be null.
    4. -
    5. Let focusState be false.
    6. -
    7. Let ancestorOrigins be the empty array.
    8. -
    9. Queue a task task to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: -
        -
      1. Run the focusing steps with browsingContext.
      2. -
      3. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
      4. -
      5. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
      6. -
      7. Set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
      8. -
      -
    10. -
    11. Wait for task to have executed.
    12. -
    13. Let windowClient be the result of running Create Window Client algorithm with the context object's associated service worker client, visibilityState, focusState, and ancestorOrigins as the arguments.
    14. -
    15. If windowClient's focus state is true, resolve promise with windowClient.
    16. -
    17. Else, reject promise with a TypeError.
    18. -
    -
  6. -
  7. Return promise.
  8. -
+ The focus() method *must* run these steps: + + 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: + 1. Run the focusing steps with |browsingContext|. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed. + 1. Let |windowClient| be the result of running Create Window Client algorithm with the context object's associated service worker client, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. If |windowClient|'s focus state is true, resolve |promise| with |windowClient|. + 1. Else, reject |promise| with a TypeError. + 1. Return |promise|.

{{WindowClient/navigate(url)}}

-

The navigate() method must run these steps:

- -
    -
  1. Let url be the result of parsing url with the context object's relevant settings object's API base URL.
  2. -
  3. If url is failure, return a promise rejected with a TypeError.
  4. -
  5. If url is about:blank, return a promise rejected with a TypeError.
  6. -
  7. If the context object's associated service worker client's active service worker is not the context object's relevant global object's service worker, return a promise rejected with a TypeError.
  8. -
  9. Let promise be a new promise.
  10. -
  11. Run these substeps in parallel: -
      -
    1. Let browsingContext be the context object's associated service worker client's global object's browsing context.
    2. -
    3. If browsingContext has discarded its {{Document}}, reject promise with a TypeError and abort these steps.
    4. -
    5. Let navigateFailed to false.
    6. -
    7. Let visibilityState be null.
    8. -
    9. Let focusState be false.
    10. -
    11. Let ancestorOrigins be the empty array.
    12. -
    13. Queue a task task to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: -
        -
      1. HandleNavigate: Navigate browsingContext to url with exceptions enabled. The source browsing context must be browsingContext.
      2. -
      3. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set navigateFailed to true.
      4. -
      5. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
      6. -
      7. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
      8. -
      9. Set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
      10. -
      -
    14. -
    15. Wait for task to have executed (including its asynchronous steps).
    16. -
    17. If navigateFailed is true, reject promise with a TypeError and abort these steps.
    18. -
    19. If browsingContext's {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: -
        -
      1. Resolve promise with null.
      2. -
      3. Abort these steps.
      4. -
      -
    20. -
    21. Let windowClient be the result of running Create Window Client algorithm with browsingContext's {{Window}} object's environment settings object, visibilityState, focusState, and ancestorOrigins as the arguments.
    22. -
    23. Resolve promise with windowClient.
    24. -
    -
  12. -
  13. Return promise.
  14. -
+ The navigate() method *must* run these steps: + + 1. Let |url| be the result of parsing |url| with the context object's relevant settings object's API base URL. + 1. If |url| is failure, return a promise rejected with a TypeError. + 1. If |url| is about:blank, return a promise rejected with a TypeError. + 1. If the context object's associated service worker client's active service worker is not the context object's relevant global object's service worker, return a promise rejected with a TypeError. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. + 1. If |browsingContext| has discarded its {{Document}}, reject |promise| with a TypeError and abort these steps. + 1. Let |navigateFailed| to false. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: + 1. HandleNavigate: Navigate |browsingContext| to |url| with exceptions enabled. The source browsing context must be |browsingContext|. + 1. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set |navigateFailed| to true. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed (including its asynchronous steps). + 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. + 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. Resolve |promise| with null. + 1. Abort these steps. + 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |windowClient|. + 1. Return |promise|.
@@ -1115,235 +960,144 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

The user agent must create a {{Clients}} object when a {{ServiceWorkerGlobalScope}} object is created and associate it with that object.

+ The user agent *must* create a {{Clients}} object when a {{ServiceWorkerGlobalScope}} object is created and associate it with that object.

{{Clients/get(id)}}

-

The get(id) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. For each service worker client client whose origin is the same as the associated service worker's origin: -
        -
      1. If client's id is not id, continue to the next iteration of the loop.
      2. -
      3. If client is a type of environment, then: -
          -
        1. If client’s creation URL is not a potentially trustworthy URL, reject promise with a "{{SecurityError}}" exception and abort these steps.
        2. -
        -
      4. -
      5. Else: -
          -
        1. If client is not a secure context, reject promise with a "{{SecurityError}}" exception and abort these steps.
        2. -
        -
      6. -
      7. If client is a type of environment or is a window client, then: -
          -
        1. Let browsingContext be null.
        2. -
        3. Let visibilityState be null.
        4. -
        5. Let focusState be false.
        6. -
        7. Let ancestorOrigins be the empty array.
        8. -
        9. If client is a type of environment, set browsingContext to client’s target browsing context.
        10. -
        11. Else, set browsingContext to client's global object's browsing context.
        12. -
        13. Queue a task task to run the following substeps on browsingContext's event loop using the user interaction task source: -
            -
          1. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
          2. -
          3. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
          4. -
          5. If client is a window client, set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
          6. -
          -
        14. -
        15. Wait for task to have executed.
        16. -
        17. Let windowClient be the result of running Create Window Client algorithm with client, visibilityState, focusState, and ancestorOrigins as the arguments.
        18. -
        19. Resolve promise with windowClient and abort these steps.
        20. -
        -
      8. -
      9. Else: -
          -
        1. Let clientObject be the result of running Create Client algorithm with client as the argument.
        2. -
        3. Resolve promise with clientObject and abort these steps.
        4. -
        -
      10. -
      -
    2. -
    3. Resolve promise with undefined.
    4. -
    -
  4. -
  5. Return promise.
  6. -
+ The get(|id|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: + 1. If |client|'s id is not |id|, continue to the next iteration of the loop. + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, reject |promise| with a "{{SecurityError}}" exception and abort these steps. + 1. Else: + 1. If |client| is not a secure context, reject |promise| with a "{{SecurityError}}" exception and abort these steps. + 1. If |client| is a type of environment or is a window client, then: + 1. Let |browsingContext| be null. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. + 1. Else, set |browsingContext| to |client|'s global object's browsing context. + 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed. + 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |windowClient| and abort these steps. + 1. Else: + 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. + 1. Resolve |promise| with |clientObject| and abort these steps. + 1. Resolve |promise| with undefined. + 1. Return |promise|.

{{Clients/matchAll(options)}}

-

The matchAll(options) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. Let targetClients be an empty array.
    2. -
    3. For each service worker client client whose origin is the same as the associated service worker's origin: -
        -
      1. If client is a type of environment, then: -
          -
        1. If client’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop.
        2. -
        -
      2. -
      3. Else: -
          -
        1. If client is not a secure context, continue to the next iteration of the loop.
        2. -
        -
      4. -
      5. If options.{{ClientQueryOptions/includeUncontrolled}} is false, then: -
          -
        1. If client's active service worker is not the associated service worker, continue to the next iteration of the loop.
        2. -
        -
      6. -
      7. If options.{{ClientQueryOptions/includeReserved}} is false, then: -
          -
        1. If client's execution ready flag is unset, continue to the next iteration of the loop.
        2. -
        -
      8. -
      9. Add client to targetClients.
      10. -
      -
    4. -
    5. Let matchedClients be an empty array.
    6. -
    7. For each service worker client client in targetClients: -
        -
      1. If options.{{ClientQueryOptions/type}} is "window" or "all", and client is a type of environment or is a window client, then: -
          -
        1. Let browsingContext be null.
        2. -
        3. Let isClientEnumerable be true.
        4. -
        5. Let visibilityState be the empty string.
        6. -
        7. Let focusState be false.
        8. -
        9. Let ancestorOrigins be the empty array.
        10. -
        11. If client is a type of environment, set browsingContext to client’s target browsing context.
        12. -
        13. Else, set browsingContext to client's global object's browsing context.
        14. -
        15. Queue a task task to run the following substeps on browsingContext's event loop using the user interaction task source: -
            -
          1. If browsingContext has been discarded, set isClientEnumerable to false and abort these steps.
          2. -
          3. If client is a window client and client's responsible document is not browsingContext's active document, set isClientEnumerable to false and abort these steps.
          4. -
          5. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
          6. -
          7. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
          8. -
          9. It client is a window client, set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
          10. -
          -
        16. -
        17. Wait for task to have executed. -

          Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken.

          -
        18. -
        19. If isClientEnumerable is true, then: -
            -
          1. Let windowClient be the result of running Create Window Client algorithm with client, visibilityState, focusState, and ancestorOrigins as the arguments.
          2. -
          3. Add windowClient to matchedClients.
          4. -
          -
        20. -
        -
      2. -
      3. Else if options.{{ClientQueryOptions/type}} is "worker" or "all" and client is a dedicated worker client, or options.{{ClientQueryOptions/type}} is "sharedworker" or "all" and client is a shared worker client, then: -
          -
        1. Let clientObject be the result of running Create Client algorithm with client as the argument.
        2. -
        3. Add clientObject to matchedClients.
        4. -
        -
      4. -
      -
    8. -
    9. Sort matchedClients such that: - -
    10. -
    11. Resolve promise with matchedClients.
    12. -
    -
  4. -
  5. Return promise.
  6. -
+ The matchAll(|options|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |targetClients| be an empty array. + 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. + 1. Else: + 1. If |client| is not a secure context, continue to the next iteration of the loop. + 1. If |options|.{{ClientQueryOptions/includeUncontrolled}} is false, then: + 1. If |client|'s active service worker is not the associated service worker, continue to the next iteration of the loop. + 1. If |options|.{{ClientQueryOptions/includeReserved}} is false, then: + 1. If |client|'s execution ready flag is unset, continue to the next iteration of the loop. + 1. Add |client| to |targetClients|. + 1. Let |matchedClients| be an empty array. + 1. For each service worker client |client| in |targetClients|: + 1. If |options|.{{ClientQueryOptions/type}} is "window" or "all", and |client| is a type of environment or is a window client, then: + 1. Let |browsingContext| be null. + 1. Let |isClientEnumerable| be true. + 1. Let |visibilityState| be the empty string. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. + 1. Else, set |browsingContext| to |client|'s global object's browsing context. + 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: + 1. If |browsingContext| has been discarded, set |isClientEnumerable| to false and abort these steps. + 1. If |client| is a window client and |client|'s responsible document is not |browsingContext|'s active document, set |isClientEnumerable| to false and abort these steps. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed. + Note: Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken. + 1. If |isClientEnumerable| is true, then: + 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Add |windowClient| to |matchedClients|. + 1. Else if |options|.{{ClientQueryOptions/type}} is "worker" or "all" and |client| is a dedicated worker client, or |options|.{{ClientQueryOptions/type}} is "sharedworker" or "all" and |client| is a shared worker client, then: + 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. + 1. Add |clientObject| to |matchedClients|. + 1. Sort |matchedClients| such that: + * {{WindowClient}} objects are always placed before {{Client}} objects whose associated service worker clients are worker clients. + * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their service worker clients' creation order. + * {{Client}} objects whose associated service worker clients are worker clients are placed next sorted in their service worker clients' creation order. + 1. Resolve |promise| with |matchedClients|. + 1. Return |promise|.

{{Clients/openWindow(url)}}

-

The openWindow(url) method must run these steps:

- -
    -
  1. Let url be the result of parsing url with the context object's relevant settings object's API base URL.
  2. -
  3. If url is failure, return a promise rejected with a TypeError.
  4. -
  5. If url is about:blank, return a promise rejected with a TypeError.
  6. -
  7. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception.
  8. -
  9. Let promise be a new promise.
  10. -
  11. Run these substeps in parallel: -
      -
    1. Let newContext be a new top-level browsing context.
    2. -
    3. Let openWindowFailed to false.
    4. -
    5. Let visibilityState be null.
    6. -
    7. Let focusState be false.
    8. -
    9. Let ancestorOrigins be the empty array.
    10. -
    11. Queue a task task to run the following substeps on newContext's {{Window}} object's environment settings object's responsible event loop using the user interaction task source: -
        -
      1. HandleNavigate: Navigate newContext to url with exceptions enabled and replacement enabled.
      2. -
      3. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set openWindowFailed to true.
      4. -
      5. Set visibilityState to newContext's active document's {{Document/visibilityState}} attribute value.
      6. -
      7. Set focusState to the result of running the has focus steps with newContext's active document as the argument.
      8. -
      9. Set ancestorOrigins to newContext's active document's relevant global object's {{Location}} object's ancestor origins array.
      10. -
      -
    12. -
    13. Wait for task to have executed (including its asynchronous steps).
    14. -
    15. If openWindowFailed is true, reject promise with a TypeError and abort these steps.
    16. -
    17. If newContext's {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: -
        -
      1. Resolve promise with null.
      2. -
      3. Abort these steps.
      4. -
      -
    18. -
    19. Let client be the result of running Create Window Client algorithm with newContext's {{Window}} object's environment settings object, visibilityState, focusState, and ancestorOrigins as the arguments.
    20. -
    21. Resolve promise with client.
    22. -
    -
  12. -
  13. Return promise.
  14. -
+ The openWindow(|url|) method *must* run these steps: + 1. Let |url| be the result of parsing |url| with the context object's relevant settings object's API base URL. + 1. If |url| is failure, return a promise rejected with a TypeError. + 1. If |url| is about:blank, return a promise rejected with a TypeError. + 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |newContext| be a new top-level browsing context. + 1. Let |openWindowFailed| to false. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on |newContext|'s {{Window}} object's environment settings object's responsible event loop using the user interaction task source: + 1. HandleNavigate: Navigate |newContext| to |url| with exceptions enabled and replacement enabled. + 1. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set |openWindowFailed| to true. + 1. Set |visibilityState| to |newContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |newContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed (including its asynchronous steps). + 1. If |openWindowFailed| is true, reject |promise| with a TypeError and abort these steps. + 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. Resolve |promise| with null. + 1. Abort these steps. + 1. Let |client| be the result of running Create Window Client algorithm with |newContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |client|. + 1. Return |promise|.

{{Clients/claim()}}

-

The claim() method must run these steps:

+ The claim() method *must* run these steps: -
    -
  1. If the service worker is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception.
  2. -
  3. Let promise be a new promise.
  4. -
  5. Run the following substeps in parallel: -
      -
    1. For each service worker client client whose origin is the same as the service worker's origin: -
        -
      1. If client is a type of environment, then: -
          -
        1. If client’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop.
        2. -
        -
      2. -
      3. Else: -
          -
        1. If client is not a secure context, continue to the next iteration of the loop.
        2. -
        -
      4. -
      5. Let registration be the result of running Match Service Worker Registration algorithm passing client's creation URL as the argument.
      6. -
      7. If registration is not the service worker's containing service worker registration, continue to the next iteration of the loop.
      8. -
      9. If client's active service worker is not the service worker, then: -
          -
        1. Invoke Handle Service Worker Client Unload with client as the argument.
        2. -
        3. Set client's active service worker to service worker.
        4. -
        5. Invoke Notify Controller Change algorithm with client as the argument.
        6. -
        -
      10. -
      -
    2. -
    3. Resolve promise with undefined.
    4. -
    -
  6. -
  7. Return promise.
  8. -
+ 1. If the service worker is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception. + 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. For each service worker client |client| whose origin is the same as the service worker's origin: + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. + 1. Else: + 1. If |client| is not a secure context, continue to the next iteration of the loop. + 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 service worker's containing service worker registration, continue to the next iteration of the loop. + 1. If |client|'s active service worker is not the service worker, then: + 1. Invoke Handle Service Worker Client Unload with |client| as the argument. + 1. Set |client|'s active service worker to service worker. + 1. Invoke Notify Controller Change algorithm with |client| as the argument. + 1. Resolve |promise| with undefined. + 1. Return |promise|.
@@ -1362,42 +1116,35 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

An {{ExtendableEvent}} object has an associated extend lifetime promises (an array of promises). It is initially an empty array.

+ An {{ExtendableEvent}} object has an associated extend lifetime promises (an array of promises). It is initially an empty array. -

An {{ExtendableEvent}} object has an associated extensions allowed flag. It is initially set.

+ An {{ExtendableEvent}} object has an associated extensions allowed flag. It is initially set. -

Service workers have two lifecycle events, install and activate. Service workers use the {{ExtendableEvent}} interface for activate event and install event.

+ Service workers have two lifecycle events, install and activate. Service workers use the {{ExtendableEvent}} interface for activate event and install event. -

Service worker extensions that define event handlers may also use or extend the {{ExtendableEvent}} interface.

+ Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. -

To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run Extend Service Worker Lifetime algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event.

+ Note: To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run Extend Service Worker Lifetime algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event.

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

-

{{ExtendableEvent/waitUntil(f)}} method extends the lifetime of the event.

+ {{ExtendableEvent/waitUntil(f)}} method extends the lifetime of the event. -

waitUntil(f) method must run these steps:

+ waitUntil(|f|) method *must* run these steps: -
    -
  1. If the extensions allowed flag is unset, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  2. -
  3. Add f to the extend lifetime promises.
  4. -
+ 1. If the extensions allowed flag is unset, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. Add |f| to the extend lifetime promises.
-

Service workers and extensions that define event handlers may define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure.

+ Service workers and extensions that define event handlers *may* define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure. -

Service workers define the following behaviors for install event and activate event, respectively:

+ Service workers define the following behaviors for install event and activate event, respectively: - + * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as installed (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered installed (i.e. a waiting worker) until all of the core caches it depends on are populated. + * Adding a promise to the event's extend lifetime promises delays treating the active worker as activated until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries.
@@ -1418,43 +1165,30 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231

{{InstallEvent/registerForeignFetch(options)|event.registerForeignFetch(options)}}

-

{{InstallEvent/registerForeignFetch(options)}} registers this service worker to handle foreign fetches from certain origins for certain sub scopes.

- -

registerForeignFetch(options) method must run these steps:

-
    -
  1. If the dispatch flag is unset, then: -
      -
    1. Throw an "InvalidStateError" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  2. -
  3. If options.{{ForeignFetchOptions/origins}} is empty throw a TypeError and abort these steps.
  4. -
  5. Let originURLs be an empty list of URLs.
  6. -
  7. If the value of options.{{ForeignFetchOptions/origins}} is not a single string equal to a single U+002A ASTERISK character (*): -
      -
    1. For each origin in options.origins: -
        -
      1. If the value of origin is not an absolute-URL string, throw a TypeError and abort these steps.
      2. -
      3. Add the result of parsing origin to originURLs.
      4. -
      -
    2. -
    -
  8. -
  9. If options.{{ForeignFetchOptions/scopes}} is empty throw a TypeError and abort these steps.
  10. -
  11. Let scopeString be the context object's relevant global object's service worker's containing service worker registration's scope url, serialized.
  12. -
  13. Let subScopeURLs be an empty list of URLs.
  14. -
  15. For each subScope in options.{{ForeignFetchOptions/scopes}}: -
      -
    1. Let subScopeURL be the result of parsing subScope with context object's relevant settings object's API base URL.
    2. -
    3. If subScopeURL is failure, throw a TypeError and abort these steps.
    4. -
    5. Let subScopeString be the serialized subScopeURL.
    6. -
    7. If subScopeString does not start with scopeString, throw a TypeError and abort these steps.
    8. -
    9. Add subScopeURL to subScopeURLs.
    10. -
    -
  16. -
  17. Set this service worker's list of foreign fetch scopes to subScopeURLs.
  18. -
  19. Set this service worker's list of foreign fetch origins to originURLs.
  20. -
+ {{InstallEvent/registerForeignFetch(options)}} registers this service worker to handle foreign fetches from certain origins for certain sub scopes. + + registerForeignFetch(|options|) method *must* run these steps: + + 1. If the dispatch flag is unset, then: + 1. Throw an "InvalidStateError" exception. + 1. Abort these steps. + 1. If |options|.{{ForeignFetchOptions/origins}} is empty throw a TypeError and abort these steps. + 1. Let |originURLs| be an empty list of URLs. + 1. If the value of |options|.{{ForeignFetchOptions/origins}} is not a single string equal to a single U+002A ASTERISK character (*): + 1. For each |origin| in |options|.|origins|: + 1. If the value of |origin| is not an absolute-URL string, throw a TypeError and abort these steps. + 1. Add the result of parsing |origin| to |originURLs|. + 1. If |options|.{{ForeignFetchOptions/scopes}} is empty throw a TypeError and abort these steps. + 1. Let |scopeString| be the context object's relevant global object's service worker's containing service worker registration's scope url, serialized. + 1. Let |subScopeURLs| be an empty list of URLs. + 1. For each |subScope| in |options|.{{ForeignFetchOptions/scopes}}: + 1. Let |subScopeURL| be the result of parsing |subScope| with context object's relevant settings object's API base URL. + 1. If |subScopeURL| is failure, throw a TypeError and abort these steps. + 1. Let |subScopeString| be the serialized |subScopeURL|. + 1. If |subScopeString| does not start with |scopeString|, throw a TypeError and abort these steps. + 1. Add |subScopeURL| to |subScopeURLs|. + 1. Set this service worker's list of foreign fetch scopes to |subScopeURLs|. + 1. Set this service worker's list of foreign fetch origins to |originURLs|.
@@ -1483,147 +1217,112 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

Service workers have an essential functional event fetch. For fetch event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface.

+ Service workers have an essential functional eventfetch. For fetch event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. -

Each event using {{FetchEvent}} interface has an associated potential response (a response), initially set to null, and the following associated flags that are initially unset: -

    -
  • wait to respond flag
  • -
  • respond-with entered flag
  • -
  • respond-with error flag
  • -
-

+ Each event using {{FetchEvent}} interface has an associated potential response (a response), initially set to null, and the following associated flags that are initially unset: + + * wait to respond flag + * respond-with entered flag + * respond-with error flag +

{{FetchEvent/request|event.request}}

-

request attribute must return the value it was initialized to.

+ request attribute *must* return the value it was initialized to.

{{FetchEvent/clientId|event.clientId}}

-

clientId attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

+ clientId attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to the empty string.

{{FetchEvent/reservedClientId|event.reservedClientId}}

-

reservedClientId attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

+ reservedClientId attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to the empty string.

{{FetchEvent/targetClientId|event.targetClientId}}

-

targetClientId attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

+ targetClientId attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to the empty string.

{{FetchEvent/isReload|event.isReload}}

-

isReload attribute must return the value it was initialized to. When an event is created the attribute must be initialized to false.

+ isReload attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to false. -

Pressing the refresh button should be considered a reload while clicking a link and pressing the back button should not. The behavior of the Ctrl+l enter is left to the implementations of the user agents.

+ Note: Pressing the refresh button should be considered a reload while clicking a link and pressing the back button should not. The behavior of Ctrl+l enter is left to the implementations of the user agents.

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

-

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. If the dispatch flag is unset, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  2. -
  3. If the respond-with entered flag is set, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  4. -
  5. Add r to the extend lifetime promises. -

    {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil(f)|event.waitUntil(r)}} is called.

    -
  6. -
  7. Set the stop propagation flag and stop immediate propagation flag.
  8. -
  9. Set the respond-with entered flag.
  10. -
  11. Set the wait to respond flag.
  12. -
  13. Let targetRealm be the relevant Realm of the context object. -
  14. Run the following substeps in parallel: -
      -
    1. Wait until r settles.
    2. -
    3. If r rejected, then: -
        -
      1. Set the respond-with error flag.
      2. -
      -
    4. -
    5. If r resolved with response, then: -
        -
      1. If response is a {{Response}} object, then: -
          -
        1. If response is disturbed or locked, then: -
            -
          1. Set the respond-with error flag.
          2. -
          -
        2. -
        3. Else: -
            -
          1. Let bytes be an empty byte sequence. -
          2. Let end-of-body be false. -
          3. Let done be false. -
          4. Let potentialResponse be a copy of response's associated response, except for its body.
          5. -
          6. If response's body is non-null, run these substeps: -
              -
            1. Let reader be the result of getting a reader from response's body's stream.
            2. -
            3. Let strategy be an object created in targetRealm. The user agent may choose any object.
            4. -
            5. Let pull be an action that runs these subsubsteps: -
                -
              1. Let promise be the result of reading a chunk from response's body's stream with reader.
              2. -
              3. 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.
              4. -
              5. When promise is fulfilled with an object whose done property is true, set end-of-body to true.
              6. -
              7. When promise is fulfilled with a value that matches with neither of the above patterns, or promise is rejected, error newStream with a TypeError.
              8. -
              -
            6. -
            7. Let cancel be an action that cancels response's body's stream with reader.
            8. -
            9. Let newStream be the result of constructing a ReadableStream object with strategy, pull and cancel in targetRealm.
            10. -
            11. Set potentialResponse's body to a new body whose stream is newStream.
            12. -
            13. Run these subsubsteps repeatedly in parallel while done is false:
            14. -
                -
              1. If newStream is errored, then set done to true.
              2. -
              3. Otherwise, if bytes is empty and end-of-body is true, then close newStream and set done to true.
              4. -
              5. Otherwise, if bytes is not empty, run these subsubsubsteps: -
                  -
                1. Let chunk be a subsequence of bytes starting from the beginning of bytes.
                2. -
                3. Remove chunk from bytes. -
                4. Let buffer be an ArrayBuffer object created in targetRealm and containing chunk. -
                5. Enqueue a Uint8Array object created in targetRealm and wrapping buffer to newStream. -
                -
              6. -
              - -
            -

            These substeps are meant to produce the observable equivalent of "piping" response's body's stream into potentialResponse.

            -
          7. -
          8. Set the potential response to potentialResponse.
          9. -
          -
        4. -
        -
      2. -
      3. Else: -
          -
        1. Set the respond-with error flag.
        2. -
        -

        If the 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.)

        -
      4. -
      -
    6. -
    7. Unset the wait to respond flag.
    8. -
    -
  15. -
+ 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. If the dispatch flag is unset, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. If the respond-with entered flag is set, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. Add |r| to the extend lifetime promises. + + Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil(f)|event.waitUntil(r)}} is called. + + 1. Set the stop propagation flag and stop immediate propagation flag. + 1. Set the respond-with entered flag. + 1. Set the 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 respond-with error flag. + 1. If |r| resolved with |response|, then: + 1. If |response| is a {{Response}} object, then: + 1. If |response| is disturbed or locked, then: + 1. Set the 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, except for its body. + 1. If |response|'s body is non-null, run these substeps: + 1. Let |reader| be the result of getting a reader from |response|'s 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 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, error |newStream| with a TypeError. + 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. + 1. Let |newStream| be the result of constructing a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. + 1. Set |potentialResponse|'s 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 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. 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 body's stream into |potentialResponse|. + + 1. Set the potential response to |potentialResponse|. + 1. Else: + 1. Set the respond-with error flag. + + Note: If the 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 wait to respond flag. +
@@ -1651,126 +1350,87 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

Service workers have a functional event foreignfetch. For foreignfetch events, service workers use the {{ForeignFetchEvent}} interface which extends the {{ExtendableEvent}} interface.

+ Service workers have a functional eventforeignfetch. For foreignfetch events, service workers use the {{ForeignFetchEvent}} interface which extends the {{ExtendableEvent}} interface. -

Each event using {{ForeignFetchEvent}} interface has an associated potential response (a response), initially set to null, an associated origin (a {{USVString}} or null), initially set to null, an associated list of exposed headers (whose element type is a byte string), initially set to an empty list, and the following associated flags that are initially unset: -

    -
  • wait to respond flag
  • -
  • respond-with entered flag
  • -
  • respond-with error flag
  • -
-

+ Each event using {{ForeignFetchEvent}} interface has an associated potential response (a response), initially set to null, an associated origin (a {{USVString}} or null), initially set to null, an associated list of exposed headers (whose element type is a byte string), initially set to an empty list, and the following associated flags that are initially unset: + + * wait to respond flag + * respond-with entered flag + * respond-with error flag

{{ForeignFetchEvent/request|event.request}}

-

The request attribute must return the value it was initialized to.

+ The request attribute *must* return the value it was initialized to.

{{ForeignFetchEvent/origin|event.origin}}

-

The origin attribute must return the value it was initialized to.

+ The origin attribute *must* return the value it was initialized to.

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

-

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. If the dispatch flag is unset, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  2. -
  3. If the respond-with entered flag is set, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  4. -
  5. Add r to the extend lifetime promises.
  6. -
  7. Set the stop propagation flag and stop immediate propagation flag.
  8. -
  9. Set the respond-with entered flag.
  10. -
  11. Set the wait to respond flag.
  12. -
  13. Let targetRealm be the relevant Realm of the context object. -
  14. Run the following substeps in parallel: -
      -
    1. Wait until r settles.
    2. -
    3. If r rejected, then: -
        -
      1. Set the respond-with error flag.
      2. -
      -
    4. -
    5. If r resolved with response, then: -
        -
      1. If response is a {{ForeignFetchResponse}}, then: -
          -
        1. Set the origin to response.{{ForeignFetchResponse/origin}}.
        2. -
        3. Set the list of exposed headers to response.{{ForeignFetchResponse/headers}}.
        4. -
        5. If response.{{ForeignFetchResponse/response}} is disturbed or locked, then: -
            -
          1. Set the respond-with error flag.
          2. -
          -
        6. -
        7. Else: -
            -
          1. Let bytes be an empty byte sequence. -
          2. Let end-of-body be false. -
          3. Let done be false. -
          4. Let potentialResponse be a copy of response.{{ForeignFetchResponse/response}}'s associated response, except for its body.
          5. -
          6. If response.{{ForeignFetchResponse/response}}'s body is non-null, run these substeps: -
              -
            1. Let reader be the result of getting a reader from response.{{ForeignFetchResponse/response}}'s body's stream.
            2. -
            3. Let strategy be an object created in targetRealm. The user agent may choose any object.
            4. -
            5. Let pull be an action that runs these subsubsteps: -
                -
              1. Let promise be the result of reading a chunk from response.{{ForeignFetchResponse/response}}'s body's stream with reader.
              2. -
              3. 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.
              4. -
              5. When promise is fulfilled with an object whose done property is true, set end-of-body to true.
              6. -
              7. When promise is fulfilled with a value that matches with neither of the above patterns, or promise is rejected, error newStream with a TypeError.
              8. -
              -
            6. -
            7. Let cancel be an action that cancels response.{{ForeignFetchResponse/response}}'s body's stream with reader.
            8. -
            9. Let newStream be the result of constructing a ReadableStream object with strategy, pull and cancel in targetRealm.
            10. -
            11. Set potentialResponse's body to a new body whose stream is newStream.
            12. -
            13. Run these subsubsteps repeatedly in parallel while done is false:
            14. -
                -
              1. If newStream is errored, then set done to true.
              2. -
              3. Otherwise, if bytes is empty and end-of-body is true, then close newStream and set done to true.
              4. -
              5. Otherwise, if bytes is not empty, run these subsubsubsteps: -
                  -
                1. Let chunk be a subsequence of bytes starting from the beginning of bytes.
                2. -
                3. Remove chunk from bytes. -
                4. Let buffer be an ArrayBuffer object created in targetRealm and containing chunk. -
                5. Enqueue a Uint8Array object created in targetRealm and wrapping buffer to newStream. -
                -
              6. -
              - -
            -
          7. -
          8. Set the potential response to potentialResponse.
          9. -
          -
        8. -
        -
      2. -
      3. Else: -
          -
        1. Set the respond-with error flag.
        2. -
        -

        If the respond-with error flag is set, a network error is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 19.1.) Otherwise, a filtered version of response is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 20.1.)

        -
      4. -
      -
    6. -
    7. Unset the wait to respond flag.
    8. -
    -
  15. -
+ 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. If the dispatch flag is unset, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. If the respond-with entered flag is set, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. Add |r| to the extend lifetime promises. + 1. Set the stop propagation flag and stop immediate propagation flag. + 1. Set the respond-with entered flag. + 1. Set the 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 respond-with error flag. + 1. If |r| resolved with |response|, then: + 1. If |response| is a {{ForeignFetchResponse}}, then: + 1. Set the origin to |response|.{{ForeignFetchResponse/origin}}. + 1. Set the list of exposed headers to |response|.{{ForeignFetchResponse/headers}}. + 1. If |response|.{{ForeignFetchResponse/response}} is disturbed or locked, then: + 1. Set the 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|.{{ForeignFetchResponse/response}}'s associated response, except for its body. + 1. If |response|.{{ForeignFetchResponse/response}}'s body is non-null, run these substeps: + 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/response}}'s 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|.{{ForeignFetchResponse/response}}'s 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, error |newStream| with a TypeError. + 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. + 1. Let |newStream| be the result of constructing a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. + 1. Set |potentialResponse|'s 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 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. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. + 1. Set the potential response to |potentialResponse|. + 1. Else: + 1. Set the respond-with error flag. + + Note: If the respond-with error flag is set, a network error is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 19.1.) Otherwise, a filtered version of |response| is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 20.1.) + + 1. Unset the wait to respond flag. +
@@ -1797,43 +1457,43 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

Service workers define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, service workers use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface.

+ Service workers define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, service workers use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface.

{{ExtendableMessageEvent/data|event.data}}

-

The data attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to null. It represents the message being sent.

+ The data attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to null. It represents the message being sent.

{{ExtendableMessageEvent/origin|event.origin}}

-

The origin attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to the empty string. It represents the origin of the service worker client that sent the message.

+ The origin attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string. It represents the origin of the service worker client that sent the message.

{{ExtendableMessageEvent/lastEventId|event.lastEventId}}

-

The lastEventId attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to the empty string.

+ The lastEventId attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string.

{{ExtendableMessageEvent/source|event.source}}

-

The source attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to null. It represents the {{Client}} object from which the message is sent.

+ The source attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to null. It represents the {{Client}} object from which the message is sent.

{{ExtendableMessageEvent/ports|event.ports}}

-

The ports attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to the empty array. It represents the {{MessagePort}} array being sent.

+ The ports attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty array. It represents the {{MessagePort}} array being sent.

Events

-

The following events are dispatched on {{ServiceWorkerGlobalScope}} object:

+ The following events are dispatched on {{ServiceWorkerGlobalScope}} object:
oninstallinstallinstall
onactivateactivateactivate
onfetchfetchfetch
onforeignfetchforeignfetchforeignfetch
onmessage
@@ -1847,22 +1507,22 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - + - + - + - + @@ -4281,4 +3941,4 @@ navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(functio

The authors would also like to thank Dimitri Glazkov for his scripts and formatting tools which have been essential in the production of this specification. The authors are also grateful for his considerable guidance.

Thanks also to Vivian Cromwell, Greg Simon, Alex Komoroske, Wonsuk Lee, and Seojin Kim for their considerable professional support.

- + \ No newline at end of file From 7fc510d42d1e94c3e08d44bffbc1beceb11131f4 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 23 Nov 2016 11:41:29 +0000 Subject: [PATCH 02/17] More --- docs/index.bs | 3159 ++++++++++++++++++++----------------------------- 1 file changed, 1296 insertions(+), 1863 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 2c426e01..94beff45 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -78,7 +78,7 @@ Markup Shorthands: css no, markdown yes A script resource has an associated HTTPS state (an HTTPS state value). It is initially "none". - A script resource has an associated referrer policy (a referrer policy). It is initially the empty string. + A script resource has an associated referrer policy (a referrer policy). It is initially the empty string. A service worker has an associated script resource map which is an ordered map where the keys are URLs and the values are responses. @@ -740,7 +740,7 @@ Markup Shorthands: css no, markdown yes 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: 1. Set service worker's skip waiting flag. - 1. If service worker's state is installed, then: + 1. If service worker's state is *installed*, then: 1. Run Activate algorithm passing service worker's registration as the argument. 1. Resolve |promise| with undefined. 1. Return |promise|. @@ -915,8 +915,8 @@ Markup Shorthands: css no, markdown yes 1. Let |focusState| be false. 1. Let |ancestorOrigins| be the empty array. 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: - 1. HandleNavigate: Navigate |browsingContext| to |url| with exceptions enabled. The source browsing context must be |browsingContext|. - 1. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set |navigateFailed| to true. + 1. *HandleNavigate*: Navigate |browsingContext| to |url| with exceptions enabled. The source browsing context must be |browsingContext|. + 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |navigateFailed| to true. 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. @@ -1062,8 +1062,8 @@ Markup Shorthands: css no, markdown yes 1. Let |focusState| be false. 1. Let |ancestorOrigins| be the empty array. 1. Queue a task |task| to run the following substeps on |newContext|'s {{Window}} object's environment settings object's responsible event loop using the user interaction task source: - 1. HandleNavigate: Navigate |newContext| to |url| with exceptions enabled and replacement enabled. - 1. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set |openWindowFailed| to true. + 1. *HandleNavigate*: Navigate |newContext| to |url| with exceptions enabled and replacement enabled. + 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |openWindowFailed| to true. 1. Set |visibilityState| to |newContext|'s active document's {{Document/visibilityState}} attribute value. 1. Set |focusState| to the result of running the has focus steps with |newContext|'s active document as the argument. 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. @@ -1143,8 +1143,8 @@ Markup Shorthands: css no, markdown yes Service workers define the following behaviors for install event and activate event, respectively: - * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as installed (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered installed (i.e. a waiting worker) until all of the core caches it depends on are populated. - * Adding a promise to the event's extend lifetime promises delays treating the active worker as activated until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries. + * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. + * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries.
@@ -1536,62 +1536,62 @@ Markup Shorthands: css no, markdown yes
-

The serviceworker keyword may be used with <{link}> elements. This keyword creates an external resource link (serviceworker link) that is used to declare a service worker registration and its scope url.

+ + The serviceworker keyword may be used with <{link}> elements. This keyword creates an external resource link (serviceworker link) that is used to declare a service worker registration and its scope url.
-

When a user agent that supports [[!RFC5988]] processes a Link header that contains a serviceworker link, the user agent should run these steps:

- -
    -
  1. If the Link header has an "anchor" parameter, abort these steps.
  2. -
  3. Let contextURL be the result of parsing the context IRI of the Link header.
  4. -
  5. If the result of running Is origin potentially trustworthy with the origin of contextURL is Not Trusted, abort these steps.
  6. -
  7. Let request be the request for which this header was received in the response.
  8. -
  9. If request's client is not a secure context, abort these steps.
  10. -
  11. Let scriptURL be the result of parsing the target IRI of the Link header.
  12. -
  13. Let scopeURL be null. -
  14. If the "scope" target attribute of the Link header is present, set scopeURL to the result of parsing the "scope" target attribute with scriptURL.
  15. -
  16. Let workerType be the "workertype" target attribute of the Link header, or "classic" if no such attribute is present.
  17. -
  18. If workerType is not a valid {{WorkerType}} value, abort these steps.
  19. -
  20. Invoke [[#start-register-algorithm]] with scopeURL, scriptURL, a new promise, null, contextURL and workerType.
  21. -
- -

When a serviceworker link's <{link}> element is inserted into a document, a serviceworker link is created on a <{link}> element that is already in a document tree, or the <{link/href}> or <{link/scope}> attributes of the <{link}> element of a serviceworker link is changed, the user agent should run these steps:

- -
    -
  1. If the <{link/href}> attribute is the empty string, abort these steps.
  2. -
  3. Let client be the document's service worker client.
  4. -
  5. If client is not a secure context, queue a task to fire an event named error at the <{link}> element, and abort these steps.
  6. -
  7. Let scriptURL be the result of parsing the <{link/href}> attribute with the <{link}> element's node document's document base URL.
  8. -
  9. Let scopeURL be null. -
  10. If the <{link/scope}> attribute is present, set scopeURL to the result of parsing the <{link/scope}> attribute with the <{link}> element's node document's document base URL.
  11. -
  12. Let workerType be the <{link/workertype}> attribute, or "classic" if the <{link/workertype}> attribute is omitted.
  13. -
  14. If workerType is not a valid {{WorkerType}} value, queue a task to fire an event named error at the <{link}> element, and abort these steps.
  15. -
  16. Let promise be a new promise.
  17. -
  18. Invoke [[#start-register-algorithm]] with scopeURL, scriptURL, promise, client, client's creation URL and workerType.
  19. -
  20. Run the following substeps in parallel: -
      -
    1. Wait until promise settles.
    2. -
    3. If promise rejected, queue a task to fire an event named error at the <{link}> element.
    4. -
    5. If promise resolved, queue a task to fire an event named load at the <{link}> element.
    6. -
    -
  21. -
- -

The serviceworker link element must not delay the load event of the element's node document.

+ When a user agent that supports [[!RFC5988]] processes a Link header that contains a serviceworker link, the user agent *should* run these steps: + + 1. If the Link header has an "anchor" parameter, abort these steps. + 1. Let |contextURL| be the result of parsing the context IRI of the Link header. + 1. If the result of running Is origin potentially trustworthy with the origin of |contextURL| is Not Trusted, abort these steps. + 1. Let |request| be the request for which this header was received in the response. + 1. If |request|'s client is not a secure context, abort these steps. + 1. Let |scriptURL| be the result of parsing the target IRI of the Link header. + 1. Let |scopeURL| be null. + 1. If the "scope" target attribute of the Link header is present, set |scopeURL| to the result of parsing the "scope" target attribute with |scriptURL|. + 1. Let |workerType| be the "workertype" target attribute of the Link header, or "classic" if no such attribute is present. + 1. If |workerType| is not a valid {{WorkerType}} value, abort these steps. + 1. Invoke [[#start-register-algorithm]] with |scopeURL|, |scriptURL|, a new promise, null, |contextURL| and |workerType|. + + When a serviceworker link's <{link}> element is inserted into a document, a serviceworker link is created on a <{link}> element that is already in a document tree, or the <{link/href}> or <{link/scope}> attributes of the <{link}> element of a serviceworker link is changed, the user agent *should* run these steps: + + 1. If the <{link/href}> attribute is the empty string, abort these steps. + 1. Let |client| be the document's service worker client. + 1. If |client| is not a secure context, queue a task to fire an event named error at the <{link}> element, and abort these steps. + 1. Let |scriptURL| be the result of parsing the <{link/href}> attribute with the <{link}> element's node document's document base URL. + 1. Let |scopeURL| be null. + 1. If the <{link/scope}> attribute is present, set |scopeURL| to the result of parsing the <{link/scope}> attribute with the <{link}> element's node document's document base URL. + 1. Let |workerType| be the <{link/workertype}> attribute, or "classic" if the <{link/workertype}> attribute is omitted. + 1. If |workerType| is not a valid {{WorkerType}} value, queue a task to fire an event named error at the <{link}> element, and abort these steps. + 1. Let |promise| be a new promise. + 1. Invoke [[#start-register-algorithm]] with |scopeURL|, |scriptURL|, |promise|, |client|, |client|'s creation URL and |workerType|. + 1. Run the following substeps in parallel: + 1. Wait until |promise| settles. + 1. If |promise| rejected, queue a task to fire an event named error at the <{link}> element. + 1. If |promise| resolved, queue a task to fire an event named load at the <{link}> element. + + The serviceworker link element *must not* delay the load event of the element's node document.
A resource being loaded with the following response header: -
+
+      
         Link: </js/sw.js>; rel="serviceworker"; scope="/"
       
- has more or less the same effect as a document being loaded in a secure context with the following link element: -
+      
+      has more or less the same effect as a document being loaded in a secure context with the following 
+      link element:
+
+      
         <link rel="serviceworker" href="/js/sw.js" scope="/">
       
+ which is more or less equivalent to the page containing javascript code like: -
+      
+      
         navigator.serviceworker.register("/js/sw.js", { scope: "/" });
       
@@ -1607,33 +1607,35 @@ Markup Shorthands: css no, markdown yes }; -

The scope IDL attribute must reflect the element's scope content attribute.

+ The scope IDL attribute must reflect the element's scope content attribute. -

The workerType IDL attribute must reflect the element's workertype content attribute.

+ The workerType IDL attribute must reflect the element's workertype content attribute.

Caches

-

To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An origin can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across origins, and they are completely isolated from the browser's HTTP cache.

+ To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An origin can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across origins, and they are completely isolated from the browser's HTTP cache.

Constructs

-

A fetching record is a Record {\[[key]], \[[value]]} where \[[key]] is a {{Request}} and \[[value]] is a {{Response}}.

-

A fetching record has an associated incumbent record (a fetching record). It is initially set to null.

-

A request to response map is a List of fetching records.

+ A fetching record is a Record {\[[key]], \[[value]]} where \[[key]] is a {{Request}} and \[[value]] is a {{Response}}. -

A name to cache map is a List of the Record {\[[key]], \[[value]]} where \[[key]] is a string that represents a name of the {{Cache}} object and \[[value]] is a {{Cache}} object.

+ A fetching record has an associated incumbent record (a fetching record). It is initially set to null. -

Each origin has an associated name to cache map.

+ A request to response map is a List of fetching records. + + A name to cache map is a List of the Record {\[[key]], \[[value]]} where \[[key]] is a string that represents a name of the {{Cache}} object and \[[value]] is a {{Cache}} object. + + Each origin has an associated name to cache map.

Understanding Cache Lifetimes

-

The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the service worker script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the service worker that can safely operate on.

+ The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the service worker script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the service worker that can safely operate on.
@@ -1648,7 +1650,7 @@ Markup Shorthands: css no, markdown yes

{{WindowOrWorkerGlobalScope/caches}}

-

caches attribute must return this object's associated {{CacheStorage}} object.

+ caches attribute *must* return this object's associated {{CacheStorage}} object.
@@ -1684,396 +1686,232 @@ Markup Shorthands: css no, markdown yes }; -

A {{Cache}} object represents a request to response map. Multiple separate objects implementing the {{Cache}} interface across documents and workers can all be associated with the same request to response map simultaneously.

+ A {{Cache}} object represents a request to response map. Multiple separate objects implementing the {{Cache}} interface across documents and workers can all be associated with the same request to response map simultaneously. -

{{Cache}} objects are always enumerable via {{WindowOrWorkerGlobalScope/caches|self.caches}} in insertion order (per ECMAScript 6 Map objects).

+ {{Cache}} objects are always enumerable via {{WindowOrWorkerGlobalScope/caches|self.caches}} in insertion order (per ECMAScript 6 Map objects).

{{Cache/match(request, options)}}

-

match(request, options) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. Let p be the result of running the algorithm specified in {{Cache/matchAll(request, options)}} method with request and options as the arguments.
    2. -
    3. Wait until p settles.
    4. -
    5. If p rejects with an exception, then: -
        -
      1. Reject promise with that exception.
      2. -
      -
    6. -
    7. Else if p resolves with an array, responseArray, then: -
        -
      1. If responseArray is an empty array, then: -
          -
        1. Resolve promise with undefined.
        2. -
        -
      2. -
      3. Else: -
          -
        1. Resolve promise with the first element of responseArray.
        2. -
        -
      4. -
      -
    8. -
    -
  4. -
  5. Return promise.
  6. -
+ match(|request|, |options|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |p| be the result of running the algorithm specified in {{Cache/matchAll(request, options)}} method with |request| and |options| as the arguments. + 1. Wait until |p| settles. + 1. If |p| rejects with an exception, then: + 1. Reject |promise| with that exception. + 1. Else if |p| resolves with an array, |responseArray|, then: + 1. If |responseArray| is an empty array, then: + 1. Resolve |promise| with undefined. + 1. Else: + 1. Resolve |promise| with the first element of |responseArray|. + 1. Return |promise|.

{{Cache/matchAll(request, options)}}

-

matchAll(request, options) method must run these steps:

- -
    -
  1. Let r be null.
  2. -
  3. If the optional argument request is not omitted, then: -
      -
    1. If request is a {{Request}} object, then: -
        -
      1. Set r to request's request.
      2. -
      3. If r's method is not `GET` and options.ignoreMethod is false, return a promise resolved with an empty array.
      4. -
      -
    2. -
    3. Else if request is a string, then: -
        -
      1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
      2. -
      -
    4. -
    -
  4. -
  5. Let promise be a new promise.
  6. -
  7. Run these substeps in parallel: -
      -
    1. Let responseArray be an empty array.
    2. -
    3. If the optional argument request is omitted, then: -
        -
      1. For each fetching record entry of its request to response map, in key insertion order: -
          -
        1. Add a copy of entry.\[[value]] to responseArray.
        2. -
        -
      2. -
      3. Resolve promise with responseArray.
      4. -
      5. Abort these steps.
      6. -
      -
    4. -
    5. Else: -
        -
      1. Let entries be the result of running Query Cache algorithm passing a {{Request}} object associated with r and options as the arguments.
      2. -
      3. For each entry of entries: -
          -
        1. Let response be null.
        2. -
        3. If the incumbent record incumbentRecord of the corresponding fetching record fetchingRecord in request to response map is not null, set response to a copy of incumbentRecord.\[[value]].
        4. -
        5. Else, set response to a copy of entry[1].
        6. -
        7. Add response to responseArray.
        8. -
        -
      4. -
      5. Resolve promise with responseArray.
      6. -
      -
    6. -
    -
  8. -
  9. Return promise.
  10. -
+ matchAll(|request|, |options|) method *must* run these steps: + + 1. Let |r| be null. + 1. If the optional argument |request| is not omitted, then: + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.|ignoreMethod| is false, return a promise resolved with an empty array. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |responseArray| be an empty array. + 1. If the optional argument |request| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Add a copy of |entry|.\[[value]] to |responseArray|. + 1. Resolve |promise| with |responseArray|. + 1. Abort these steps. + 1. Else: + 1. Let |entries| be the result of running Query Cache algorithm passing a {{Request}} object associated with |r| and |options| as the arguments. + 1. For each |entry| of |entries|: + 1. Let |response| be null. + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, set |response| to a copy of |incumbentRecord|.\[[value]]. + 1. Else, set |response| to a copy of |entry|[1]. + 1. Add |response| to |responseArray|. + 1. Resolve |promise| with |responseArray|. + 1. Return |promise|.

{{Cache/add(request)}}

-

add(request) method must run these steps:

+ add(|request|) method *must* run these steps: -
    -
  1. Let requests be an array containing only request.
  2. -
  3. Set responseArrayPromise to the result of running the algorithm specified in {{Cache/addAll(requests)}} passing requests as the argument.
  4. -
  5. Return the result of transforming responseArrayPromise with a fulfillment handler that returns undefined.
  6. -
+ 1. Let |requests| be an array containing only |request|. + 1. Set |responseArrayPromise| to the result of running the algorithm specified in {{Cache/addAll(requests)}} passing |requests| as the argument. + 1. Return the result of transforming |responseArrayPromise| with a fulfillment handler that returns undefined.

{{Cache/addAll(requests)}}

-

addAll(requests) method must run these steps:

- -
    -
  1. Let responsePromiseArray be an empty array.
  2. -
  3. Let requestArray be an empty array.
  4. -
  5. For each request whose type is {{Request}} in requests: -
      -
    1. Let r be request's request.
    2. -
    3. If r's url's scheme is not one of "http" and "https", or r's method is not `GET`, return a promise rejected with a TypeError.
    4. -
    -
  6. -
  7. For each request in requests: -
      -
    1. Let r be the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
    2. -
    3. If r's url's scheme is not one of "http" and "https", then: -
        -
      1. Terminate all the ongoing fetches initiated by requests with reason fatal.
      2. -
      3. Break the loop.
      4. -
      -
    4. -
    5. Set r's initiator to "fetch" and destination to "subresource".
    6. -
    7. Add a {{Request}} object associated with r to requestArray.
    8. -
    9. Let responsePromise be a new promise.
    10. -
    11. Run the following substeps in parallel: -
        -
      • Fetch r.
      • -
      • To process response for response, run these substeps: -
          -
        1. If response's type is "error", or response's status is not an ok status, reject responsePromise with a TypeError.
        2. -
        3. Else if response's header list contains a header named `Vary`, then: -
            -
          1. Let varyHeaders be the array containing the elements corresponding to the field-values of the Vary header.
          2. -
          3. Let matchAsterisk be false.
          4. -
          5. For each f in varyHeaders: -
              -
            1. If f matches "*", set matchAsterisk to true and break the loop.
            2. -
            -
          6. -
          7. If matchAsterisk is true, reject responsePromise with a TypeError.
          8. -
          9. Else, resolve responsePromise with a new {{Response}} object associated with response and a new {{Headers}} object whose guard is "immutable".
          10. -
          -
        4. -
        5. Else, resolve responsePromise with a new {{Response}} object associated with response and a new {{Headers}} object whose guard is "immutable".
        6. -
        -

        This step ensures that the promise for this fetch resolves as soon as the response's headers become available.

        -
      • -
      • To process response body for response, do nothing.
      • -
      • To process response end-of-file for response, do nothing.
      • -
      -
    12. -
    13. Add responsePromise to responsePromiseArray.
    14. -
    -
  8. -
  9. Let p be waiting for all of responsePromiseArray.
  10. -
  11. Return the result of transforming p with a fulfillment handler that, when called with argument responseArray, performs the following substeps in parallel: -
      -
    1. Let operations be an empty array.
    2. -
    3. For each response in responseArray with the index index: -
        -
      1. Let o be an empty object representing a {{CacheBatchOperation}} dictionary.
      2. -
      3. Set the {{CacheBatchOperation/type}} dictionary member of o to "put".
      4. -
      5. Set the {{CacheBatchOperation/request}} dictionary member of o to requestArray[index].
      6. -
      7. Set the {{CacheBatchOperation/response}} dictionary member of o to response.
      8. -
      9. Add o to operations.
      10. -
      -
    4. -
    5. Let resultPromise be the result of running Batch Cache Operations algorithm passing operations as the argument.
    6. -
    7. Return the result of transforming resultPromise with a fulfillment handler that, when called with argument responses, performs the following substeps in parallel: -
        -
      1. Let responseBodyPromiseArray be an empty array.
      2. -
      3. For each response in responses: -
          -
        1. Let responseBodyPromise be a new promise.
        2. -
        3. Run the following substeps in parallel: -
            -
          1. Wait for either end-of-file to have been pushed to response's associated response r's body or for r to have a termination reason.
          2. -
          3. If r had a termination reason, then: -
              -
            1. If the incumbent record incumbentRecord of the corresponding fetching record fetchingRecord in request to response map is not null, then: -
                -
              1. Set fetchingRecord in request to response map to the copy of incumbentRecord.
              2. -
              -
            2. -
            3. Else: -
                -
              1. Delete fetchingRecord from request to response map.
              2. -
              -
            4. -
            5. Reject responseBodyPromise with a TypeError.
            6. -
            -
          4. -
          5. Else: -
              -
            1. Set the incumbent record of the corresponding fetching record fetchingRecord in request to response map to the copy of fetchingRecord.
            2. -
            3. Let invalidRecords be the result of running Query Cache algorithm passing fetchingRecord.\[[key]] as the argument.
            4. -
            5. For each invalidRecord in invalidRecords: -
                -
              1. If invalidRecord is not fetchingRecord, delete it from request to response map.
              2. -
              -
            6. -
            7. Resolve responseBodyPromise with response.
            8. -
            -
          6. -
          -
        4. -
        5. Add responseBodyPromise to responseBodyPromiseArray.
        6. -
        -
      4. -
      5. Let q be waiting for all of responseBodyPromiseArray.
      6. -
      7. Return the result of transforming q with a fulfillment handler that returns undefined.
      8. -
      -
    8. -
    -
  12. -
+ addAll(|requests|) method *must* run these steps: + + 1. Let |responsePromiseArray| be an empty array. + 1. Let |requestArray| be an empty array. + 1. For each |request| whose type is {{Request}} in |requests|: + 1. Let |r| be |request|'s request. + 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. + 1. For each |request| in |requests|: + 1. Let |r| be the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s url's scheme is not one of "http" and "https", then: + 1. Terminate all the ongoing fetches initiated by |requests| with reason *fatal*. + 1. Break the loop. + 1. Set |r|'s initiator to "fetch" and destination to "subresource". + 1. Add a {{Request}} object associated with |r| to |requestArray|. + 1. Let |responsePromise| be a new promise. + 1. Run the following substeps in parallel: + * Fetch |r|. + * To process response for |response|, run these substeps: + 1. If |response|'s type is "error", or |response|'s status is not an ok status, reject |responsePromise| with a TypeError. + 1. Else if |response|'s header list contains a header named `Vary`, then: + 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. Let |matchAsterisk| be false. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", set |matchAsterisk| to true and break the loop. + 1. If |matchAsterisk| is true, reject |responsePromise| with a TypeError. + 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". + 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". + + Note: This step ensures that the promise for this fetch resolves as soon as the response's headers become available. + + * To process response body for |response|, do nothing. + * To process response end-of-file for |response|, do nothing. + 1. Add |responsePromise| to |responsePromiseArray|. + 1. Let |p| be waiting for all of |responsePromiseArray|. + 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |responseArray|, performs the following substeps in parallel: + 1. Let |operations| be an empty array. + 1. For each |response| in |responseArray| with the index |index|: + 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. + 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "put". + 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to |requestArray|[|index|]. + 1. Set the {{CacheBatchOperation/response}} dictionary member of |o| to |response|. + 1. Add |o| to |operations|. + 1. Let |resultPromise| be the result of running Batch Cache Operations algorithm passing |operations| as the argument. + 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: + 1. Let |responseBodyPromiseArray| be an empty array. + 1. For each |response| in |responses|: + 1. Let |responseBodyPromise| be a new promise. + 1. Run the following substeps in parallel: + 1. Wait for either end-of-file to have been pushed to |response|'s associated response |r|'s body or for |r| to have a termination reason. + 1. If |r| had a termination reason, then: + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: + 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. + 1. Else: + 1. Delete |fetchingRecord| from request to response map. + 1. Reject |responseBodyPromise| with a TypeError. + 1. Else: + 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. + 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. + 1. For each |invalidRecord| in |invalidRecords|: + 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. + 1. Resolve |responseBodyPromise| with |response|. + 1. Add |responseBodyPromise| to |responseBodyPromiseArray|. + 1. Let |q| be waiting for all of |responseBodyPromiseArray|. + 1. Return the result of transforming |q| with a fulfillment handler that returns undefined.

{{Cache/put(request, response)}}

-

put(request, response) method must run these steps:

- -
    -
  1. Let r be null.
  2. -
  3. If request is a {{Request}} object, then: -
      -
    1. Set r to request's request.
    2. -
    3. If r's url's scheme is not one of "http" and "https", or r's method is not `GET`, return a promise rejected with a TypeError.
    4. -
    -
  4. -
  5. Else if request is a string, then: -
      -
    1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
    2. -
    3. If r's url's scheme is not one of "http" and "https", return a promise rejected with a TypeError.
    4. -
    -
  6. -
  7. If response's associated response's header list contains a header named `Vary`, then: -
      -
    1. Let varyHeaders be the array containing the elements corresponding to the field-values of the Vary header.
    2. -
    3. For each f in varyHeaders: -
        -
      1. If f matches "*", return a promise rejected with a TypeError.
      2. -
      -
    4. -
    -
  8. -
  9. If response is disturbed or locked, return a promise rejected with a TypeError.
  10. -
  11. Let newResponse be a new {{Response}} object associated with response's associated response and a new {{Headers}} object whose guard is response's {{Headers}}' guard.
  12. -
  13. If response's body is non-null, run these substeps: -
      -
    1. Let dummyStream be an empty ReadableStream object.
    2. -
    3. Set response's body to a new body whose stream is dummyStream.
    4. -
    5. Let reader be the result of getting a reader from dummyStream.
    6. -
    7. Read all bytes from dummyStream with reader.
    8. -
    -
  14. -
  15. Let operations be an empty array.
  16. -
  17. Let o be an empty object representing a {{CacheBatchOperation}} dictionary.
  18. -
  19. Set the {{CacheBatchOperation/type}} dictionary member of o to "put".
  20. -
  21. Set the {{CacheBatchOperation/request}} dictionary member of o to a {{Request}} object associated with r.
  22. -
  23. Set the {{CacheBatchOperation/response}} dictionary member of o to newResponse.
  24. -
  25. Add o to operations.
  26. -
  27. Let resultPromise be the result of running Batch Cache Operations passing operations as the argument.
  28. -
  29. Return the result of transforming resultPromise with a fulfillment handler that, when called with argument responses, performs the following substeps in parallel: -
      -
    1. Wait for either end-of-file to have been pushed to responses[0]'s associated response r's body or for r to have a termination reason.
    2. -
    3. If r had a termination reason, then: -
        -
      1. If the incumbent record incumbentRecord of the corresponding fetching record fetchingRecord in request to response map is not null, then: -
          -
        1. Set fetchingRecord in request to response map to the copy of incumbentRecord.
        2. -
        -
      2. -
      3. Else: -
          -
        1. Delete fetchingRecord from request to response map.
        2. -
        -
      4. -
      5. Throw a TypeError.
      6. -
      -
    4. -
    5. Else: -
        -
      1. Set the incumbent record of the corresponding fetching record fetchingRecord in request to response map to the copy of fetchingRecord.
      2. -
      3. Let invalidRecords be the result of running Query Cache algorithm passing fetchingRecord.\[[key]] as the argument.
      4. -
      5. For each invalidRecord in invalidRecords: -
          -
        1. If invalidRecord is not fetchingRecord, delete it from request to response map.
        2. -
        -
      6. -
      7. Return undefined.
      8. -
      -
    6. -
    -
  30. -
+ put(|request|, |response|) method *must* run these steps: + + 1. Let |r| be null. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s request. + 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s url's scheme is not one of "http" and "https", return a promise rejected with a TypeError. + 1. If |response|'s associated response's header list contains a header named `Vary`, then: + 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", return a promise rejected with a TypeError. + 1. If |response| is disturbed or locked, return a promise rejected with a TypeError. + 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated response and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. + 1. If |response|'s body is non-null, run these substeps: + 1. Let |dummyStream| be an empty ReadableStream object. + 1. Set |response|'s body to a new body whose stream is |dummyStream|. + 1. Let |reader| be the result of getting a reader from |dummyStream|. + 1. Read all bytes from |dummyStream| with |reader|. + 1. Let |operations| be an empty array. + 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. + 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "put". + 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to a {{Request}} object associated with |r|. + 1. Set the {{CacheBatchOperation/response}} dictionary member of |o| to |newResponse|. + 1. Add |o| to |operations|. + 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. + 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: + 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated response |r|'s body or for |r| to have a termination reason. + 1. If |r| had a termination reason, then: + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: + 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. + 1. Else: + 1. Delete |fetchingRecord| from request to response map. + 1. Throw a TypeError. + 1. Else: + 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. + 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. + 1. For each |invalidRecord| in |invalidRecords|: + 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. + 1. Return undefined.

{{Cache/delete(request, options)}}

-

delete(request, options) method must run these steps:

- -
    -
  1. Let r be null.
  2. -
  3. If request is a {{Request}} object, then: -
      -
    1. Set r to request's request.
    2. -
    3. If r's method is not `GET` and options.ignoreMethod is false, return a promise resolved with false.
    4. -
    -
  4. -
  5. Else if request is a string, then: -
      -
    1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
    2. -
    -
  6. -
  7. Let operations be an empty array.
  8. -
  9. Let o be an empty object representing a {{CacheBatchOperation}} dictionary.
  10. -
  11. Set the {{CacheBatchOperation/type}} dictionary member of o to "delete".
  12. -
  13. Set the {{CacheBatchOperation/request}} dictionary member of o to a {{Request}} object associated with r.
  14. -
  15. Set the {{CacheBatchOperation/options}} dictionary member of o to options.
  16. -
  17. Add o to operations.
  18. -
  19. Let resultPromise be the result of running Batch Cache Operations passing operations as the argument.
  20. -
  21. Return the result of transforming resultPromise with a fulfillment handler, when called with argument responseArray, performs the following substeps in parallel: -
      -
    1. If responseArray is not null, return true.
    2. -
    3. Else, return false.
    4. -
    -
  22. -
+ delete(|request|, |options|) method *must* run these steps: + + 1. Let |r| be null. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.|ignoreMethod| is false, return a promise resolved with false. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |operations| be an empty array. + 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. + 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "delete". + 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to a {{Request}} object associated with |r|. + 1. Set the {{CacheBatchOperation/options}} dictionary member of |o| to |options|. + 1. Add |o| to |operations|. + 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. + 1. Return the result of transforming |resultPromise| with a fulfillment handler, when called with argument |responseArray|, performs the following substeps in parallel: + 1. If |responseArray| is not null, return true. + 1. Else, return false.

{{Cache/keys(request, options)}}

-

keys(request, options) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. Let resultArray be an empty array.
    2. -
    3. If the optional argument request is omitted, then: -
        -
      1. For each fetching record entry of its request to response map, in key insertion order: -
          -
        1. Add entry.\[[key]] to resultArray.
        2. -
        -
      2. -
      -
    4. -
    5. Else: -
        -
      1. Let r be null.
      2. -
      3. If request is a {{Request}} object, then: -
          -
        1. Set r to request's request.
        2. -
        3. If r's method is not `GET` and options.ignoreMethod is false, resolve promise with an empty array.
        4. -
        -
      4. -
      5. Else if request is a string, then: -
          -
        1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
        2. -
        -
      6. -
      7. Let requestResponseArray be the result of running Query Cache algorithm passing a {{Request}} object that represents r and options as the arguments.
      8. -
      9. For each requestResponse in requestResponseArray: -
          -
        1. Add requestResponse[0] to resultArray.
        2. -
        -
      10. -
      -
    6. -
    7. Resolve promise with resultArray.
    8. -
    -
  4. -
  5. Return promise.
  6. -
+ keys(|request|, |options|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |resultArray| be an empty array. + 1. If the optional argument |request| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Add |entry|.\[[key]] to |resultArray|. + 1. Else: + 1. Let |r| be null. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.|ignoreMethod| is false, resolve |promise| with an empty array. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing a {{Request}} object that represents |r| and |options| as the arguments. + 1. For each |requestResponse| in |requestResponseArray|: + 1. Add |requestResponse|[0] to |resultArray|. + 1. Resolve |promise| with |resultArray|. + + 1. Return |promise|.
@@ -2090,156 +1928,94 @@ Markup Shorthands: css no, markdown yes [NewObject] Promise<sequence<DOMString>> keys(); }; - + -

{{CacheStorage}} interface is designed to largely conform to ECMAScript 6 Map objects but entirely async, and with additional convenience methods. The methods, clear, forEach, entries and values, are intentionally excluded from the scope of the first version resorting to the ongoing discussion about the async iteration by TC39.

+ Note: {{CacheStorage}} interface is designed to largely conform to ECMAScript 6 Map objects but entirely async, and with additional convenience methods. The methods, clear, forEach, entries and values, are intentionally excluded from the scope of the first version resorting to the ongoing discussion about the async iteration by TC39. -

The user agent must create a {{CacheStorage}} object when a {{Window}} object or a {{WorkerGlobalScope}} object is created and associate it with that global object.

+ The user agent *must* create a {{CacheStorage}} object when a {{Window}} object or a {{WorkerGlobalScope}} object is created and associate it with that global object. -

A {{CacheStorage}} object represents a name to cache map of its associated global object's environment settings object's origin. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously.

+ A {{CacheStorage}} object represents a name to cache map of its associated global object's environment settings object's origin. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously.

{{CacheStorage/match(request, options)}}

-

match(request, options) method must run these steps:

- -
    -
  1. If options.{{CacheQueryOptions/cacheName}} is present, then: -
      -
    1. Return a new promise p and run the following substeps in parallel: -
        -
      1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
          -
        1. If options.{{CacheQueryOptions/cacheName}} matches entry.\[[key]], then: -
            -
          1. Resolve p with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with request and options as the arguments (providing entry.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.)
          2. -
          3. Abort these steps.
          4. -
          -
        2. -
        -
      2. -
      3. Resolve p with undefined.
      4. -
      -
    2. -
    -
  2. -
  3. Else: -
      -
    1. Let p be a promise resolved with undefined.
    2. -
    3. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. Set p to the result of transforming itself with a fulfillment handler that, when called with argument v, performs the following substeps in parallel: -
          -
        1. If v is not undefined, return v.
        2. -
        3. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with request and options as the arguments (providing entry.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.)
        4. -
        -
      2. -
      -
    4. -
    5. Return p.
    6. -
    -
  4. -
+ match(|request|, |options|) method *must* run these steps: + + 1. If |options|.{{CacheQueryOptions/cacheName}} is present, then: + 1. Return a new promise |p| and run the following substeps in parallel: + 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: + 1. If |options|.{{CacheQueryOptions/cacheName}} matches |entry|.\[[key]], then: + 1. Resolve |p| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |entry|.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. Abort these steps. + 1. Resolve |p| with undefined. + 1. Else: + 1. Let |p| be a promise resolved with undefined. + 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: + 1. Set |p| to the result of transforming itself with a fulfillment handler that, when called with argument |v|, performs the following substeps in parallel: + 1. If |v| is not undefined, return |v|. + 1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |entry|.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. Return |p|.

{{CacheStorage/has(cacheName)}}

-

has(cacheName) method must run these steps:

- -
    -
  1. Return a promise p resolved with the result of running the following substeps: -
      -
    1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. If cacheName matches entry.\[[key]], then: -
          -
        1. Return true.
        2. -
        -
      2. -
      -
    2. -
    3. Return false.
    4. -
    -
  2. -
+ has(|cacheName|) method *must* run these steps: + + 1. Return a promise |p| resolved with the result of running the following substeps: + 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: + 1. If |cacheName| matches |entry|.\[[key]], then: + 1. Return true. + 1. Return false.

{{CacheStorage/open(cacheName)}}

-

open(cacheName) method must run these steps:

- -
    -
  1. Let p be a new promise.
  2. -
  3. Run the following substeps: -
      -
    1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. If cacheName matches entry.\[[key]], then: -
          -
        1. Resolve p with a new {{Cache}} object which is a copy of entry.\[[value]].
        2. -
        3. Abort these steps.
        4. -
        -
      2. -
      -
    2. -
    3. Let cache be a new {{Cache}} object.
    4. -
    5. Set a newly-created Record {\[[key]]: cacheName, \[[value]]: cache} to name to cache map. If this cache write operation failed due to exceeding the granted quota limit, reject p with a "{{QuotaExceededError}}" exception and abort these steps.
    6. -
    7. Resolve p with cache.
    8. -
    -
  4. -
  5. Return p.
  6. -
+ open(|cacheName|) method *must* run these steps: + + 1. Let |p| be a new promise. + 1. Run the following substeps: + 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: + 1. If |cacheName| matches |entry|.\[[key]], then: + 1. Resolve |p| with a new {{Cache}} object which is a copy of |entry|.\[[value]]. + 1. Abort these steps. + 1. Let |cache| be a new {{Cache}} object. + 1. Set a newly-created Record {\[[key]]: |cacheName|, \[[value]]: |cache|} to name to cache map. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. + 1. Resolve |p| with |cache|. + 1. Return |p|.

{{CacheStorage/delete(cacheName)}}

-

delete(cacheName) method must run these steps:

- -
    -
  1. Let p be the result of running the algorithm specified in {{CacheStorage/has(cacheName)}} method with cacheName as the argument.
  2. -
  3. Return the result of transforming p with a fulfillment handler that, when called with argument cacheExists, performs the following substeps in parallel: -
      -
    1. If cacheExists is true, then: -
        -
      1. Delete a Record {\[[key]], \[[value]]} entry from its name to cache map where cacheName matches entry.\[[key]].
      2. -
      3. Return true.
      4. -
      5. Abort these steps.
      6. -
      -

      After this step, the existing DOM objects (i.e. the currently referenced Cache, Request, and Response objects) should remain functional.

      -
    2. -
    3. Else: -
        -
      1. Return false.
      2. -
      -
    4. -
    -
  4. -
+ delete(|cacheName|) method *must* run these steps: + + 1. Let |p| be the result of running the algorithm specified in {{CacheStorage/has(cacheName)}} method with |cacheName| as the argument. + 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |cacheExists|, performs the following substeps in parallel: + 1. If |cacheExists| is true, then: + 1. Delete a Record {\[[key]], \[[value]]} |entry| from its name to cache map where |cacheName| matches entry.\[[key]]. + 1. Return true. + 1. Abort these steps. + + Note: After this step, the existing DOM objects (i.e. the currently referenced Cache, Request, and Response objects) should remain functional. + + 1. Else: + 1. Return false.

{{CacheStorage/keys()}}

-

keys() method must run these steps:

+ keys() method *must* run these steps: -

The promise returned from this method resolves with the sequence of keys, cache names in DOMString, in insertion order.

+ Note: The promise returned from this method resolves with the sequence of keys, cache names in DOMString, in insertion order. -
    -
  1. Let resultArray be an empty array.
  2. -
  3. Return a promise p resolved with the result of running the following substeps: -
      -
    1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. Add entry.\[[key]] to resultArray.
      2. -
      -
    2. -
    3. Return resultArray.
    4. -
    -
  4. -
+ 1. Let |resultArray| be an empty array. + 1. Return a promise |p| resolved with the result of running the following substeps: + 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: + 1. Add |entry|.\[[key]] to |resultArray|. + 1. Return |resultArray|.
@@ -2250,19 +2026,18 @@ Markup Shorthands: css no, markdown yes

Secure Context

-

Service workers must execute in secure contexts. Service worker clients must also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients should be hosted over HTTPS. A user agent may allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts.

+ Service workers *must* execute in secure contexts. Service worker clients *must* also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts.

Content Security Policy

-

Whenever a user agent invokes Run Service Worker algorithm with a service worker serviceWorker: -

    -
  • If serviceWorker's script resource was delivered with a Content-Security-Policy HTTP header containing the value policy, the user agent must enforce policy for serviceWorker.
  • -
  • If serviceWorker's script resource was delivered with a Content-Security-Policy-Report-Only HTTP header containing the value policy, the user agent must monitor policy for serviceWorker.
  • -
-

-

The primary reason for this restriction is to mitigate a broad class of content injection vulnerabilities, such as cross-site scripting (XSS).

+ Whenever a user agent invokes Run Service Worker algorithm with a service worker |serviceWorker|: + + * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy HTTP header containing the value |policy|, the user agent *must* enforce |policy| for |serviceWorker|. + * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy-Report-Only HTTP header containing the value |policy|, the user agent *must* monitor |policy| for |serviceWorker|. + + The primary reason for this restriction is to mitigate a broad class of content injection vulnerabilities, such as cross-site scripting (XSS).
@@ -2271,85 +2046,72 @@ Markup Shorthands: css no, markdown yes

Origin restriction

- This section is non-normative. + *This section is non-normative.* -

A Service worker executes in the registering service worker client's origin. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other origins. Therefore, service workers cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that service workers create the opportunity for a bad actor to turn a bad day into a bad eternity.

+ A Service worker executes in the registering service worker client's origin. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other origins. Therefore, service workers cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that service workers create the opportunity for a bad actor to turn a bad day into a bad eternity.

{{WorkerGlobalScope/importScripts(urls)}}

-

When the importScripts(urls) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent must import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and urls, and with the following steps to perform the fetch given the request request:

- -
    -
  1. Let serviceWorker be request's client's global object's service worker.
  2. -
  3. If serviceWorker's imported scripts updated flag is unset, then: -
      -
    1. Let response be the result of fetching request.
    2. -
    3. If response's unsafe response's type is not "error", and response's status is an ok status, then: -
        -
      1. If there exists a corresponding Record record for request's url in serviceWorker's script resource map, set record.\[[value]] to response.
      2. -
      3. Else, set a newly-created Record {\[[key]]: url, \[[value]]: response} to serviceWorker's script resource map.
      4. -
      -
    4. -
    5. Return response. -
    -
  4. -
  5. Else: -
      -
    1. If there exists a corresponding Record record for url in serviceWorker's script resource map, return record.\[[value]].
    2. -
    3. Else, return a network error.
    4. -
    -
  6. -
+ When the importScripts(|urls|) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent *must* import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and |urls|, and with the following steps to perform the fetch given the request |request|: + + 1. Let |serviceWorker| be |request|'s client's global object's service worker. + 1. If |serviceWorker|'s imported scripts updated flag is unset, then: + 1. Let |response| be the result of fetching |request|. + 1. If |response|'s unsafe response's type is not "error", and |response|'s status is an ok status, then: + 1. If there exists a corresponding Record |record| for |request|'s url in |serviceWorker|'s script resource map, set |record|.\[[value]] to |response|. + 1. Else, set a newly-created Record {\[[key]]: |url|, \[[value]]: |response|} to |serviceWorker|'s script resource map. + 1. Return |response|. + 1. Else: + 1. If there exists a corresponding Record |record| for |url| in |serviceWorker|'s script resource map, return |record|.\[[value]]. + 1. Else, return a network error.

Cross-Origin Resources and CORS

- This section is non-normative. + *This section is non-normative.* -

Applications tend to cache items that come from a CDN or other origin. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to fetch many sorts of off-origin resources when appropriate CORS headers are set.

-

Service workers enable this by allowing {{Cache|Caches}} to fetch and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding responses are basic filtered response, the objects stored are {{Response}} objects whose corresponding responses are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding responses are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases.

+ Applications tend to cache items that come from a CDN or other origin. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to fetch many sorts of off-origin resources when appropriate CORS headers are set. + Service workers enable this by allowing {{Cache|Caches}} to fetch and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding responses are basic filtered response, the objects stored are {{Response}} objects whose corresponding responses are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding responses are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases.

Implementer Concerns

- This section is non-normative. + *This section is non-normative.* + + The implementers are encouraged to note: -

The implementers are encouraged to note: -

    -
  • Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching fetch event.
  • -
  • Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with service workers.
  • -
-

+ * Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching fetch event. + * Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with service workers.

Privacy

-

Service workers introduce new persistent storage features including scope to registration map (for service worker registrations and their service workers), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages should be cleared when users intend to clear them and should maintain and interoperate with existing user controls e.g. purging all existing persistent storages.

+ Service workers introduce new persistent storage features including scope to registration map (for service worker registrations and their service workers), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages *should* be cleared when users intend to clear them and *should* maintain and interoperate with existing user controls e.g. purging all existing persistent storages.

Storage Considerations

-

Service workers should take a dependency on Quota Management API that extends the ServiceWorkerGlobalScope with the event listeners {{ServiceWorkerGlobalScope/onbeforeevicted}} and {{ServiceWorkerGlobalScope/onevicted}} to detect a storage pressure and give pre-eviction information to the application.

-

The cache write operations in service workers when failed due to exceeding the granted quota limit should throw "{{QuotaExceededError}}" exception.

+ Service workers *should* take a dependency on Quota Management API that extends the ServiceWorkerGlobalScope with the event listeners {{ServiceWorkerGlobalScope/onbeforeevicted}} and {{ServiceWorkerGlobalScope/onevicted}} to detect a storage pressure and give pre-eviction information to the application. + The cache write operations in service workers when failed due to exceeding the granted quota limit *should* throw "{{QuotaExceededError}}" exception.

Extensibility

-

Service workers are extensible from other specifications.

+ Service workers are extensible from other specifications.

Define API bound to Service Worker Registration

-

Specifications may define an API tied to a service worker registration by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it may define the specification specific attributes and methods:

+ Specifications *may* define an API tied to a service worker registration by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it *may* define the specification specific attributes and methods:
       partial interface ServiceWorkerRegistration {
@@ -2364,7 +2126,7 @@ Markup Shorthands: css no, markdown yes
   

Define Functional Event

-

Specifications may define a functional event by extending {{ExtendableEvent}} interface:

+ Specifications *may* define a functional event by extending {{ExtendableEvent}} interface:
       // e.g. define FunctionalEvent interface
@@ -2377,11 +2139,11 @@ Markup Shorthands: css no, markdown yes
   

Define Event Handler

-

Specifications may define an event handler attribute for the corresponding functional event using partial interface definition to the {{ServiceWorkerGlobalScope}} interface:

+ Specifications *may* define an event handler attribute for the corresponding functional event using partial interface definition to the {{ServiceWorkerGlobalScope}} interface:
       partial interface ServiceWorkerGlobalScope {
-        attribute EventHandler onfunctionalevent;
+        attribute EventHandler onfunctionalevent;
       };
     
@@ -2389,1451 +2151,1125 @@ Markup Shorthands: css no, markdown yes

Request Functional Event Dispatch

-

To request a functional event dispatch to a service worker, specifications may invoke Handle Functional Event algorithm with its service worker registration registration and the algorithm callbackSteps as the arguments.

+ To request a functional event dispatch to a service worker, specifications *may* invoke Handle Functional Event algorithm with its service worker registration |registration| and the algorithm |callbackSteps| as the arguments. -

Specifications may define an algorithm callbackSteps where the corresponding functional event can be created and fired with specification specific objects. The algorithm is passed globalObject (a {{ServiceWorkerGlobalScope}} object) at which it may fire its functional events. This algorithm is called on a task queued by Handle Functional Event algorithm.

+ Specifications *may* define an algorithm |callbackSteps| where the corresponding functional event can be created and fired with specification specific objects. The algorithm is passed |globalObject| (a {{ServiceWorkerGlobalScope}} object) at which it *may* fire its functional events. This algorithm is called on a task queued by Handle Functional Event algorithm. -

See an example hook defined in Notifications API.

+ Note: See an example hook defined in Notifications API.

Appendix A: Algorithms

-

The following definitions are the user agent's internal data structures used throughout the specification.

+ The following definitions are the user agent's internal data structures used throughout the specification. -

A scope to registration map is a List of the Record {\[[key]], \[[value]]} where \[[key]] is a string that represents a scope url and \[[value]] is a service worker registration.

+ A scope to registration map is an ordered map where the keys are scope urls and the values are service worker registrations. -

A job is an abstraction of one of register, update, and unregister request for a service worker registration.

+ A job is an abstraction of one of register, update, and unregister request for a service worker registration. -

A job has a job type, which is one of register, update, and unregister.

+
+ A job has a job type, which is one of *register*, *update*, and *unregister*. -

A job has a scope url (a URL).

+ A job has a scope url (a URL). -

A job has a script url (a URL).

+ A job has a script url (a URL). -

A job has a worker type ("classic" or "module").

+ A job has a worker type ("classic" or "module"). -

A job has a client (a service worker client). It is initially null.

+ A job has a client (a service worker client). It is initially null. -

A job has a referrer (a URL or null).

+ A job has a referrer (a URL or null). -

A job has a promise (a promise). It is initially null.

+ A job has a promise (a promise). It is initially null. -

A job has a list of equivalent jobs (a list of jobs). It is initially the empty list.

+ A job has a list of equivalent jobs (a list of jobs). It is initially the empty list. + + A job has a force bypass cache flag It is initially unset. +
-

A job has a force bypass cache flag It is initially unset.

-

Two jobs are equivalent when their job type is the same and: -

-

+ Two jobs are equivalent when their job type is the same and: -

A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue should satisfy the general properties of FIFO queue. A user agent must maintain a separate job queue for each service worker registration keyed by its scope url. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's scope url.

+ * For *register* and *update* jobs, both their scope url and the script url are the same. + * For *unregister* jobs, their scope url is the same. + + A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue *should* satisfy the general properties of FIFO queue. A user agent *must* maintain a separate job queue for each service worker registration keyed by its scope url. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's scope url.

Create Job

-
-
Input
-
jobType, a job type
-
scopeURL, a URL
-
scriptURL, a URL
-
promise, a promise
-
client, a service worker client
-
Output
-
job, a job
-
-
    -
  1. Let job be a new job.
  2. -
  3. Set job's job type to jobType.
  4. -
  5. Set job's scope url to scopeURL.
  6. -
  7. Set job's script url to scriptURL.
  8. -
  9. Set job's promise to promise.
  10. -
  11. Set job's client to client.
  12. -
  13. If client is not null, set job's referrer to client's creation URL.
  14. -
  15. Return job.
  16. -
+ : Input + :: |jobType|, a job type + :: |scopeURL|, a URL + :: |scriptURL|, a URL + :: |promise|, a promise + :: |client|, a service worker client + : Output + :: |job|, a job + + 1. Let |job| be a new job. + 1. Set |job|'s job type to |jobType|. + 1. Set |job|'s scope url to |scopeURL|. + 1. Set |job|'s script url to |scriptURL|. + 1. Set |job|'s promise to |promise|. + 1. Set |job|'s client to |client|. + 1. If |client| is not null, set |job|'s referrer to |client|'s creation URL. + 1. Return |job|.

Schedule Job

-
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. If the job queue is empty, then: -
      -
    1. Push job to the job queue and invoke Run Job.
    2. -
    -
  2. -
  3. Else: -
      -
    1. Let lastJob be the element at the back of the job queue.
    2. -
    3. If job is equivalent to lastJob and lastJob's promise has not settled, append job to lastJob's list of equivalent jobs.
    4. -
    5. Else, push job to the job queue.
    6. -
    -
  4. -
+ : Input + :: |job|, a job + : Output + :: none + + 1. If the job queue is empty, then: + 1. Push |job| to the job queue and invoke Run Job. + 1. Else: + 1. Let |lastJob| be the element at the back of the job queue. + 1. If |job| is equivalent to |lastJob| and |lastJob|'s promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. + 1. Else, push |job| to the job queue. +

Run Job

-
-
Input
-
none
-
Output
-
none
-
-
    -
  1. Assert: the job queue is not empty.
  2. -
  3. Queue a task to run these steps: -
      -
    1. Let job be the element in the front of the job queue.
    2. -
    3. If job's job type is register, run Register with job in parallel.
    4. -
    5. Else if job's job type is update, run Update with job in parallel. -

      For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event.

      -
    6. -
    7. Else if job's job type is unregister, run Unregister with job in parallel.
    8. -
    -
  4. -
+ : Input + :: none + : Output + :: none + + 1. Assert: the job queue is not empty. + 1. Queue a task to run these steps: + 1. Let |job| be the element in the front of the job queue. + 1. If |job|'s job type is *register*, run Register with |job| in parallel. + 1. Else if |job|'s job type is *update*, run Update with |job| in parallel. + Note: For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event. + + 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel. +

Finish Job

-
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. Assert: the top element in the job queue is job.
  2. -
  3. Pop the top element from the job queue.
  4. -
  5. If the job queue is not empty, invoke Run Job with the top element of the job queue.
  6. -
+ : Input + :: |job|, a job + : Output + :: none + + 1. Assert: the top element in the job queue is |job|. + 1. Pop the top element from the job queue. + 1. If the job queue is not empty, invoke Run Job with the top element of the job queue.

Resolve Job Promise

-
-
Input
-
job, a job
-
value, any
-
Output
-
none
-
-
    -
  1. If job's client is not null, queue a task to resolve job's promise with value on job's client's responsible event loop using the DOM manipulation task source as the task source.
  2. -
  3. For each equivalentJob in job's list of equivalent jobs: -
      -
    1. If equivalentJob's client is not null, queue a task to resolve equivalentJob's promise with value on equivalentJob's client's responsible event loop using the DOM manipulation task source as the task source.
    2. -
    -
  4. -
+ : Input + :: |job|, a job + :: |value|, any + : Output + :: none + + 1. If |job|'s client is not null, queue a task to resolve |job|'s promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. For each |equivalentJob| in |job|'s list of equivalent jobs: + 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. +

Reject Job Promise

-
-
Input
-
job, a job
-
reason, an exception
-
Output
-
none
-
-
    -
  1. If job's client is not null, queue a task to reject job's promise with reason on job's client's responsible event loop using the DOM manipulation task source as the task source.
  2. -
  3. For each equivalentJob in job's list of equivalent jobs: -
      -
    1. If equivalentJob's client is not null, queue a task to reject equivalentJob's promise with reason on equivalentJob's client's responsible event loop using the DOM manipulation task source as the task source.
    2. -
    -
  4. -
+ : Input + :: |job|, a job + :: |reason|, an exception + : Output + :: none + + 1. If |job|'s client is not null, queue a task to reject |job|'s promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. For each |equivalentJob| in |job|'s list of equivalent jobs: + 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. +

Start Register

-
-
Input
-
scopeURL, a URL or failure or null
-
scriptURL, a URL or failure
-
promise, a promise
-
client, a service worker client
-
referrer, a URL
-
workerType, a worker type
-
Output
-
none
-
-
    -
  1. If scriptURL is failure, reject promise with a TypeError and abort these steps.
  2. -
  3. If scriptURL's scheme is not one of "http" and "https", reject promise with a TypeError and abort these steps.
  4. -
  5. If any of the strings in scriptURL's path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject promise with a TypeError and abort these steps.
  6. -
  7. If scopeURL is null, set scopeURL to the result of parsing the string "./" with scriptURL. -

    The scope url for the registration is set to the location of the service worker script by default.

    -
  8. -
  9. If scopeURL is failure, reject promise with a TypeError and abort these steps.
  10. -
  11. If scopeURL's scheme is not one of "http" and "https", reject promise with a TypeError and abort these steps.
  12. -
  13. If any of the strings in scopeURL's path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject promise with a TypeError and abort these steps.
  14. -
  15. Let job be the result of running [[#create-job-algorithm]] with register, scopeURL, scriptURL, promise, and client.
  16. -
  17. Set job's worker type to workerType.
  18. -
  19. Set job's referrer to referrer.
  20. -
  21. Invoke [[#schedule-job-algorithm]] with job.
  22. -
+ : Input + :: |scopeURL|, a URL or failure or null + :: |scriptURL|, a URL or failure + :: |promise|, a promise + :: |client|, a service worker client + :: |referrer|, a URL + :: |workerType|, a worker type + : Output + :: none + + 1. If |scriptURL| is failure, reject |promise| with a TypeError and abort these steps. + 1. If |scriptURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. + 1. If any of the strings in |scriptURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. + 1. If |scopeURL| is null, set |scopeURL| to the result of parsing the string "./" with |scriptURL|. + Note: The scope url for the registration is set to the location of the service worker script by default. + + 1. If |scopeURL| is failure, reject |promise| with a TypeError and abort these steps. + 1. If |scopeURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. + 1. If any of the strings in |scopeURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. + 1. Let |job| be the result of running [[#create-job-algorithm]] with *register*, |scopeURL|, |scriptURL|, |promise|, and |client|. + 1. Set |job|'s worker type to |workerType|. + 1. Set |job|'s referrer to |referrer|. + 1. Invoke [[#schedule-job-algorithm]] with |job|.

Register

-
-
Input
-
job, a job
-
Output
-
promise, a promise
-
-
    -
  1. If the result of running Is origin potentially trustworthy with the origin of job's script url as the argument is Not Trusted, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  2. -
  3. If the origin of job's script url is not job's referrer's origin, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  4. -
  5. If the origin of job's scope url is not job's referrer's origin, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  6. -
  7. Let registration be the result of running the Get Registration algorithm passing job's scope url as the argument.
  8. -
  9. If registration is not null, then: -
      -
    1. If registration's uninstalling flag is set, unset it.
    2. -
    3. Let newestWorker be the result of running the Get Newest Worker algorithm passing registration as the argument.
    4. -
    5. If newestWorker is not null and job's script url equals newestWorker's script url with the exclude fragments flag set, then: -
        -
      1. Invoke Resolve Job Promise with job and the {{ServiceWorkerRegistration}} object which represents registration.
      2. -
      3. Invoke Finish Job with job and abort these steps.
      4. -
      -
    6. -
    -
  10. -
  11. Else: -
      -
    1. Invoke Set Registration algorithm passing job's scope url as its argument.
    2. -
    -
  12. -
  13. Invoke Update algorithm passing job as the argument.
  14. -
+ : Input + :: |job|, a job + : Output + :: |promise|, a promise + + 1. If the result of running Is origin potentially trustworthy with the origin of |job|'s script url as the argument is Not Trusted, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. + + 1. If the origin of |job|'s script url is not |job|'s referrer's origin, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. + + 1. If the origin of |job|'s scope url is not |job|'s referrer's origin, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 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 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 and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Invoke Finish Job with |job| and abort these steps. + + + 1. Else: + 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. + + 1. Invoke Update algorithm passing |job| as the argument.

Update

-
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. Let registration be the result of running the Get Registration algorithm passing job's scope url as the argument.
  2. -
  3. If registration is null or registration's uninstalling flag is set, then: -
      -
    1. Invoke Reject Job Promise with job and a TypeError.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  4. -
  5. Let newestWorker be the result of running Get Newest Worker algorithm passing registration as the argument.
  6. -
  7. If job's job type is update, and newestWorker's script url does not equal job's script url with the exclude fragments flag set, then: -
      -
    1. Invoke Reject Job Promise with job and a TypeError.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  8. -
  9. Let httpsState be "none".
  10. -
  11. Let referrerPolicy be the empty string.
  12. -
  13. Switching on job's worker type, run these substeps with the following options: - -
    -
    "classic"
    -

    Fetch a classic worker script given job’s serialized script url, job’s client, "serviceworker", and the to-be-created environment settings object for this service worker.

    -
    "module"
    -

    Fetch a module worker script graph given job’s serialized script url, job’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker.

    -
    -

    To perform the fetch given request, run the following steps if the is top-level flag is set:

    -
      -
    1. Append `Service-Worker`/`script` to request's header list. -

      See the definition of the Service-Worker header in Appendix B: Extended HTTP headers.

      -
    2. -
    3. Set request's skip service worker flag and request's redirect mode to "error".
    4. -
    5. If newestWorker is not null and registration's last update check time is not null, then: -
        -
      1. If the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, or force bypass cache flag is set, set request's cache mode to "reload".
      2. -
      -

      Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache.

      -
    6. -
    7. Fetch request, and asynchronously wait to run the remaining steps as part of fetch's process response for the response response.
    8. -
    9. Extract a MIME type from the response's header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: -
        -
      1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
      2. -
      3. Asynchronously complete these steps with a network error.
      4. -
      -
    10. -
    11. Let serviceWorkerAllowed be the result of parsing `Service-Worker-Allowed` in response's header list. -

      See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers.

      -
    12. -
    13. Set httpsState to response's HTTPS state.
    14. -
    15. Set referrerPolicy to the result of parsing the `Referrer-Policy` header of response.
    16. -
    17. If serviceWorkerAllowed is failure, then: -
        -
      1. Asynchronously complete these steps with a network error.
      2. -
      -
    18. -
    19. Let scopeURL be registration's scope url.
    20. -
    21. Let maxScopeString be null.
    22. -
    23. If serviceWorkerAllowed is null, then: -
        -
      1. Set maxScopeString to "/" concatenated with the strings, except the last string that denotes the script's file name, in job's script url's path (including empty strings), separated from each other by "/".
      2. -
      -
    24. -
    25. Else: -
        -
      1. Let maxScope be the result of parsing serviceWorkerAllowed with job's script url.
      2. -
      3. Set maxScopeString to "/" concatenated with the strings in maxScope's path (including empty strings), separated from each other by "/".
      4. -
      -
    26. -
    27. Let scopeString be "/" concatenated with the strings in scopeURL's path (including empty strings), separated from each other by "/".
    28. -
    29. If scopeString starts with maxScopeString, do nothing.
    30. -
    31. Else: -
        -
      1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
      2. -
      3. Asynchronously complete these steps with a network error.
      4. -
      -
    32. -
    33. If response's cache state is not "local", set registration's last update check time to the current time. -

      The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state.

      -
    34. -
    35. Return true.
    36. -
    -

    If the algorithm asynchronously completes with null, then: -

      -
    1. -

      Invoke Reject Job Promise with job and a TypeError.

      - -

      This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception.

      -
    2. -
    3. If newestWorker is null, invoke Clear Registration algorithm passing registration as its argument.
    4. -
    5. Invoke Finish Job with job and abort these steps.
    6. -
    -

    -

    Else, continue the rest of these steps after the algorithm's asynchronous completion, with script being the asynchronous completion value.

    -
  14. -
  15. If newestWorker is not null, newestWorker's script url equals job's script url with the exclude fragments flag set, and script is a byte-for-byte match with newestWorker's script resource, then: -
      -
    1. Invoke Resolve Job Promise with job and the {{ServiceWorkerRegistration}} object which represents registration.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  16. -
  17. Else: -
      -
    1. Let worker be a new service worker.
    2. -
    3. Generate a unique opaque string and set worker's id to the value.
    4. -
    5. Set worker's script url to job's script url, worker's script resource to script, and worker's type to job's worker type.
    6. -
    7. Set worker's script resource's HTTPS state to httpsState.
    8. -
    9. Set worker's script resource's referrer policy to referrerPolicy.
    10. -
    11. Invoke Run Service Worker algorithm with worker as the argument.
    12. -
    13. If an uncaught runtime script error occurs during the above step, then: -
        -
      1. Invoke Reject Job Promise with job and a TypeError.
      2. -
      3. If newestWorker is null, invoke Clear Registration algorithm passing registration as its argument.
      4. -
      5. Invoke Finish Job with job and abort these steps.
      6. -
      -
    14. -
    -
  18. -
  19. Invoke Install algorithm with job, worker, and registration as its arguments.
  20. -
+ : Input + :: |job|, a job + : Output + :: none + + 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s scope url as the argument. + 1. If |registration| is null or |registration|'s uninstalling flag is set, then: + 1. Invoke Reject Job Promise with |job| and a 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. + 1. If |job|'s job type is *update*, and |newestWorker|'s script url does not equal |job|'s script url with the *exclude fragments flag* set, then: + 1. Invoke Reject Job Promise with |job| and a TypeError. + 1. Invoke Finish Job with |job| and abort these steps. + + 1. Let |httpsState| be "none". + 1. Let |referrerPolicy| be the empty string. + 1. Switching on |job|'s worker type, run these substeps with the following options: + + : *"classic"* + :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". + : *"module"* + :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. + + To perform the fetch given |request|, run the following steps if the is top-level flag is set: + 1. Append `Service-Worker`/`script` to |request|'s header list. + Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. + + 1. Set |request|'s skip service worker flag and |request|'s redirect mode to "error". + 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". + Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. + + 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. + 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + + 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. + Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. + + 1. Set |httpsState| to |response|'s HTTPS state. + 1. Set |referrerPolicy| to the result of parsing the `Referrer-Policy` header of |response|. + 1. If |serviceWorkerAllowed| is failure, then: + 1. Asynchronously complete these steps with a network error. + + 1. Let |scopeURL| be |registration|'s scope url. + 1. Let |maxScopeString| be null. + 1. If |serviceWorkerAllowed| is null, then: + 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". + + 1. Else: + 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. + 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s path (including empty strings), separated from each other by "/". + + 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s path (including empty strings), separated from each other by "/". + 1. If |scopeString| starts with |maxScopeString|, do nothing. + 1. Else: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + + 1. If |response|'s cache state is not "local", set |registration|'s last update check time to the current time. +

The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state. + + 1. Return true. + If the algorithm asynchronously completes with null, then: + 1. + Invoke Reject Job Promise with |job| and a TypeError. + + Note: This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception. + + 1. If |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. + + Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. + + 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Invoke Finish Job with |job| and abort these steps. + + 1. Else: + 1. Let |worker| be a new service worker. + 1. Generate a unique opaque string and set |worker|'s id to the value. + 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. + 1. Set |worker|'s script resource's HTTPS state to |httpsState|. + 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. + 1. Invoke Run Service Worker algorithm with |worker| as the argument. + 1. If an uncaught runtime script error occurs during the above step, then: + 1. Invoke Reject Job Promise with |job| and a TypeError. + 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. Invoke Install algorithm with |job|, |worker|, and |registration| as its arguments.

Soft Update

-

The user agent may call this as often as it likes to check for updates.

- -
-
Input
-
registration, a service worker registration
-
force bypass cache flag, an optional flag unset by default
-

Implementers may use the force bypass cache flag to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs.

-
Output
-
None
-
-
    -
  1. Let newestWorker be the result of running Get Newest Worker algorithm passing registration as its argument.
  2. -
  3. If newestWorker is null, abort these steps.
  4. -
  5. Let job be the result of running Create Job with update, registration's scope url, newestWorker's script url, null, and null.
  6. -
  7. Set job's worker type to newestWorker's type.
  8. -
  9. Set job's force bypass cache flag if its force bypass cache flag is set.
  10. -
  11. Invoke Schedule Job with job.
  12. -
+ The user agent *may* call this as often as it likes to check for updates. + + + : Input + :: |registration|, a service worker registration + :: *force bypass cache flag*, an optional flag unset by default + Note: Implementers may use the *force bypass cache flag* to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs. + : Output + :: None + + 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. + 1. If |newestWorker| is null, abort these steps. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, null, and null. + 1. Set |job|'s worker type to |newestWorker|'s type. + 1. Set |job|'s force bypass cache flag if its *force bypass cache flag* is set. + 1. Invoke Schedule Job with |job|.

Install

-
-
Input
-
job, a job
-
worker, a service worker
-
registration, a service worker registration
-
Output
-
none
-
-
    -
  1. Let installFailed be false.
  2. -
  3. Let newestWorker be the result of running Get Newest Worker algorithm passing registration as its argument.
  4. -
  5. Let redundantWorker be null.
  6. -
  7. Run the Update Registration State algorithm passing registration, "installing" and worker as the arguments.
  8. -
  9. Run the Update Worker State algorithm passing registration's installing worker and installing as the arguments.
  10. -
  11. Assert: job's promise is not null.
  12. -
  13. Invoke Resolve Job Promise with job and the {{ServiceWorkerRegistration}} object which represents registration.
  14. -
  15. 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 scope url and all the service workers whose containing service worker registration is registration.
  16. -
  17. Let installingWorker be registration's installing worker.
  18. -
  19. Invoke Run Service Worker algorithm with installingWorker as the argument.
  20. -
  21. Queue a task task to run the following substeps: -
      -
    1. Let e be the result of creating an event with {{InstallEvent}}.
    2. -
    3. Initialize e’s {{Event/type}} attribute to "install".
    4. -
    5. Dispatch e at installingWorker's global object.
    6. -
    7. Invoke Extend Service Worker Lifetime with e.
    8. -
    9. WaitForAsynchronousExtensions: Run the following substeps in parallel: -
        -
      1. Wait until e's extensions allowed flag is unset.
      2. -
      3. If the result of waiting for all of e's extend lifetime promises rejected, set installFailed to true.
      4. -
      -
    10. -
    -
  22. -

    If task is discarded or the script has been aborted by the termination of installingWorker, set installFailed to true.

    -
  23. Wait for task to have executed or been discarded.
  24. -
  25. Wait for the step labeled WaitForAsynchronousExtensions to complete.
  26. -
  27. If installFailed is true, then: -
      -
    1. Set redundantWorker to registration's installing worker.
    2. -
    3. Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
    4. -
    5. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    6. -
    7. If newestWorker is null, invoke Clear Registration algorithm passing registration as its argument.
    8. -
    9. Invoke Finish Job with job and abort these steps.
    10. -
    -
  28. -
  29. Set registration's installing worker's imported scripts updated flag.
  30. -
  31. If registration's waiting worker is not null, then: -
      -
    1. Set redundantWorker to registration's waiting worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    -
  32. -
  33. Run the Update Registration State algorithm passing registration, "waiting" and registration's installing worker as the arguments.
  34. -
  35. Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
  36. -
  37. Run the Update Worker State algorithm passing registration's waiting worker and installed as the arguments.
  38. -
  39. If redundantWorker is not null, run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
  40. -
  41. If registration's waiting worker's skip waiting flag is set, then: -
      -
    1. Run Activate algorithm passing registration as the argument.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  42. -
  43. Invoke Finish Job with job.
  44. -
  45. Wait for all the tasks queued by Update Worker State invoked in this algorithm have executed.
  46. -
  47. Wait until no service worker client is using registration or registration's waiting worker's skip waiting flag is set.
  48. -
  49. If registration's waiting worker waitingWorker is not null and waitingWorker's skip waiting flag is not set, invoke Activate algorithm with registration as its argument.
  50. -
+ : Input + :: |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. Let |redundantWorker| be null. + 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. Assert: |job|'s promise is not null. + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 scope url and all the service workers whose containing service worker registration is |registration|. + 1. Let |installingWorker| be |registration|'s installing worker. + 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. + 1. Queue a task |task| to run the following substeps: + 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type install, which does not bubble and is not cancelable. + 1. Dispatch |e| at |installingWorker|'s environment settings object's global object |globalObject|. + 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: + 1. Wait until |e|'s extensions allowed flag is unset. + 1. If 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. + 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. Set |redundantWorker| to |registration|'s installing worker. + 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 |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. + + 1. Set |registration|'s installing worker's imported scripts updated flag. + 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. If |registration|'s waiting worker's skip waiting flag is set, then: + 1. Run Activate algorithm passing |registration| as the argument. + 1. Invoke Finish Job with |job| and abort these steps. + + 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 |waitingWorker| is not null and |waitingWorker|'s skip waiting flag is not set, invoke Activate algorithm with |registration| as its argument.

Activate

-
-
Input
-
registration, a service worker registration
-
Output
-
None
-
-
    -
  1. If registration's waiting worker is null, abort these steps.
  2. -
  3. Let redundantWorker be null.
  4. -
  5. If registration's active worker is not null, then: -
      -
    1. Set redundantWorker to registration's active worker.
    2. -
    3. Wait for redundantWorker to finish handling any in-progress requests. -
    4. -
    5. Terminate redundantWorker.
    6. -
    -
  6. -
  7. Run the Update Registration State algorithm passing registration, "active" and registration's waiting worker as the arguments.
  8. -
  9. Run the Update Registration State algorithm passing registration, "waiting" and null as the arguments.
  10. -
  11. Run the Update Worker State algorithm passing registration's active worker and activating as the arguments. -

    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.

    -
  12. -
  13. If redundantWorker is not null, run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
  14. -
  15. For each service worker client client whose creation URL matches registration's scope url: -
      -
    1. If client is a window client, unassociate client's responsible document from its application cache, if it has one.
    2. -
    3. Else if client is a shared worker client, unassociate client's global object from its application cache, if it has one.
    4. -
    -

    Resources will now use the service worker registration instead of the existing application cache.

    -
  16. -
  17. For each service worker client client who is using registration: -
      -
    1. Set client's active worker to registration's active worker.
    2. -
    3. Invoke Notify Controller Change algorithm with client as the argument.
    4. -
    -
  18. -
  19. Let activeWorker be registration's active worker.
  20. -
  21. Invoke Run Service Worker algorithm with activeWorker as the argument.
  22. -
  23. Queue a task task to run the following substeps: -
      -
    1. Let e be the result of creating an event with {{ExtendableEvent}}.
    2. -
    3. Initialize e’s {{Event/type}} attribute to "activate".
    4. -
    5. Dispatch e at activeWorker's global object.
    6. -
    7. Invoke Extend Service Worker Lifetime with e.
    8. -
    9. WaitForAsynchronousExtensions: Wait, in parallel, until e's extensions allowed flag is unset.
    10. -
    -
  24. -
  25. Wait for task to have executed or been discarded, or the script to have been aborted by the termination of activeWorker.
  26. -
  27. Wait for the step labeled WaitForAsynchronousExtensions to complete.
  28. -
  29. Run the Update Worker State algorithm passing registration's active worker and activated as the arguments.
  30. -
+ : Input + :: |registration|, a service worker registration + : Output + :: None + + 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. 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. + 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. + 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: + 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 global object from its application cache, if it has one. + Note: Resources will now use the service worker registration instead of the existing application cache. + + 1. For each service worker client |client| who is using |registration|: + 1. Set |client|'s active worker to |registration|'s active worker. + 1. Invoke Notify Controller Change algorithm with |client| as the argument. + + 1. Let |activeWorker| be |registration|'s active worker. + 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 1. Queue a task |task| to run the following substeps: + 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type activate, which does not bubble and is not cancelable. + 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. + + 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.

Run Service Worker

-
-
Input
-
serviceWorker, a service worker
-
Output
-
None
-
-
    -
  1. Let script be serviceWorker's script resource.
  2. -
  3. Assert: script is not null.
  4. -
  5. If serviceWorker is already running, abort these steps.
  6. -
  7. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context.
  8. -
  9. Call the JavaScript InitializeHostDefinedRealm() abstract operation with the following customizations: + : Input + :: |serviceWorker|, a service worker + : Output + :: None + + 1. Let |script| be |serviceWorker|'s script resource. + 1. Assert: |script| is not null. + 1. If |serviceWorker| is already running, abort these steps. + 1. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context. + 1. Call the JavaScript InitializeHostDefinedRealm() abstract operation with the following customizations:
      -
    • For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let workerGlobalScope be the created object.
    • -
    • Let realmExecutionContext be the created JavaScript execution context.
    • + 1. For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. + 1. Let |realmExecutionContext| be the created JavaScript execution context.
    -
  10. -
  11. Set serviceWorker's global object to workerGlobalScope.
  12. -
  13. Let workerEventLoop be a newly created event loop.
  14. -
  15. Let settingsObject be a new environment settings object whose algorithms are defined as follows: -
    -
    The realm execution context
    -
    Return realmExecutionContext.
    -
    The global object
    -
    Return workerGlobalScope.
    -
    The responsible event loop
    -
    Return workerEventLoop.
    -
    The referrer policy
    -
    Return workerGlobalScope's referrer policy.
    -
    The API URL character encoding
    -
    Return UTF-8.
    -
    The API base URL
    -
    Return serviceWorker's script url.
    -
    The origin
    -
    Return its registering service worker client's origin.
    -
    The creation URL
    -
    Return workerGlobalScope's url.
    -
    The HTTPS state
    -
    Return workerGlobalScope's HTTPS state.
    -
    -
  16. -
  17. Set workerGlobalScope's url to serviceWorker's script url.
  18. -
  19. Set workerGlobalScope's HTTPS state to serviceWorker's script resource's HTTPS state.
  20. -
  21. Set workerGlobalScope's referrer policy to serviceWorker's script resource's referrer policy.
  22. -
  23. Set workerGlobalScope's type to serviceWorker's type.
  24. -
  25. Create a new {{WorkerLocation}} object and associate it with workerGlobalScope.
  26. -
  27. If serviceWorker is an active worker, and there are any tasks queued in serviceWorker's containing service worker registration's task queues, queue them to serviceWorker's event loop's task queues in the same order using their original task sources.
  28. -
  29. If script is a classic script, then run the classic script script. Otherwise, it is a module script; run the module script script. -

    In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms.

    -
  30. -
  31. If script's has ever been evaluated flag is unset, then: -
      -
    1. Set workerGlobalScope's associated service worker's set of event types to handle to the set of event types created from settingsObject's global object's associated list of event listeners' event types. -

      If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script.

      -
    2. -
    3. Set script's has ever been evaluated flag.
    4. -
    -
  32. -
  33. Run the responsible event loop specified by settingsObject until it is destroyed.
  34. -
  35. Empty workerGlobalScope's list of active timers.
  36. -
+ + 1. Let |workerEventLoop| be a newly created event loop. + 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: + + : The realm execution context + :: Return |realmExecutionContext|. + : The global object + :: Return |workerGlobalScope|. + : The responsible event loop + :: Return |workerEventLoop|. + : The referrer policy + :: Return |workerGlobalScope|'s referrer policy. + : The API URL character encoding + :: Return UTF-8. + : The API base URL + :: Return |serviceWorker|'s script url. + : The origin + :: Return its registering service worker client's origin. + : The creation URL + :: Return |workerGlobalScope|'s url. + : The HTTPS state + :: Return |workerGlobalScope|'s HTTPS state. + + + 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. + 1. Set |workerGlobalScope|'s HTTPS state to |serviceWorker|'s script resource's HTTPS state. + 1. Set |workerGlobalScope|'s referrer policy to |serviceWorker|'s script resource's referrer policy. + 1. Set |workerGlobalScope|'s type to |serviceWorker|'s type. + 1. Create a new {{WorkerLocation}} object and associate it with |workerGlobalScope|. + 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. + 1. If |script| is a classic script, then run the classic script |script|. Otherwise, it is a module script; run the module script |script|. + Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. + + 1. If |script|'s has ever been evaluated flag is unset, then: + 1. Set |workerGlobalScope|'s associated service worker's set of event types to handle to the set of event types created from |settingsObject|'s global object's associated list of event listeners' event types. + Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. + + 1. Set |script|'s has ever been evaluated flag. + + 1. Run the responsible event loop specified by |settingsObject| until it is destroyed. + 1. Empty |workerGlobalScope|'s list of active timers.

Terminate Service Worker

-
-
Input
-
serviceWorker, a service worker
-
Output
-
None
-
-
    -
  1. If serviceWorker is not running, abort these steps.
  2. -
  3. Let serviceWorkerGlobalScope be serviceWorker's global object.
  4. -
  5. Set serviceWorkerGlobalScope's closing flag to true.
  6. -
  7. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in serviceWorkerGlobalScope's event loop's task queues, queue them to serviceWorker's containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from serviceWorkerGlobalScope's event loop's task queues without processing them. -

    This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded.

    -
  8. -
  9. Abort the script currently running in serviceWorker.
  10. -
  11. Set serviceWorker's global object to null.
  12. -
-
- -
-

Extend Service Worker Lifetime

- -
-
Input
-
event, an {{ExtendableEvent}} object
-
Output
-
None
-
-
    -
  1. If event's extend lifetime promises is empty, unset event's extensions allowed flag and abort these steps.
  2. -
  3. Let extendLifetimePromises be an empty array.
  4. -
  5. Run the following substeps in parallel: -
      -
    1. SetupPromiseArray: Set extendLifetimePromises to a copy of event's extend lifetime promises.
    2. -
    3. Wait until all the promises in extendLifetimePromises settle.
    4. -
    5. If the length of extendLifetimePromises does not equal the length of event's extend lifetime promises, jump to the step labeled SetupPromiseArray.
    6. -
    7. Unset event's extensions allowed flag.
    8. -
    -
  6. -
- -

The user agent should not terminate the service worker associated with event's relevant settings object's global object until event's extensions allowed flag is unset. However, the user agent may impose a time limit to this lifetime extension.

+ : Input + :: |serviceWorker|, a service worker + : Output + :: None + + 1. If |serviceWorker| is not running, abort these steps. + 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s environment settings object's global object. + 1. Set |serviceWorkerGlobalScope|'s closing flag to true. + 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's task queues, queue them to |serviceWorker|'s containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's task queues without processing them. + Note: This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded. + + 1. Abort the script currently running in |serviceWorker|.

Handle Fetch

-

The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context.

+ The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context. -
-
Input
-
request, a request
-
Output
-
response, a response
-
+ + : Input + :: |request|, a request + : Output + :: |response|, a response +
    -
  1. Let handleFetchFailed be false.
  2. -
  3. Let respondWithEntered be false.
  4. -
  5. Let eventCanceled be false.
  6. -
  7. Let r be a new {{Request}} object associated with request.
  8. -
  9. Let headersObject be r's {{Request/headers}} attribute value.
  10. -
  11. Set headersObject's guard to immutable.
  12. -
  13. Let response be null.
  14. -
  15. Let registration be null.
  16. -
  17. Let client be request's client.
  18. -
  19. Let reservedClient be request's reserved client.
  20. -
  21. Assert: request's destination is not "serviceworker".
  22. -
  23. If request is a potential-navigation-or-subresource request, then: -
      -
    1. Return null.
    2. -
    -
  24. -
  25. Else if request is a non-subresource request, then: -

    If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration.

    -
      -
    1. If reservedClient is not null and is an environment settings object, then: -
        -
      1. If reservedClient is not a secure context, return null.
      2. -
      -
    2. -
    3. Else: -
        -
      1. If request's url is not a potentially trustworthy URL, return null.
      2. -
      -
    4. -
    5. If request is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null.
    6. -
    7. Set registration to the result of running Match Service Worker Registration algorithm passing request's url as the argument.
    8. -
    9. If registration is null or registration's active worker is null, return null.
    10. -
    11. If request's destination is not "report", set reservedClient's active service worker to registration's active worker.
    12. -
    -

    From this point, the service worker client starts to use its active service worker's containing service worker registration.

    -
  26. -
  27. Else if request is a subresource request, then: -
      -
    1. If client's active service worker is non-null, set registration to client's active service worker's containing service worker registration.
    2. -
    3. Else, return null.
    4. -
    -
  28. -
  29. Let activeWorker be registration's active worker.
  30. -
  31. If activeWorker's set of event types to handle does not contain fetch, then: -
      -
    1. Return null and continue running these steps in parallel.
    2. -
    3. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    5. Abort these steps.
    6. -
    -

    To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution.

    -
  32. -
  33. If activeWorker's state is activating, wait for activeWorker's state to become activated.
  34. -
  35. Invoke Run Service Worker algorithm with activeWorker as the argument.
  36. -
  37. Queue a task task to run the following substeps: -
      -
    1. Let e be the result of creating an event with {{FetchEvent}}.
    2. -
    3. Initialize e’s {{Event/type}} attribute to "fetch".
    4. -
    5. Initialize e’s {{Event/cancelable}} attribute to true.
    6. -
    7. Initialize e’s {{FetchEvent/request}} attribute to r.
    8. -
    9. Initialize e's {{FetchEvent/clientId}} attribute to client's id.
    10. -
    11. If request is a non-subresource request and request's destination is not "report", initialize e's {{FetchEvent/reservedClientId}} attribute to reservedClient's id, and to the empty string otherwise.
    12. -
    13. If request is a navigation request, initialize e's {{FetchEvent/targetClientId}} attribute to request's target client id, and to the empty string otherwise.
    14. -
    15. Let the {{FetchEvent/isReload}} attribute of e be initialized to true if request's client is a window client and the event was dispatched with the user's intention for the page reload, and false otherwise.
    16. -
    17. Dispatch e at activeWorker's global object.
    18. -
    19. Invoke Extend Service Worker Lifetime with e.
    20. -
    21. If e's respond-with entered flag is set, set respondWithEntered to true.
    22. -
    23. If e's wait to respond flag is set, then: -
        -
      1. Wait until e's wait to respond flag is unset.
      2. -
      3. If e's respond-with error flag is set, set handleFetchFailed to true.
      4. -
      5. Else, set response to e's potential response.
      6. -
      -
    24. -
    25. If e's canceled flag is set, set eventCanceled to true.
    26. -
    -

    If task is discarded or the script has been aborted by the termination of activeWorker, set handleFetchFailed to true.

    -

    The task must use activeWorker's event loop and the handle fetch task source.

    -
  38. -
  39. Wait for task to have executed or been discarded.
  40. -
  41. If respondWithEntered is false, then: -
      -
    1. If eventCanceled is true, return a network error and continue running these steps in parallel.
    2. -
    3. Else, return null and continue running these steps in parallel.
    4. -
    5. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    6. -
    7. Abort these steps.
    8. -
    -
  42. -
  43. If handleFetchFailed is true, then: -
      -
    1. Return a network error and continue running these steps in parallel.
    2. -
    3. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    -
  44. -
  45. Else: -
      -
    1. Return response and continue running these steps in parallel.
    2. -
    3. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    -
  46. -
+ 1. Let |handleFetchFailed| be false. + 1. Let |respondWithEntered| be false. + 1. Let |eventCanceled| be false. + 1. Let |r| be a new {{Request}} object associated with |request|. + 1. Let |headersObject| be |r|'s {{Request/headers}} attribute value. + 1. Set |headersObject|'s guard to *immutable*. + 1. Let |response| be null. + 1. Let |registration| be null. + 1. Let |client| be |request|'s client. + 1. Let |reservedClient| be |request|'s reserved client. + 1. Assert: |request|'s destination is not "serviceworker". + 1. If |request| is a potential-navigation-or-subresource request, then: + 1. Return null. + + 1. Else if |request| is a non-subresource request, then: + Note: If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration. + 1. If |reservedClient| is not null and is an environment settings object, then: + 1. If |reservedClient| is not a secure context, return null. + + 1. Else: + 1. If |request|'s url is not a potentially trustworthy URL, return null. + + 1. If |request| is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null. + 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s url as the argument. + 1. If |registration| is null or |registration|'s active worker is null, return null. + 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. + Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. + + 1. Else if |request| is a subresource request, then: + 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. + 1. Else, return null. + + 1. Let |activeWorker| be |registration|'s active worker. + 1. If |activeWorker|'s set of event types to handle does not contain fetch, then: + 1. Return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + Note: To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. + + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. + 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 1. Queue a task |task| to run the following substeps: + 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. + 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. + 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. + 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. + 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s target client id, and to the empty string otherwise. + 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s 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 environment settings object's global object. + 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. + 1. If |e|'s wait to respond flag is set, then: + 1. Wait until |e|'s wait to respond flag is unset. + 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. + 1. Else, set |response| to |e|'s potential response. + + 1. If |e|'s canceled flag is set, set |eventCanceled| to true. + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + The |task| *ust* use |activeWorker|'s event loop and the handle fetch task source. + + 1. Wait for |task| to have executed or been discarded. + 1. If |respondWithEntered| is false, then: + 1. If |eventCanceled| is true, return a network error and continue running these steps in parallel. + 1. Else, return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + + 1. If |handleFetchFailed| is true, then: + 1. Return a network error and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + + 1. Else: + 1. Return |response| and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. +

Handle Foreign Fetch

-

The [[#on-foreign-fetch-request-algorithm]] algorithm is the entry point for the fetch handling handed to the service worker context to handle foreign fetch requests.

+ The [[#on-foreign-fetch-request-algorithm]] algorithm is the entry point for the fetch handling handed to the service worker context to handle foreign fetch requests. -
-
Input
-
request, a request
-
Output
-
response, a response
-
+ + : Input + :: |request|, a request + : Output + :: |response|, a response +
    -
  1. Let handleFetchFailed be false.
  2. -
  3. Let respondWithEntered be false.
  4. -
  5. Let eventCanceled be false.
  6. -
  7. If request is not a subresource request, return null and abort these steps. -

    Foreign fetch only allows intercepting of subresource requests. Navigation requests can be intercepted by the regular fetch event anyway, so there is no benefit to supporting those requests here as well.

    -
  8. -
  9. If request's client is not a secure context, return null and abort these steps.
  10. -
  11. Let activeWorker be the result of running the [[#foreign-fetch-scope-match-algorithm]] algorithm passing request's url as the argument.
  12. -
  13. If activeWorker is null, return null.
  14. -
  15. If activeWorker's state is activating, then: -
      -
    1. Wait for activeWorker's state to become activated.
    2. -
    -
  16. -
  17. If activeWorker's origin is the same as request's origin, return null.
  18. -
  19. Let originMatches be false.
  20. -
  21. If activeWorker's list of foreign fetch origins is empty, set originMatches to true.
  22. -
  23. For each origin in activeWorker's list of foreign fetch origins: -
      -
    1. If origin is equal to request's origin, set originMatches to true.
    2. -
    -
  24. -
  25. If originMatches is false, return null.
  26. -
  27. Let r be a new {{Request}} object associated with request.
  28. -
  29. Invoke [[#run-service-worker-algorithm]] algorithm with activeWorker as the argument.
  30. -
  31. Queue a task task to run the following substeps: -
      -
    1. Let e be the result of creating an event with {{ForeignFetchEvent}}.
    2. -
    3. Initialize e’s {{Event/type}} attribute to "foreignfetch".
    4. -
    5. Initialize e’s {{Event/cancelable}} attribute to true.
    6. -
    7. Initialize e’s {{ForeignFetchEvent/request}} attribute to r.
    8. -
    9. Initialize e’s {{ForeignFetchEvent/origin}} attribute to the Unicode serialization of request's origin.
    10. -
    11. Dispatch e at activeWorker's global object.
    12. -
    13. Invoke Extend Service Worker Lifetime with e.
    14. -
    15. If e's respond-with entered flag is set, set respondWithEntered to true.
    16. -
    17. If e's wait to respond flag is set, wait until e's wait to respond flag is unset.
    18. -
    19. Let internalResponse be e's potential response.
    20. -
    21. If internalResponse is a filtered response, set internalResponse to internalResponse's internal response.
    22. -
    23. If e's respond-with error flag is set, set handleFetchFailed to true.
    24. -
    25. Else if e's origin is null: -
        -
      1. If e's list of exposed headers is not empty, set handleFetchFailed to true.
      2. -
      3. Else if e's potential response is a opaque-redirect filtered response, set response to e's potential response.
      4. -
      5. Else set response to an opaque filtered response of internalResponse.
      6. -
      -
    26. -
    27. Else if e's origin is not equal to the Unicode serialization of request's origin, set handleFetchFailed to true.
    28. -
    29. Else if e's potential response is an opaque filtered response or is an opaque-redirect filtered response, set response to e's potential response.
    30. -
    31. Else if request's response tainting is "opaque", set response to an opaque filtered response of internalResponse.
    32. -
    33. Else: -
        -
      1. Let headers be e's list of exposed headers.
      2. -
      3. If response is a CORS filtered response, remove from internalResponse's CORS-exposed header-name list all values not in headers.
      4. -
      5. Else set internalResponse's CORS-exposed header-name list to headers.
      6. -
      7. Set response to a CORS filtered response of internalResponse.
      8. -
      -
    34. -
    35. If e's canceled flag is set, set eventCanceled to true.
    36. -
    -

    If task is discarded or the script has been aborted by the termination of activeWorker, set handleFetchFailed to true.

    -

    The task must use activeWorker's event loop and the handle fetch task source.

    -
  32. -
  33. Wait for task to have executed or been discarded.
  34. -
  35. If respondWithEntered is false, then: -
      -
    1. If eventCanceled is true, then: -
        -
      1. Return a network error.
      2. -
      -
    2. -
    3. Else: -
        -
      1. Return null.
      2. -
      -
    4. -
    -
  36. -
  37. If handleFetchFailed is true, then: -
      -
    1. Return a network error.
    2. -
    -
  38. -
  39. Else: -
      -
    1. Return response.
    2. -
    -
  40. -
+ 1. Let |handleFetchFailed| be false. + 1. Let |respondWithEntered| be false. + 1. Let |eventCanceled| be false. + 1. If |request| is not a subresource request, return null and abort these steps. + Note: Foreign fetch only allows intercepting of subresource requests. Navigation requests can be intercepted by the regular fetch event anyway, so there is no benefit to supporting those requests here as well. + + 1. If |request|'s client is not a secure context, return null and abort these steps. + 1. Let |activeWorker| be the result of running the [[#foreign-fetch-scope-match-algorithm]] algorithm passing |request|'s url as the argument. + 1. If |activeWorker| is null, return null. + 1. If |activeWorker|'s state is *activating*, then: + 1. Wait for |activeWorker|'s state to become *activated*. + + 1. If |activeWorker|'s origin is the same as |request|'s origin, return null. + 1. Let |originMatches| be false. + 1. If |activeWorker|'s list of foreign fetch origins is empty, set |originMatches| to true. + 1. For each |origin| in |activeWorker|'s list of foreign fetch origins: + 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. + + 1. If |originMatches| is false, return null. + 1. Let |r| be a new {{Request}} object associated with |request|. + 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. + 1. Queue a task |task| to run the following substeps: + 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. + 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. + 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. + 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. If |e|'s 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 potential response. + 1. If |internalResponse| is a filtered response, set |internalResponse| to |internalResponse|'s internal response. + 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. + 1. Else if |e|'s origin is null: + 1. If |e|'s list of exposed headers is not empty, set |handleFetchFailed| to true. + 1. Else if |e|'s potential response is a opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else set |response| to an opaque filtered response of |internalResponse|. + + 1. Else if |e|'s origin is not equal to the Unicode serialization of |request|'s origin, set |handleFetchFailed| to true. + 1. Else if |e|'s potential response is an opaque filtered response or is an opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else if |request|'s response tainting is "opaque", set |response| to an opaque filtered response of |internalResponse|. + 1. Else: + 1. Let |headers| be |e|'s list of exposed headers. + 1. If |response| is a CORS filtered response, remove from |internalResponse|'s CORS-exposed header-name list all values not in |headers|. + 1. Else set |internalResponse|'s CORS-exposed header-name list to |headers|. + 1. Set |response| to a CORS filtered response of |internalResponse|. + + 1. If |e|'s canceled flag is set, set |eventCanceled| to true. + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + The |task| *ust* use |activeWorker|'s event loop and the handle fetch task source. + + 1. Wait for |task| to have executed or been discarded. + 1. If |respondWithEntered| is false, then: + 1. If |eventCanceled| is true, then: + 1. Return a network error. + + 1. Else: + 1. Return null. + + + 1. If |handleFetchFailed| is true, then: + 1. Return a network error. + + 1. Else: + 1. Return |response|. +

Handle Functional Event

-
-
Input
-
event, an {{ExtendableEvent}} object
-
registration, a service worker registration
-
callbackSteps, an algorithm
-
Output
-
None
-
-
    -
  1. Assert: a Record with the \[[value]] equals to registration is contained in scope to registration map.
  2. -
  3. Assert: registration's active worker is not null.
  4. -
  5. Let activeWorker be registration's active worker.
  6. -
  7. If activeWorker's set of event types to handle does not contain event's {{Event/type}}, then: -
      -
    1. Return and continue running these steps in parallel.
    2. -
    3. If the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    5. Abort these steps.
    6. -
    -

    To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution.

    -
  8. -
  9. If activeWorker's state is activating, wait for activeWorker's state to become activated.
  10. -
  11. Invoke Run Service Worker algorithm with activeWorker as the argument.
  12. -
  13. Queue a task task to run these substeps: -
      -
    1. Invoke callbackSteps with activeWorker's global object as its argument.
    2. -
    3. Invoke Extend Service Worker Lifetime with event.
    4. -
    -

    The task must use activeWorker's event loop and the handle functional event task source.

    -
  14. -
  15. Wait for task to have executed or been discarded.
  16. -
  17. If the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
  18. -
+ : Input + :: |registration|, a service worker registration + :: |callbackSteps|, an algorithm + : Output + :: None + + 1. Assert: a Record with the \[[value]] equals to |registration| is contained in scope to registration map. + 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 contain the event type for this functional event, then: + 1. Return and continue running these steps in parallel. + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + Note: To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. + + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. + 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 1. Queue a task |task| to invoke |callbackSteps| with |activeWorker|'s environment settings object's global object as its argument. + The |task| *ust* use |activeWorker|'s event loop and the handle functional event task source. + + 1. Wait for |task| to have executed or been discarded. + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|.

Handle Service Worker Client Unload

-

The user agent must run these steps when a service worker client unloads by unloading, being killed, or terminating.

+ The user agent *ust* run these steps when a service worker client unloads by unloading, being killed, or terminating. -
-
Input
-
client, a service worker client
-
Output
-
None
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let registration be the service worker registration used by client.
  4. -
  5. If registration is null, abort these steps.
  6. -
  7. If any other service worker client is using registration, abort these steps.
  8. -
  9. If registration's uninstalling flag is set, invoke Clear Registration algorithm passing registration as its argument and abort these steps.
  10. -
  11. If registration's waiting worker is not null, run Activate algorithm with registration as the argument.
  12. -
+ + : Input + :: |client|, a service worker client + : Output + :: None + + 1. Run the following steps atomically. + 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 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.

Handle User Agent Shutdown

-
-
Input
-
None
-
Output
-
None
-
-
    -
  1. For each Record {\[[key]], \[[value]]} entry of its scope to registration map: -
      -
    1. Let registration be entry.\[[value]].
    2. -
    3. If registration's installing worker installingWorker is not null, then: -
        -
      1. If the result of running Get Newest Worker with registration is installingWorker, invoke Clear Registration with registration and continue to the next iteration of the loop.
      2. -
      3. Else, set registration's installing worker to null.
      4. -
      -
    4. -
    5. If registration's waiting worker is not null, run the following substep in parallel: -
        -
      1. Invoke Activate with registration.
      2. -
      -
    6. -
    -
  2. -
+ : Input + :: None + : Output + :: None + + 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: + 1. Let |registration| be |entry|.\[[value]]. + 1. If |registration|'s installing worker |installingWorker| is not null, then: + 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. + 1. Else, set |registration|'s installing worker to null. + + 1. If |registration|'s waiting worker is not null, run the following substep in parallel: + 1. Invoke Activate with |registration|. +

Unregister

-
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. If the origin of job's scope url is not job's client's origin, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  2. -
  3. Let registration be the result of running Get Registration algorithm passing job's scope url as the argument.
  4. -
  5. If registration is null, then: -
      -
    1. Invoke Resolve Job Promise with job and false.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  6. -
  7. Set registration's uninstalling flag.
  8. -
  9. Invoke Resolve Job Promise with job and true.
  10. -
  11. If no service worker client is using registration, invoke Clear Registration algorithm passing registration as its argument. -

    When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm.

    -
  12. -
  13. Invoke Finish Job with job.
  14. -
+ : Input + :: |job|, a job + : Output + :: none + + 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. + + 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s scope url as the argument. + 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. Invoke Resolve Job Promise with |job| and true. + 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. + Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. + + 1. Invoke Finish Job with |job|.

Set Registration

-
-
Input
-
scope, a URL
-
Output
-
registration, a service worker registration
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let scopeString be serialized scope with the exclude fragment flag set.
  4. -
  5. Let registration be a new service worker registration whose scope url is set to scope.
  6. -
  7. Set a newly-created Record {\[[key]]: scopeString, \[[value]]: registration} to scope to registration map.
  8. -
  9. Return registration.
  10. -
+ : Input + :: |scope|, a URL + : Output + :: |registration|, a service worker registration + + 1. Run the following steps atomically. + 1. Let |scopeString| be serialized |scope| with the *exclude fragment flag* set. + 1. Let |registration| be a new service worker registration whose scope url is set to |scope|. + 1. Set a newly-created Record {\[[key]]: |scopeString|, \[[value]]: |registration|} to scope to registration map. + 1. Return |registration|.

Clear Registration

-
-
Input
-
registration, a service worker registration
-
Output
-
None
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let redundantWorker be null.
  4. -
  5. If registration's installing worker is not null, then: -
      -
    1. Set redundantWorker to registration's installing worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    7. Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
    8. -
    9. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    10. -
    -
  6. -
  7. If registration's waiting worker is not null, then: -
      -
    1. Set redundantWorker to registration's waiting worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    7. Run the Update Registration State algorithm passing registration, "waiting" and null as the arguments.
    8. -
    9. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    10. -
    -
  8. -
  9. If registration's active worker is not null, then: -
      -
    1. Set redundantWorker to registration's active worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    7. Run the Update Registration State algorithm passing registration, "active" and null as the arguments.
    8. -
    9. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    10. -
    -
  10. -
  11. Delete a Record {\[[key]], \[[value]]} entry from scope to registration map where registration's scope url is the result of parsing entry.\[[key]].
  12. -
+ : Input + :: |registration|, a service worker registration + : Output + :: None + + 1. Run the following steps atomically. + 1. Let |redundantWorker| be null. + 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. Delete a Record {\[[key]], \[[value]]} |entry| from scope to registration map where |registration|'s scope url is the result of parsing |entry|.\[[key]].

Update Registration 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.
  2. -
  3. If target is "installing", then: -
      -
    1. Set registration's installing worker to source.
    2. -
    3. 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.
      2. -
      -
    4. -
    -
  4. -
  5. Else if target is "waiting", then: -
      -
    1. Set registration's waiting worker to source.
    2. -
    3. 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.
      2. -
      -
    4. -
    -
  6. -
  7. Else if target is "active", then: -
      -
    1. Set registration's active worker to source.
    2. -
    3. 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 active worker, or null if registration’s active worker is null.
      2. -
      -
    4. -
    -

    The task must use registrationObject's relevant settings object's responsible event loop and the DOM manipulation task source.

    -
  8. -
+ : 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 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 active worker, or null if |registration|’s active worker is null. + + The task *ust* use |registrationObject|'s relevant settings object's responsible event loop and the DOM manipulation task source. +

Update Worker State

-
-
Input
-
worker, a service worker
-
state, a service worker's state
-
Output
-
None
-
-
    -
  1. Set worker's state to state.
  2. -
  3. Let workerObjects be an array containing all the {{ServiceWorker}} objects associated with worker.
  4. -
  5. 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" -

        The service worker in this state is considered an installing worker. During this state, event.waitUntil(f) 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" -

        The service worker in this state is considered a waiting worker.

        - -
        activating
        -
        "activating" -

        The service worker in this state is considered an active worker. During this state, event.waitUntil(f) 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" -

        The service worker in this state is considered an active worker ready to handle functional events.

        - -
        redundant
        -
        "redundant" -

        A new service worker is replacing the current service worker, or the current service worker is being discarded due to an install failure.

        -
        -
      2. -
      3. Fire an event named statechange at workerObject.
      4. -
      -
    2. -
    -

    The task must use workerObject's relevant settings object's responsible event loop and the DOM manipulation task source.

    -
  6. -
+ : Input + :: |worker|, a service worker + :: |state|, a service worker's state + : 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, event.waitUntil(|f|) 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" + 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, event.waitUntil(|f|) 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 *ust* 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.
  2. -
  3. If client is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object client is associated with.
  4. -
-

The task must use client's responsible event loop and the DOM manipulation task source.

+ : Input + :: |client|, a service worker client + : Output + :: None + + 1. Assert: |client| is not null. + 1. If |client| is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object |client| is associated with. + The task *ust* use |client|'s responsible event loop and the DOM manipulation task source.

Match Service Worker Registration

-
-
Input
-
clientURL, a URL
-
Output
-
registration, a service worker registration
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let clientURLString be serialized clientURL.
  4. -
  5. Let matchingScope be the empty string.
  6. -
  7. Set matchingScope to the longest \[[key]] in scope to registration map which the value of clientURLString starts with, if it exists. -

    The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix").

    -
  8. -
  9. Let parsedMatchingScope be null.
  10. -
  11. If matchingScope is not the empty string, set parsedMatchingScope to the result of parsing matchingScope.
  12. -
  13. Let registration be the result of running Get Registration algorithm passing parsedMatchingScope as the argument.
  14. -
  15. If registration is not null and registration's uninstalling flag is set, return null.
  16. -
  17. Return registration.
  18. -
+ : Input + :: |clientURL|, a URL + : Output + :: |registration|, a service worker registration + + 1. Run the following steps atomically. + 1. Let |clientURLString| be serialized |clientURL|. + 1. Let |matchingScope| be the empty string. + 1. Set |matchingScope| to the longest \[[key]] in scope to registration map which the value of |clientURLString| starts with, if it exists. + Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). + + 1. Let |parsedMatchingScope| be null. + 1. If |matchingScope| is not the empty string, set |parsedMatchingScope| to the result of parsing |matchingScope|. + 1. Let |registration| be the result of running Get Registration algorithm passing |parsedMatchingScope| as the argument. + 1. If |registration| is not null and |registration|'s uninstalling flag is set, return null. + 1. Return |registration|.

Match Service Worker for Foreign Fetch

-
-
Input
-
requestURL, a URL
-
Output
-
worker, a service worker
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let registration be the result of running the [[#scope-match-algorithm]] algorithm passing requestURL as the argument.
  4. -
  5. If registration is null, return null.
  6. -
  7. Let worker be registration's active worker.
  8. -
  9. If worker is null, return null.
  10. -
  11. Let requestURLString be the serialized requestURL.
  12. -
  13. For each URL scope in worker's list of foreign fetch scopes: -
      -
    1. Let scopeString be the serialized scope.
    2. -
    3. If requestString starts with scopeString return worker.
    4. -
    -
  14. -
  15. Return null.
  16. -
+ : Input + :: |requestURL|, a URL + : Output + :: |worker|, a service worker + + 1. Run the following steps atomically. + 1. Let |registration| be the result of running the [[#scope-match-algorithm]] algorithm passing |requestURL| as the argument. + 1. If |registration| is null, return null. + 1. Let |worker| be |registration|'s active worker. + 1. If |worker| is null, return null. + 1. Let |requestURLString| be the serialized |requestURL|. + 1. For each URL |scope| in |worker|'s list of foreign fetch scopes: + 1. Let |scopeString| be the serialized |scope|. + 1. If |requestString| starts with |scopeString| return |worker|. + + 1. Return null.

Get Registration

-
-
Input
-
scope, a URL
-
Output
-
registration, a service worker registration
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let scopeString be the empty string.
  4. -
  5. If scope is not null, set scopeString to serialized scope with the exclude fragment flag set.
  6. -
  7. Let registration be null.
  8. -
  9. For each Record {\[[key]], \[[value]]} entry of its scope to registration map: -
      -
    1. If scopeString matches entry.\[[key]], set registration to entry.\[[value]].
    2. -
    -
  10. -
  11. Return registration.
  12. -
+ : Input + :: |scope|, a URL + : Output + :: |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 serialized |scope| with the *exclude fragment flag* set. + 1. Let |registration| be null. + 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: + 1. If |scopeString| matches |entry|.\[[key]], set |registration| to |entry|.\[[value]]. + + 1. Return |registration|.

Get Newest Worker

-
-
Input
-
registration, a service worker registration
-
Output
-
worker, a service worker
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let newestWorker be null.
  4. -
  5. If registration's installing worker is not null, set newestWorker to registration's installing worker.
  6. -
  7. Else if registration's waiting worker is not null, set newestWorker to registration's waiting worker.
  8. -
  9. Else if registration's active worker is not null, set newestWorker to registration's active worker.
  10. -
  11. Return newestWorker.
  12. -
+ : Input + :: |registration|, a service worker registration + : Output + :: |worker|, a service worker + + 1. Run the following steps atomically. + 1. Let |newestWorker| be null. + 1. If |registration|'s installing worker is not null, set |newestWorker| to |registration|'s installing worker. + 1. Else if |registration|'s waiting worker is not null, set |newestWorker| to |registration|'s waiting worker. + 1. Else if |registration|'s active worker is not null, set |newestWorker| to |registration|'s active worker. + 1. Return |newestWorker|.

Create Client

-
-
Input
-
client, a service worker client
-
Output
-
clientObject, a {{Client}} object
-
-
    -
  1. Let clientObject be a new {{Client}} object.
  2. -
  3. Set clientObject's service worker client to client.
  4. -
  5. Set clientObject's reserved state to true if client's execution ready flag is unset, and false otherwise.
  6. -
  7. Return clientObject.
  8. -
+ : Input + :: |client|, a service worker client + : Output + :: |clientObject|, a {{Client}} object + + 1. Let |clientObject| be a new {{Client}} object. + 1. Set |clientObject|'s service worker client to |client|. + 1. Set |clientObject|'s reserved state to true if |client|'s execution ready flag is unset, and false otherwise. + 1. Return |clientObject|.

Create Window Client

-
-
Input
-
client, a service worker client
-
visibilityState, a string
-
focusState, a boolean
-
ancestorOrigins, an array
-
Output
-
windowClient, a {{WindowClient}} object
-
-
    -
  1. Let windowClient be a new {{WindowClient}} object.
  2. -
  3. Set windowClient's service worker client to client.
  4. -
  5. Set windowClient's visibility state to visibilityState.
  6. -
  7. Set windowClient's focus state to focusState.
  8. -
  9. Set windowClient's ancestor origins array to ancestorOrigins.
  10. -
  11. Return windowClient.
  12. -
+ : Input + :: |client|, a service worker client + :: |visibilityState|, a string + :: |focusState|, a boolean + :: |ancestorOrigins|, an array + : Output + :: |windowClient|, a {{WindowClient}} object + + 1. Let |windowClient| be a new {{WindowClient}} object. + 1. Set |windowClient|'s service worker client to |client|. + 1. Set |windowClient|'s visibility state to |visibilityState|. + 1. Set |windowClient|'s focus state to |focusState|. + 1. Set |windowClient|'s ancestor origins array to |ancestorOrigins|. + 1. Return |windowClient|.

Query Cache

-
-
Input
-
request, a {{Request}} object
-
options, a {{CacheQueryOptions}} object, optional
-
targetStorage, an array that has [{{Request}}, {{Response}}] pairs as its elements, optional
-
Output
-
resultArray, an array that has [{{Request}}, {{Response}}] pairs as its elements
-
-
    -
  1. Let requestArray be an empty array.
  2. -
  3. Let responseArray be an empty array.
  4. -
  5. Let resultArray be an empty array.
  6. -
  7. If options.{{CacheQueryOptions/ignoreMethod}} is false and request.method is not `GET`, return resultArray.
  8. -
  9. Let cachedURL and requestURL be null.
  10. -
  11. If the optional argument targetStorage is omitted, then: -
      -
    1. For each fetching record entry of its request to response map, in key insertion order: -
        -
      1. Set cachedURL to entry.\[[key]]'s associated request's url.
      2. -
      3. Set requestURL to request's associated request's url.
      4. -
      5. If options.ignoreSearch is true, then: -
          -
        1. Set cachedURL's query to the empty string.
        2. -
        3. Set requestURL's query to the empty string.
        4. -
        -
      6. -
      7. If cachedURL equals requestURL with the exclude fragments flag set, then: -
          -
        1. Add a copy of entry.\[[key]] to requestArray.
        2. -
        3. Add a copy of entry.\[[value]] to responseArray.
        4. -
        -
      8. -
      -
    2. -
    -
  12. -
  13. Else: -
      -
    1. For each record in targetStorage: -
        -
      1. Set cachedURL to record[0]'s associated request's url.
      2. -
      3. Set requestURL to request's associated request's url.
      4. -
      5. If options.{{CacheQueryOptions/ignoreSearch}} is true, then: -
          -
        1. Set cachedURL's query to the empty string.
        2. -
        3. Set requestURL's query to the empty string.
        4. -
        -
      6. -
      7. If cachedURL equals requestURL with the exclude fragments flag set, then: -
          -
        1. Add record[0] to requestArray.
        2. -
        3. Add record[1] to responseArray.
        4. -
        -
      8. -
      -
    2. -
    -
  14. -
  15. For each cachedResponse in responseArray with the index index: -
      -
    1. Let cachedRequest be the indexth element in requestArray.
    2. -
    3. If cachedResponse's response's header list contains no header named `Vary`, or options.{{CacheQueryOptions/ignoreVary}} is true, then: -
        -
      1. Add an array [cachedRequest, cachedResponse] to resultArray.
      2. -
      3. Continue to the next iteration of the loop.
      4. -
      -
    4. -
    5. Let varyHeaders be the array containing the elements corresponding to the field-values of the Vary header.
    6. -
    7. Let matchFailed be false.
    8. -
    9. For each f in varyHeaders: -
        -
      1. If f matches "*", or the result of running cachedRequest.{{Request/headers}} object's {{Headers/get(name)}} method with f as the argument does not match the result of running request.{{Request/headers}} object's {{Headers/get(name)}} method with f as the argument, then: -
          -
        1. Set matchFailed to true.
        2. -
        3. Break the loop.
        4. -
        -
      2. -
      -
    10. -
    11. If matchFailed is false, add an array [cachedRequest, cachedResponse] to resultArray.
    12. -
    -
  16. -
  17. Return resultArray.
  18. -
+ : Input + :: |request|, a {{Request}} object + :: |options|, a {{CacheQueryOptions}} object, optional + :: |targetStorage|, an array that has [{{Request}}, {{Response}}] pairs as its elements, optional + : Output + :: |resultArray|, an array that has [{{Request}}, {{Response}}] pairs as its elements + + 1. Let |requestArray| be an empty array. + 1. Let |responseArray| be an empty array. + 1. Let |resultArray| be an empty array. + 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.|method| is not `GET`, return |resultArray|. + 1. Let |cachedURL| and |requestURL| be null. + 1. If the optional argument |targetStorage| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. + 1. If |options|.|ignoreSearch| is true, then: + 1. Set |cachedURL|'s query to the empty string. + 1. Set |requestURL|'s query to the empty string. + + 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Add a copy of |entry|.\[[key]] to |requestArray|. + 1. Add a copy of |entry|.\[[value]] to |responseArray|. + + + + 1. Else: + 1. For each |record| in |targetStorage|: + 1. Set |cachedURL| to |record|[0]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. + 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: + 1. Set |cachedURL|'s query to the empty string. + 1. Set |requestURL|'s query to the empty string. + + 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Add |record|[0] to |requestArray|. + 1. Add |record|[1] to |responseArray|. + + + + 1. For each |cachedResponse| in |responseArray| with the index |index|: + 1. Let |cachedRequest| be the |index|th element in |requestArray|. + 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: + 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. + 1. Continue to the next iteration of the loop. + + 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. Let |matchFailed| be false. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", or the result of running |cachedRequest|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument does not match the result of running |request|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument, then: + 1. Set |matchFailed| to true. + 1. Break the loop. + + + 1. If |matchFailed| is false, add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. + + 1. Return |resultArray|.

Batch Cache Operations

-
-
Input
-
operations, an array of {{CacheBatchOperation}} dictionary objects
-
Output
-
promise, a promise resolves with an array of {{Response}} objects.
-
-
    -
  1. Let p be a promise resolved with no value.
  2. -
  3. Return the result of transforming p with a fulfillment handler that performs the following substeps in parallel: -
      -
    1. Let itemsCopy be a new request to response map that is a copy of its context object's request to response map.
    2. -
    3. Let addedRecords be an empty array.
    4. -
    5. Try running the following substeps atomically: -
        -
      1. Let resultArray be an empty array.
      2. -
      3. For each operation in operations with the index index: -
          -
        1. If operation.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError.
        2. -
        3. If operation.{{CacheBatchOperation/type}} matches "delete" and operation.{{CacheBatchOperation/response}} is not null, throw a TypeError.
        4. -
        5. If the result of running Query Cache algorithm passing operation.{{CacheBatchOperation/request}}, operation.{{CacheBatchOperation/options}}, and addedRecords as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception.
        6. -
        7. Let requestResponseArray be the result of running Query Cache algorithm passing operation.{{CacheBatchOperation/request}} and operation.{{CacheBatchOperation/options}} as the arguments.
        8. -
        9. For each requestResponse in requestResponseArray: -
            -
          1. If operation.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map.
          2. -
          -
        10. -
        11. If operation.{{CacheBatchOperation/type}} matches "put", then: -
            -
          1. If operation.{{CacheBatchOperation/response}} is null, throw a TypeError.
          2. -
          3. Let r be operation.{{CacheBatchOperation/request}}'s associated request.
          4. -
          5. If r's url's scheme is not one of "http" and "https", throw a TypeError.
          6. -
          7. If r's method is not `GET`, throw a TypeError.
          8. -
          9. If operation.{{CacheBatchOperation/options}} is not null, throw a TypeError.
          10. -
          11. Set requestResponseArray to the result of running Query Cache algorithm passing operation.{{CacheBatchOperation/request}}.
          12. -
          13. If requestResponseArray is not an empty array, then: -
              -
            1. Let requestResponse be requestResponseArray[0].
            2. -
            3. Let fetchingRecord be the corresponding fetching record for requestResponse[0] and requestResponse[1] in request to response map.
            4. -
            5. Set fetchingRecord.\[[key]] to operation.{{CacheBatchOperation/request}} and fetchingRecord.\[[value]] to operation.{{CacheBatchOperation/response}}.
            6. -
            -
          14. -
          15. Else: -
              -
            1. Set a newly-created fetching record {\[[key]]: operation.{{CacheBatchOperation/request}}, \[[value]]: operation.{{CacheBatchOperation/response}}} to request to response map.
            2. -
            -

            The cache commit is allowed as long as the response's headers are available.

            -
          16. -
          17. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception.
          18. -
          19. Add an array [operation.request, operation.response] to addedRecords.
          20. -
          -
        12. -
        13. Add operation.response to resultArray.
        14. -
        -
      4. -
      5. Return resultArray.
      6. -
      -
    6. -
    7. And then, if an exception was thrown, then: -
        -
      1. Set the context object's request to response map to itemsCopy.
      2. -
      3. Throw the exception
      4. -
      -
    8. -
    -
  4. -
+ : Input + :: |operations|, an array of {{CacheBatchOperation}} dictionary objects + : Output + :: |promise|, a promise resolves with an array of {{Response}} objects. + + 1. Let |p| be a promise resolved with no value. + 1. Return the result of transforming |p| with a fulfillment handler that performs the following substeps in parallel: + 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. + 1. Let |addedRecords| be an empty array. + 1. Try running the following substeps atomically: + 1. Let |resultArray| be an empty array. + 1. For each |operation| in |operations| with the index |index|: + 1. If |operation|.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete" and |operation|.{{CacheBatchOperation/response}} is not null, throw a TypeError. + 1. If the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}, |operation|.{{CacheBatchOperation/options}}, and |addedRecords| as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception. + 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}} and |operation|.{{CacheBatchOperation/options}} as the arguments. + 1. For each |requestResponse| in |requestResponseArray|: + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. + + 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: + 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. + 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. + 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. + 1. If |r|'s method is not `GET`, throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. + 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. + 1. If |requestResponseArray| is not an empty array, then: + 1. Let |requestResponse| be |requestResponseArray|[0]. + 1. Let |fetchingRecord| be the corresponding fetching record for |requestResponse|[0] and |requestResponse|[1] in request to response map. + 1. Set |fetchingRecord|.\[[key]] to |operation|.{{CacheBatchOperation/request}} and |fetchingRecord|.\[[value]] to |operation|.{{CacheBatchOperation/response}}. + + 1. Else: + 1. Set a newly-created fetching record {\[[key]]: |operation|.{{CacheBatchOperation/request}}, \[[value]]: |operation|.{{CacheBatchOperation/response}}} to request to response map. + Note: The cache commit is allowed as long as the response's headers are available. + + 1. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception. + 1. Add an array [|operation|.|request|, |operation|.|response|] to |addedRecords|. + + 1. Add |operation|.|response| to |resultArray|. + + 1. Return |resultArray|. + + 1. And then, if an exception was thrown, then: + 1. Set the context object's request to response map to |itemsCopy|. + 1. Throw the exception +
@@ -3843,27 +3279,24 @@ Markup Shorthands: css no, markdown yes

Service Worker Script Request

-

An HTTP request to fetch a service worker's script resource will include the following header:

+ An HTTP request to fetch a service worker's script resource will include the following header: -
-
`Service-Worker`
-
Indicates this request is a service worker's script resource request. -

This header helps administrators log the requests and detect threats.

-
-
+ + : `Service-Worker` + :: Indicates this request is a service worker's script resource request. + Note: This header helps administrators log the requests and detect threats. +

Service Worker Script Response

-

An HTTP response to a service worker's script resource request can include the following header:

+ An HTTP response to a service worker's script resource request can include the following header: -
-
`Service-Worker-Allowed`
-
Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. -

The value is a URL. If a relative URL is given, it is parsed against the script's URL.

-
-
+ + : `Service-Worker-Allowed` + :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. + Note: The value is a URL. If a relative URL is given, it is parsed against the script's URL.
Default scope: @@ -3917,28 +3350,28 @@ navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(functio

Syntax

-

ABNF for the values of the headers used by the service worker's script resource requests and responses:

+ ABNF for the values of the headers used by the service worker's script resource requests and responses:
     Service-Worker = %x73.63.72.69.70.74 ; "script", case-sensitive
     
-

The validation of the Service-Worker-Allowed header's values is done by URL parsing algorithm (in Update algorithm) instead of using ABNF.

+ Note: The validation of the Service-Worker-Allowed header's values is done by URL parsing algorithm (in Update algorithm) instead of using ABNF.

Acknowledgements

-

Deep thanks go to Andrew Betts for organizing and hosting a small workshop of like-minded individuals including: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. From the clarity of the day's discussions and the use-cases outlined there, much has become possible. Further thanks to Andrew for raising consciousness about the offline problem. His organization of EdgeConf and inclusion of Offline as a persistent topic there has created many opportunities and connections that have enabled this work to progress.

+ Deep thanks go to Andrew Betts for organizing and hosting a small workshop of like-minded individuals including: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. From the clarity of the day's discussions and the use-cases outlined there, much has become possible. Further thanks to Andrew for raising consciousness about the offline problem. His organization of EdgeConf and inclusion of Offline as a persistent topic there has created many opportunities and connections that have enabled this work to progress. -

Anne van Kesteren has generously lent his encyclopedic knowledge of Web Platform arcana and standards development experience throughout the development of the service worker. This specification would be incomplete without his previous work in describing the real-world behavior of URLs, HTTP Fetch, Promises, and DOM. Similarly, this specification would not be possible without Ian Hickson's rigorous Web Worker spec. Much thanks to him.

+ Anne van Kesteren has generously lent his encyclopedic knowledge of Web Platform arcana and standards development experience throughout the development of the service worker. This specification would be incomplete without his previous work in describing the real-world behavior of URLs, HTTP Fetch, Promises, and DOM. Similarly, this specification would not be possible without Ian Hickson's rigorous Web Worker spec. Much thanks to him. -

In no particular order, deep gratitude for design guidance and discussion goes to: Jungkee Song, Alec Flett, David Barrett-Kahn, Aaron Boodman, Michael Nordman, Tom Ashworth, Kinuko Yasuda, Darin Fisher, Jonas Sicking, Jesús Leganés Combarro, Mark Christian, Dave Hermann, Yehuda Katz, François Remy, Ilya Grigorik, Will Chan, Domenic Denicola, Nikhil Marathe, Yves Lafon, Adam Barth, Greg Simon, Devdatta Akhawe, Dominic Cooney, Jeffrey Yasskin, Joshua Bell, Boris Zbarsky, Matt Falkenhagen, Tobie Langel, Gavin Peters, Ben Kelly, Hiroki Nakagawa, Jake Archibald, Josh Soref, Jinho Bang and Yutaka Hirano.

+ In no particular order, deep gratitude for design guidance and discussion goes to: Jungkee Song, Alec Flett, David Barrett-Kahn, Aaron Boodman, Michael Nordman, Tom Ashworth, Kinuko Yasuda, Darin Fisher, Jonas Sicking, Jesús Leganés Combarro, Mark Christian, Dave Hermann, Yehuda Katz, François Remy, Ilya Grigorik, Will Chan, Domenic Denicola, Nikhil Marathe, Yves Lafon, Adam Barth, Greg Simon, Devdatta Akhawe, Dominic Cooney, Jeffrey Yasskin, Joshua Bell, Boris Zbarsky, Matt Falkenhagen, Tobie Langel, Gavin Peters, Ben Kelly, Hiroki Nakagawa, Jake Archibald, Josh Soref, Jinho Bang and Yutaka Hirano. -

Jason Weber, Chris Wilson, Paul Kinlan, Ehsan Akhgari, and Daniel Austin have provided valuable, well-timed feedback on requirements and the standardization process.

+ Jason Weber, Chris Wilson, Paul Kinlan, Ehsan Akhgari, and Daniel Austin have provided valuable, well-timed feedback on requirements and the standardization process. -

The authors would also like to thank Dimitri Glazkov for his scripts and formatting tools which have been essential in the production of this specification. The authors are also grateful for his considerable guidance.

+ The authors would also like to thank Dimitri Glazkov for his scripts and formatting tools which have been essential in the production of this specification. The authors are also grateful for his considerable guidance. -

Thanks also to Vivian Cromwell, Greg Simon, Alex Komoroske, Wonsuk Lee, and Seojin Kim for their considerable professional support.

+ Thanks also to Vivian Cromwell, Greg Simon, Alex Komoroske, Wonsuk Lee, and Seojin Kim for their considerable professional support.
\ No newline at end of file From 759b124c6d0111eb4671d12b32e2213532aa051e Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 23 Nov 2016 13:24:17 +0000 Subject: [PATCH 03/17] Fixing formatting --- docs/index.bs | 1049 +++++++++++++++++++++++-------------------------- 1 file changed, 496 insertions(+), 553 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 94beff45..214df60c 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -923,8 +923,8 @@ Markup Shorthands: css no, markdown yes 1. Wait for |task| to have executed (including its asynchronous steps). 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: - 1. Resolve |promise| with null. - 1. Abort these steps. + 1. Resolve |promise| with null. + 1. Abort these steps. 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. Resolve |promise| with |windowClient|. 1. Return |promise|. @@ -983,9 +983,9 @@ Markup Shorthands: css no, markdown yes 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. 1. Else, set |browsingContext| to |client|'s global object's browsing context. 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: - 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. - 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. 1. Wait for |task| to have executed. 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. Resolve |promise| with |windowClient| and abort these steps. @@ -1036,12 +1036,12 @@ Markup Shorthands: css no, markdown yes 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. Add |windowClient| to |matchedClients|. 1. Else if |options|.{{ClientQueryOptions/type}} is "worker" or "all" and |client| is a dedicated worker client, or |options|.{{ClientQueryOptions/type}} is "sharedworker" or "all" and |client| is a shared worker client, then: - 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. - 1. Add |clientObject| to |matchedClients|. + 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. + 1. Add |clientObject| to |matchedClients|. 1. Sort |matchedClients| such that: - * {{WindowClient}} objects are always placed before {{Client}} objects whose associated service worker clients are worker clients. - * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their service worker clients' creation order. - * {{Client}} objects whose associated service worker clients are worker clients are placed next sorted in their service worker clients' creation order. + * {{WindowClient}} objects are always placed before {{Client}} objects whose associated service worker clients are worker clients. + * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their service worker clients' creation order. + * {{Client}} objects whose associated service worker clients are worker clients are placed next sorted in their service worker clients' creation order. 1. Resolve |promise| with |matchedClients|. 1. Return |promise|.
@@ -2212,8 +2212,8 @@ Markup Shorthands: css no, markdown yes 1. Set |job|'s job type to |jobType|. 1. Set |job|'s scope url to |scopeURL|. 1. Set |job|'s script url to |scriptURL|. - 1. Set |job|'s promise to |promise|. - 1. Set |job|'s client to |client|. + 1. Set |job|'s promise to |promise|. + 1. Set |job|'s client to |client|. 1. If |client| is not null, set |job|'s referrer to |client|'s creation URL. 1. Return |job|.
@@ -2227,12 +2227,11 @@ Markup Shorthands: css no, markdown yes :: none 1. If the job queue is empty, then: - 1. Push |job| to the job queue and invoke Run Job. + 1. Push |job| to the job queue and invoke Run Job. 1. Else: - 1. Let |lastJob| be the element at the back of the job queue. - 1. If |job| is equivalent to |lastJob| and |lastJob|'s promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. - 1. Else, push |job| to the job queue. - + 1. Let |lastJob| be the element at the back of the job queue. + 1. If |job| is equivalent to |lastJob| and |lastJob|'s promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. + 1. Else, push |job| to the job queue.
@@ -2245,13 +2244,13 @@ Markup Shorthands: css no, markdown yes 1. Assert: the job queue is not empty. 1. Queue a task to run these steps: - 1. Let |job| be the element in the front of the job queue. - 1. If |job|'s job type is *register*, run Register with |job| in parallel. - 1. Else if |job|'s job type is *update*, run Update with |job| in parallel. - Note: For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event. + 1. Let |job| be the element in the front of the job queue. + 1. If |job|'s job type is *register*, run Register with |job| in parallel. + 1. Else if |job|'s job type is *update*, run Update with |job| in parallel. + + Note: For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event. - 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel. - + 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel.
@@ -2264,7 +2263,7 @@ Markup Shorthands: css no, markdown yes 1. Assert: the top element in the job queue is |job|. 1. Pop the top element from the job queue. - 1. If the job queue is not empty, invoke Run Job with the top element of the job queue. + 1. If the job queue is not empty, invoke Run Job with the top element of the job queue.
@@ -2276,10 +2275,9 @@ Markup Shorthands: css no, markdown yes : Output :: none - 1. If |job|'s client is not null, queue a task to resolve |job|'s promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. - 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. - + 1. If |job|'s client is not null, queue a task to resolve |job|'s promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. For each |equivalentJob| in |job|'s list of equivalent jobs: + 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
@@ -2291,10 +2289,9 @@ Markup Shorthands: css no, markdown yes : Output :: none - 1. If |job|'s client is not null, queue a task to reject |job|'s promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. - 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. - + 1. If |job|'s client is not null, queue a task to reject |job|'s promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. For each |equivalentJob| in |job|'s list of equivalent jobs: + 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
@@ -2314,6 +2311,7 @@ Markup Shorthands: css no, markdown yes 1. If |scriptURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. 1. If any of the strings in |scriptURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. 1. If |scopeURL| is null, set |scopeURL| to the result of parsing the string "./" with |scriptURL|. + Note: The scope url for the registration is set to the location of the service worker script by default. 1. If |scopeURL| is failure, reject |promise| with a TypeError and abort these steps. @@ -2334,30 +2332,24 @@ Markup Shorthands: css no, markdown yes :: |promise|, a promise 1. If the result of running Is origin potentially trustworthy with the origin of |job|'s script url as the argument is Not Trusted, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Invoke Finish Job with |job| and abort these steps. - + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. 1. If the origin of |job|'s script url is not |job|'s referrer's origin, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Invoke Finish Job with |job| and abort these steps. - + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. 1. If the origin of |job|'s scope url is not |job|'s referrer's origin, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 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 scope url as the argument. + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 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 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 and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: - 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. - 1. Invoke Finish Job with |job| and abort these steps. - - + 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 and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Invoke Finish Job with |job| and abort these steps. 1. Else: - 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. - - 1. Invoke Update algorithm passing |job| as the argument. + 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. + 1. Invoke Update algorithm passing |job| as the argument.
@@ -2368,95 +2360,90 @@ Markup Shorthands: css no, markdown yes : Output :: none - 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s scope url as the argument. - 1. If |registration| is null or |registration|'s uninstalling flag is set, then: - 1. Invoke Reject Job Promise with |job| and a 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. - 1. If |job|'s job type is *update*, and |newestWorker|'s script url does not equal |job|'s script url with the *exclude fragments flag* set, then: - 1. Invoke Reject Job Promise with |job| and a TypeError. - 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 scope url as the argument. + 1. If |registration| is null or |registration|'s uninstalling flag is set, then: + 1. Invoke Reject Job Promise with |job| and a 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. + 1. If |job|'s job type is *update*, and |newestWorker|'s script url does not equal |job|'s script url with the *exclude fragments flag* set, then: + 1. Invoke Reject Job Promise with |job| and a TypeError. + 1. Invoke Finish Job with |job| and abort these steps. 1. Let |httpsState| be "none". 1. Let |referrerPolicy| be the empty string. 1. Switching on |job|'s worker type, run these substeps with the following options: - : *"classic"* - :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". + :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". : *"module"* - :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. + :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. To perform the fetch given |request|, run the following steps if the is top-level flag is set: - 1. Append `Service-Worker`/`script` to |request|'s header list. - Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. - - 1. Set |request|'s skip service worker flag and |request|'s redirect mode to "error". - 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: - 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". - Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. - - 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. - 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Asynchronously complete these steps with a network error. - - 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. - Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. - - 1. Set |httpsState| to |response|'s HTTPS state. - 1. Set |referrerPolicy| to the result of parsing the `Referrer-Policy` header of |response|. - 1. If |serviceWorkerAllowed| is failure, then: - 1. Asynchronously complete these steps with a network error. - - 1. Let |scopeURL| be |registration|'s scope url. - 1. Let |maxScopeString| be null. - 1. If |serviceWorkerAllowed| is null, then: - 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". + + 1. Append `Service-Worker`/`script` to |request|'s header list. + + Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. - 1. Else: - 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. - 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s path (including empty strings), separated from each other by "/". + 1. Set |request|'s skip service worker flag and |request|'s redirect mode to "error". + 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". + + Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. - 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s path (including empty strings), separated from each other by "/". - 1. If |scopeString| starts with |maxScopeString|, do nothing. - 1. Else: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Asynchronously complete these steps with a network error. + 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. + 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. + + Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. - 1. If |response|'s cache state is not "local", set |registration|'s last update check time to the current time. -

The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state. + 1. Set |httpsState| to |response|'s HTTPS state. + 1. Set |referrerPolicy| to the result of parsing the `Referrer-Policy` header of |response|. + 1. If |serviceWorkerAllowed| is failure, then: + 1. Asynchronously complete these steps with a network error. + 1. Let |scopeURL| be |registration|'s scope url. + 1. Let |maxScopeString| be null. + 1. If |serviceWorkerAllowed| is null, then: + 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". + 1. Else: + 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. + 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s path (including empty strings), separated from each other by "/". + 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s path (including empty strings), separated from each other by "/". + 1. If |scopeString| starts with |maxScopeString|, do nothing. + 1. Else: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + 1. If |response|'s cache state is not "local", set |registration|'s last update check time to the current time. + + Issue: The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state. - 1. Return true. + 1. Return true. + If the algorithm asynchronously completes with null, then: - 1. - Invoke Reject Job Promise with |job| and a TypeError. - Note: This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception. + 1. Invoke Reject Job Promise with |job| and a TypeError. + + Note: This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception. - 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 |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. - 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: - 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. - 1. Invoke Finish Job with |job| and abort these steps. - + 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Invoke Finish Job with |job| and abort these steps. 1. Else: - 1. Let |worker| be a new service worker. - 1. Generate a unique opaque string and set |worker|'s id to the value. - 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. - 1. Set |worker|'s script resource's HTTPS state to |httpsState|. - 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. - 1. Invoke Run Service Worker algorithm with |worker| as the argument. - 1. If an uncaught runtime script error occurs during the above step, then: - 1. Invoke Reject Job Promise with |job| and a TypeError. - 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. Invoke Install algorithm with |job|, |worker|, and |registration| as its arguments. + 1. Let |worker| be a new service worker. + 1. Generate a unique opaque string and set |worker|'s id to the value. + 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. + 1. Set |worker|'s script resource's HTTPS state to |httpsState|. + 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. + 1. Invoke Run Service Worker algorithm with |worker| as the argument. + 1. If an uncaught runtime script error occurs during the above step, then: + 1. Invoke Reject Job Promise with |job| and a TypeError. + 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. Invoke Install algorithm with |job|, |worker|, and |registration| as its arguments.

@@ -2464,7 +2451,6 @@ Markup Shorthands: css no, markdown yes The user agent *may* call this as often as it likes to check for updates. - : Input :: |registration|, a service worker registration :: *force bypass cache flag*, an optional flag unset by default @@ -2472,12 +2458,12 @@ Markup Shorthands: css no, markdown yes : Output :: None - 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. + 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. 1. If |newestWorker| is null, abort these steps. - 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, null, and null. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, null, and null. 1. Set |job|'s worker type to |newestWorker|'s type. - 1. Set |job|'s force bypass cache flag if its *force bypass cache flag* is set. - 1. Invoke Schedule Job with |job|. + 1. Set |job|'s force bypass cache flag if its *force bypass cache flag* is set. + 1. Invoke Schedule Job with |job|.
@@ -2491,51 +2477,48 @@ Markup Shorthands: css no, markdown yes :: none 1. Let |installFailed| be false. - 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. + 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. 1. Let |redundantWorker| be null. - 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. Assert: |job|'s promise is not null. - 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 scope url and all the service workers whose containing service worker registration is |registration|. - 1. Let |installingWorker| be |registration|'s installing worker. - 1. Invoke Run Service Worker algorithm with |installingWorker| as the 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. Assert: |job|'s promise is not null. + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 scope url and all the service workers whose containing service worker registration is |registration|. + 1. Let |installingWorker| be |registration|'s installing worker. + 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type install, which does not bubble and is not cancelable. - 1. Dispatch |e| at |installingWorker|'s environment settings object's global object |globalObject|. - 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: - 1. Wait until |e|'s extensions allowed flag is unset. - 1. If the result of waiting for all of |e|'s extend lifetime promises rejected, set |installFailed| to true. - + 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type install, which does not bubble and is not cancelable. + 1. Dispatch |e| at |installingWorker|'s environment settings object's global object |globalObject|. + 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: + 1. Wait until |e|'s extensions allowed flag is unset. + 1. If 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 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. Set |redundantWorker| to |registration|'s installing worker. - 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 |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. - 1. Invoke Finish Job with |job| and abort these steps. - - 1. Set |registration|'s installing worker's imported scripts updated flag. - 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. If |registration|'s waiting worker's skip waiting flag is set, then: - 1. Run Activate algorithm passing |registration| as the argument. - 1. Invoke Finish Job with |job| and abort these steps. - - 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 |waitingWorker| is not null and |waitingWorker|'s skip waiting flag is not set, invoke Activate algorithm with |registration| as its argument. + 1. Set |redundantWorker| to |registration|'s installing worker. + 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 |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. + 1. Set |registration|'s installing worker's imported scripts updated flag. + 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. If |registration|'s waiting worker's skip waiting flag is set, then: + 1. Run Activate algorithm passing |registration| as the argument. + 1. Invoke Finish Job with |job| and abort these steps. + 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 |waitingWorker| is not null and |waitingWorker|'s skip waiting flag is not set, invoke Activate algorithm with |registration| as its argument.
@@ -2546,39 +2529,37 @@ Markup Shorthands: css no, markdown yes : Output :: None - 1. If |registration|'s waiting worker is null, abort these steps. + 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. 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. 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. 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. + 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. - 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: - 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 global object from its application cache, if it has one. + 1. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. + 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: + 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 global object from its application cache, if it has one. + Note: Resources will now use the service worker registration instead of the existing application cache. - 1. For each service worker client |client| who is using |registration|: - 1. Set |client|'s active worker to |registration|'s active worker. - 1. Invoke Notify Controller Change algorithm with |client| as the argument. - - 1. Let |activeWorker| be |registration|'s active worker. - 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 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: - 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type activate, which does not bubble and is not cancelable. - 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. - 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. - - 1. Wait for |task| to have executed or been discarded, or the script to have been aborted by the termination of |activeWorker|. + 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type activate, which does not bubble and is not cancelable. + 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. + 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. Run the Update Worker State algorithm passing |registration|'s active worker and *activated* as the arguments.
@@ -2593,50 +2574,46 @@ Markup Shorthands: css no, markdown yes 1. Assert: |script| is not null. 1. If |serviceWorker| is already running, abort these steps. 1. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context. - 1. Call the JavaScript InitializeHostDefinedRealm() abstract operation with the following customizations: -
    - 1. For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. - 1. Let |realmExecutionContext| be the created JavaScript execution context. -
- + 1. Call the JavaScript InitializeHostDefinedRealm() abstract operation with the following customizations: + * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. + * Let |realmExecutionContext| be the created JavaScript execution context. 1. Let |workerEventLoop| be a newly created event loop. 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: - : The realm execution context + : The realm execution context :: Return |realmExecutionContext|. - : The global object + : The global object :: Return |workerGlobalScope|. - : The responsible event loop + : The responsible event loop :: Return |workerEventLoop|. - : The referrer policy + : The referrer policy :: Return |workerGlobalScope|'s referrer policy. - : The API URL character encoding + : The API URL character encoding :: Return UTF-8. - : The API base URL - :: Return |serviceWorker|'s script url. - : The origin + : The API base URL + :: Return |serviceWorker|'s script url. + : The origin :: Return its registering service worker client's origin. - : The creation URL + : The creation URL :: Return |workerGlobalScope|'s url. - : The HTTPS state + : The HTTPS state :: Return |workerGlobalScope|'s HTTPS state. - - 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. - 1. Set |workerGlobalScope|'s HTTPS state to |serviceWorker|'s script resource's HTTPS state. - 1. Set |workerGlobalScope|'s referrer policy to |serviceWorker|'s script resource's referrer policy. - 1. Set |workerGlobalScope|'s type to |serviceWorker|'s type. + 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. + 1. Set |workerGlobalScope|'s HTTPS state to |serviceWorker|'s script resource's HTTPS state. + 1. Set |workerGlobalScope|'s referrer policy to |serviceWorker|'s script resource's referrer policy. + 1. Set |workerGlobalScope|'s type to |serviceWorker|'s type. 1. Create a new {{WorkerLocation}} object and associate it with |workerGlobalScope|. - 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. + 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. 1. If |script| is a classic script, then run the classic script |script|. Otherwise, it is a module script; run the module script |script|. Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. - 1. If |script|'s has ever been evaluated flag is unset, then: - 1. Set |workerGlobalScope|'s associated service worker's set of event types to handle to the set of event types created from |settingsObject|'s global object's associated list of event listeners' event types. - Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. + 1. If |script|'s has ever been evaluated flag is unset, then: + 1. Set |workerGlobalScope|'s associated service worker's set of event types to handle to the set of event types created from |settingsObject|'s global object's associated list of event listeners' event types. + + Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. - 1. Set |script|'s has ever been evaluated flag. - + 1. Set |script|'s has ever been evaluated flag. 1. Run the responsible event loop specified by |settingsObject| until it is destroyed. 1. Empty |workerGlobalScope|'s list of active timers.
@@ -2652,7 +2629,8 @@ Markup Shorthands: css no, markdown yes 1. If |serviceWorker| is not running, abort these steps. 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s environment settings object's global object. 1. Set |serviceWorkerGlobalScope|'s closing flag to true. - 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's task queues, queue them to |serviceWorker|'s containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's task queues without processing them. + 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's task queues, queue them to |serviceWorker|'s containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's task queues without processing them. + Note: This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded. 1. Abort the script currently running in |serviceWorker|. @@ -2661,15 +2639,14 @@ Markup Shorthands: css no, markdown yes

Handle Fetch

- The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context. + The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context. - : Input :: |request|, a request : Output :: |response|, a response -
    +
    1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. 1. Let |eventCanceled| be false. @@ -2682,68 +2659,65 @@ Markup Shorthands: css no, markdown yes 1. Let |reservedClient| be |request|'s reserved client. 1. Assert: |request|'s destination is not "serviceworker". 1. If |request| is a potential-navigation-or-subresource request, then: - 1. Return null. - + 1. Return null. 1. Else if |request| is a non-subresource request, then: Note: If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration. - 1. If |reservedClient| is not null and is an environment settings object, then: - 1. If |reservedClient| is not a secure context, return null. - - 1. Else: - 1. If |request|'s url is not a potentially trustworthy URL, return null. - - 1. If |request| is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null. - 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s url as the argument. - 1. If |registration| is null or |registration|'s active worker is null, return null. - 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. - Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. + 1. If |reservedClient| is not null and is an environment settings object, then: + 1. If |reservedClient| is not a secure context, return null. + 1. Else: + 1. If |request|'s url is not a potentially trustworthy URL, return null. + 1. If |request| is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null. + 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s url as the argument. + 1. If |registration| is null or |registration|'s active worker is null, return null. + 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. + + Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. 1. Else if |request| is a subresource request, then: - 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. - 1. Else, return null. - - 1. Let |activeWorker| be |registration|'s active worker. - 1. If |activeWorker|'s set of event types to handle does not contain fetch, then: - 1. Return null and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - 1. Abort these steps. + 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. + 1. Else, return null. + 1. Let |activeWorker| be |registration|'s active worker. + 1. If |activeWorker|'s set of event types to handle does not contain fetch, then: + 1. Return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + Note: To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. - 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. - 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. + 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. - 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. - 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. - 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. - 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s target client id, and to the empty string otherwise. - 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s 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 environment settings object's global object. - 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. - 1. If |e|'s wait to respond flag is set, then: - 1. Wait until |e|'s wait to respond flag is unset. - 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. - 1. Else, set |response| to |e|'s potential response. - - 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. - The |task| *ust* use |activeWorker|'s event loop and the handle fetch task source. + 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. + 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. + 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. + 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. + 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s target client id, and to the empty string otherwise. + 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s 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 environment settings object's global object. + 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. + 1. If |e|'s wait to respond flag is set, then: + 1. Wait until |e|'s wait to respond flag is unset. + 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. + 1. Else, set |response| to |e|'s potential response. + 1. If |e|'s canceled flag is set, set |eventCanceled| to true. + + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + + The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. 1. Wait for |task| to have executed or been discarded. 1. If |respondWithEntered| is false, then: - 1. If |eventCanceled| is true, return a network error and continue running these steps in parallel. - 1. Else, return null and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - 1. Abort these steps. - + 1. If |eventCanceled| is true, return a network error and continue running these steps in parallel. + 1. Else, return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. 1. If |handleFetchFailed| is true, then: - 1. Return a network error and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - + 1. Return a network error and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. 1. Else: - 1. Return |response| and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - + 1. Return |response| and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. +
@@ -2751,167 +2725,160 @@ Markup Shorthands: css no, markdown yes The [[#on-foreign-fetch-request-algorithm]] algorithm is the entry point for the fetch handling handed to the service worker context to handle foreign fetch requests. - : Input :: |request|, a request : Output :: |response|, a response -
    +
    1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. 1. Let |eventCanceled| be false. 1. If |request| is not a subresource request, return null and abort these steps. + Note: Foreign fetch only allows intercepting of subresource requests. Navigation requests can be intercepted by the regular fetch event anyway, so there is no benefit to supporting those requests here as well. 1. If |request|'s client is not a secure context, return null and abort these steps. 1. Let |activeWorker| be the result of running the [[#foreign-fetch-scope-match-algorithm]] algorithm passing |request|'s url as the argument. 1. If |activeWorker| is null, return null. - 1. If |activeWorker|'s state is *activating*, then: - 1. Wait for |activeWorker|'s state to become *activated*. - + 1. If |activeWorker|'s state is *activating*, then: + 1. Wait for |activeWorker|'s state to become *activated*. 1. If |activeWorker|'s origin is the same as |request|'s origin, return null. 1. Let |originMatches| be false. 1. If |activeWorker|'s list of foreign fetch origins is empty, set |originMatches| to true. 1. For each |origin| in |activeWorker|'s list of foreign fetch origins: - 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. + 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. 1. If |originMatches| is false, return null. 1. Let |r| be a new {{Request}} object associated with |request|. 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. - 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. - 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. - 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. - 1. If |e|'s 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 potential response. - 1. If |internalResponse| is a filtered response, set |internalResponse| to |internalResponse|'s internal response. - 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. - 1. Else if |e|'s origin is null: - 1. If |e|'s list of exposed headers is not empty, set |handleFetchFailed| to true. - 1. Else if |e|'s potential response is a opaque-redirect filtered response, set |response| to |e|'s potential response. - 1. Else set |response| to an opaque filtered response of |internalResponse|. - - 1. Else if |e|'s origin is not equal to the Unicode serialization of |request|'s origin, set |handleFetchFailed| to true. - 1. Else if |e|'s potential response is an opaque filtered response or is an opaque-redirect filtered response, set |response| to |e|'s potential response. - 1. Else if |request|'s response tainting is "opaque", set |response| to an opaque filtered response of |internalResponse|. - 1. Else: - 1. Let |headers| be |e|'s list of exposed headers. - 1. If |response| is a CORS filtered response, remove from |internalResponse|'s CORS-exposed header-name list all values not in |headers|. - 1. Else set |internalResponse|'s CORS-exposed header-name list to |headers|. - 1. Set |response| to a CORS filtered response of |internalResponse|. - - 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. - The |task| *ust* use |activeWorker|'s event loop and the handle fetch task source. + 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. + 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. + 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. + 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. If |e|'s 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 potential response. + 1. If |internalResponse| is a filtered response, set |internalResponse| to |internalResponse|'s internal response. + 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. + 1. Else if |e|'s origin is null: + 1. If |e|'s list of exposed headers is not empty, set |handleFetchFailed| to true. + 1. Else if |e|'s potential response is a opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else set |response| to an opaque filtered response of |internalResponse|. + 1. Else if |e|'s origin is not equal to the Unicode serialization of |request|'s origin, set |handleFetchFailed| to true. + 1. Else if |e|'s potential response is an opaque filtered response or is an opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else if |request|'s response tainting is "opaque", set |response| to an opaque filtered response of |internalResponse|. + 1. Else: + 1. Let |headers| be |e|'s list of exposed headers. + 1. If |response| is a CORS filtered response, remove from |internalResponse|'s CORS-exposed header-name list all values not in |headers|. + 1. Else set |internalResponse|'s CORS-exposed header-name list to |headers|. + 1. Set |response| to a CORS filtered response of |internalResponse|. + 1. If |e|'s canceled flag is set, set |eventCanceled| to true. + + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + + The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. 1. Wait for |task| to have executed or been discarded. 1. If |respondWithEntered| is false, then: - 1. If |eventCanceled| is true, then: - 1. Return a network error. - - 1. Else: - 1. Return null. - - - 1. If |handleFetchFailed| is true, then: + 1. If |eventCanceled| is true, then: 1. Return a network error. - + 1. Else: + 1. Return null. + 1. If |handleFetchFailed| is true, then: + 1. Return a network error. 1. Else: - 1. Return |response|. - + 1. Return |response|. +

Handle Functional Event

- : Input + : Input :: |registration|, a service worker registration :: |callbackSteps|, an algorithm - : Output + : Output :: None - 1. Assert: a Record with the \[[value]] equals to |registration| is contained in scope to registration map. - 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 contain the event type for this functional event, then: - 1. Return and continue running these steps in parallel. - 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - 1. Abort these steps. + 1. Assert: a Record with the \[[value]] equals to |registration| is contained in scope to registration map. + 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 contain the event type for this functional event, then: + 1. Return and continue running these steps in parallel. + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + Note: To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. - 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. - 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. + 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to invoke |callbackSteps| with |activeWorker|'s environment settings object's global object as its argument. - The |task| *ust* use |activeWorker|'s event loop and the handle functional event task source. + + The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. 1. Wait for |task| to have executed or been discarded. - 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|.

Handle Service Worker Client Unload

- The user agent *ust* run these steps when a service worker client unloads by unloading, being killed, or terminating. - + The user agent *must* run these steps when a service worker client unloads by unloading, being killed, or terminating. - : Input + : Input :: |client|, a service worker client - : Output + : Output :: None 1. Run the following steps atomically. - 1. Let |registration| be the service worker registration used by |client|. + 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 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 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.

Handle User Agent Shutdown

- : Input + : Input :: None - : Output + : Output :: None - 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: - 1. Let |registration| be |entry|.\[[value]]. - 1. If |registration|'s installing worker |installingWorker| is not null, then: - 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. - 1. Else, set |registration|'s installing worker to null. - - 1. If |registration|'s waiting worker is not null, run the following substep in parallel: - 1. Invoke Activate with |registration|. - + 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: + 1. Let |registration| be |entry|.\[[value]]. + 1. If |registration|'s installing worker |installingWorker| is not null, then: + 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. + 1. Else, set |registration|'s installing worker to null. + 1. If |registration|'s waiting worker is not null, run the following substep in parallel: + 1. Invoke Activate with |registration|.

Unregister

- : Input + : Input :: |job|, a job : Output :: none - 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Invoke Finish Job with |job| and abort these steps. - - 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s scope url as the argument. + 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. + 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s scope url as the argument. 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. Invoke Resolve Job Promise with |job| and true. - 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. + 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. Invoke Resolve Job Promise with |job| and true. + 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. + Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. - 1. Invoke Finish Job with |job|. + 1. Invoke Finish Job with |job|.
@@ -2925,7 +2892,7 @@ Markup Shorthands: css no, markdown yes 1. Run the following steps atomically. 1. Let |scopeString| be serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be a new service worker registration whose scope url is set to |scope|. - 1. Set a newly-created Record {\[[key]]: |scopeString|, \[[value]]: |registration|} to scope to registration map. + 1. Set a newly-created Record {\[[key]]: |scopeString|, \[[value]]: |registration|} to scope to registration map. 1. Return |registration|.
@@ -2939,28 +2906,25 @@ Markup Shorthands: css no, markdown yes 1. Run the following steps atomically. 1. Let |redundantWorker| be null. - 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. Delete a Record {\[[key]], \[[value]]} |entry| from scope to registration map where |registration|'s scope url is the result of parsing |entry|.\[[key]]. + 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. Delete a Record {\[[key]], \[[value]]} |entry| from scope to registration map where |registration|'s scope url is the result of parsing |entry|.\[[key]].
@@ -2975,24 +2939,19 @@ Markup Shorthands: css no, markdown yes 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. 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. 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 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 active worker, or null if |registration|’s active worker is null. + 1. Set |registration|'s 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 active worker, or null if |registration|’s active worker is null. - The task *ust* use |registrationObject|'s relevant settings object's responsible event loop and the DOM manipulation task source. - + The task *must* use |registrationObject|'s relevant settings object's responsible event loop and the DOM manipulation task source.
@@ -3000,41 +2959,43 @@ Markup Shorthands: css no, markdown yes : Input :: |worker|, a service worker - :: |state|, a service worker's state + :: |state|, a service worker's state : Output :: None - 1. Set |worker|'s state to |state|. + 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, event.waitUntil(|f|) 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. + 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, event.waitUntil(|f|) 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" - Note: The service worker in this state is considered a waiting worker. + : *installed* + :: "installed" + + 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, event.waitUntil(|f|) 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*. + : *activating* + :: "activating" + + Note: The service worker in this state is considered an active worker. During this state, event.waitUntil(|f|) 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. + : *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|. + : *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 *ust* use |workerObject|'s relevant settings object's responsible event loop and the DOM manipulation task source. - + The task *must* use |workerObject|'s relevant settings object's responsible event loop and the DOM manipulation task source.
@@ -3047,7 +3008,7 @@ Markup Shorthands: css no, markdown yes 1. Assert: |client| is not null. 1. If |client| is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object |client| is associated with. - The task *ust* use |client|'s responsible event loop and the DOM manipulation task source. + The task *must* use |client|'s responsible event loop and the DOM manipulation task source.
@@ -3061,13 +3022,14 @@ Markup Shorthands: css no, markdown yes 1. Run the following steps atomically. 1. Let |clientURLString| be serialized |clientURL|. 1. Let |matchingScope| be the empty string. - 1. Set |matchingScope| to the longest \[[key]] in scope to registration map which the value of |clientURLString| starts with, if it exists. + 1. Set |matchingScope| to the longest \[[key]] in scope to registration map which the value of |clientURLString| starts with, if it exists. + Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). 1. Let |parsedMatchingScope| be null. 1. If |matchingScope| is not the empty string, set |parsedMatchingScope| to the result of parsing |matchingScope|. - 1. Let |registration| be the result of running Get Registration algorithm passing |parsedMatchingScope| as the argument. - 1. If |registration| is not null and |registration|'s uninstalling flag is set, return null. + 1. Let |registration| be the result of running Get Registration algorithm passing |parsedMatchingScope| as the argument. + 1. If |registration| is not null and |registration|'s uninstalling flag is set, return null. 1. Return |registration|.
@@ -3086,9 +3048,8 @@ Markup Shorthands: css no, markdown yes 1. If |worker| is null, return null. 1. Let |requestURLString| be the serialized |requestURL|. 1. For each URL |scope| in |worker|'s list of foreign fetch scopes: - 1. Let |scopeString| be the serialized |scope|. - 1. If |requestString| starts with |scopeString| return |worker|. - + 1. Let |scopeString| be the serialized |scope|. + 1. If |requestString| starts with |scopeString| return |worker|. 1. Return null. @@ -3104,9 +3065,8 @@ Markup Shorthands: css no, markdown yes 1. Let |scopeString| be the empty string. 1. If |scope| is not null, set |scopeString| to serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be null. - 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: - 1. If |scopeString| matches |entry|.\[[key]], set |registration| to |entry|.\[[value]]. - + 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: + 1. If |scopeString| matches |entry|.\[[key]], set |registration| to |entry|.\[[value]]. 1. Return |registration|. @@ -3120,9 +3080,9 @@ Markup Shorthands: css no, markdown yes 1. Run the following steps atomically. 1. Let |newestWorker| be null. - 1. If |registration|'s installing worker is not null, set |newestWorker| to |registration|'s installing worker. - 1. Else if |registration|'s waiting worker is not null, set |newestWorker| to |registration|'s waiting worker. - 1. Else if |registration|'s active worker is not null, set |newestWorker| to |registration|'s active worker. + 1. If |registration|'s installing worker is not null, set |newestWorker| to |registration|'s installing worker. + 1. Else if |registration|'s waiting worker is not null, set |newestWorker| to |registration|'s waiting worker. + 1. Else if |registration|'s active worker is not null, set |newestWorker| to |registration|'s active worker. 1. Return |newestWorker|. @@ -3153,8 +3113,8 @@ Markup Shorthands: css no, markdown yes 1. Let |windowClient| be a new {{WindowClient}} object. 1. Set |windowClient|'s service worker client to |client|. - 1. Set |windowClient|'s visibility state to |visibilityState|. - 1. Set |windowClient|'s focus state to |focusState|. + 1. Set |windowClient|'s visibility state to |visibilityState|. + 1. Set |windowClient|'s focus state to |focusState|. 1. Set |windowClient|'s ancestor origins array to |ancestorOrigins|. 1. Return |windowClient|. @@ -3175,49 +3135,37 @@ Markup Shorthands: css no, markdown yes 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.|method| is not `GET`, return |resultArray|. 1. Let |cachedURL| and |requestURL| be null. 1. If the optional argument |targetStorage| is omitted, then: - 1. For each fetching record |entry| of its request to response map, in key insertion order: - 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. - 1. If |options|.|ignoreSearch| is true, then: - 1. Set |cachedURL|'s query to the empty string. - 1. Set |requestURL|'s query to the empty string. - - 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: - 1. Add a copy of |entry|.\[[key]] to |requestArray|. - 1. Add a copy of |entry|.\[[value]] to |responseArray|. - - - + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. + 1. If |options|.|ignoreSearch| is true, then: + 1. Set |cachedURL|'s query to the empty string. + 1. Set |requestURL|'s query to the empty string. + 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Add a copy of |entry|.\[[key]] to |requestArray|. + 1. Add a copy of |entry|.\[[value]] to |responseArray|. 1. Else: - 1. For each |record| in |targetStorage|: - 1. Set |cachedURL| to |record|[0]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. - 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: - 1. Set |cachedURL|'s query to the empty string. - 1. Set |requestURL|'s query to the empty string. - - 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: - 1. Add |record|[0] to |requestArray|. - 1. Add |record|[1] to |responseArray|. - - - + 1. For each |record| in |targetStorage|: + 1. Set |cachedURL| to |record|[0]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. + 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: + 1. Set |cachedURL|'s query to the empty string. + 1. Set |requestURL|'s query to the empty string. + 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Add |record|[0] to |requestArray|. + 1. Add |record|[1] to |responseArray|. 1. For each |cachedResponse| in |responseArray| with the index |index|: - 1. Let |cachedRequest| be the |index|th element in |requestArray|. - 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: - 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. - 1. Continue to the next iteration of the loop. - - 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. - 1. Let |matchFailed| be false. - 1. For each |f| in |varyHeaders|: - 1. If |f| matches "*", or the result of running |cachedRequest|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument does not match the result of running |request|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument, then: - 1. Set |matchFailed| to true. - 1. Break the loop. - - - 1. If |matchFailed| is false, add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. - + 1. Let |cachedRequest| be the |index|th element in |requestArray|. + 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: + 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. + 1. Continue to the next iteration of the loop. + 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. Let |matchFailed| be false. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", or the result of running |cachedRequest|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument does not match the result of running |request|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument, then: + 1. Set |matchFailed| to true. + 1. Break the loop. + 1. If |matchFailed| is false, add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. 1. Return |resultArray|. @@ -3231,45 +3179,40 @@ Markup Shorthands: css no, markdown yes 1. Let |p| be a promise resolved with no value. 1. Return the result of transforming |p| with a fulfillment handler that performs the following substeps in parallel: - 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. - 1. Let |addedRecords| be an empty array. - 1. Try running the following substeps atomically: - 1. Let |resultArray| be an empty array. - 1. For each |operation| in |operations| with the index |index|: - 1. If |operation|.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError. - 1. If |operation|.{{CacheBatchOperation/type}} matches "delete" and |operation|.{{CacheBatchOperation/response}} is not null, throw a TypeError. - 1. If the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}, |operation|.{{CacheBatchOperation/options}}, and |addedRecords| as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception. - 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}} and |operation|.{{CacheBatchOperation/options}} as the arguments. - 1. For each |requestResponse| in |requestResponseArray|: - 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. - - 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: - 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. - 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. - 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. - 1. If |r|'s method is not `GET`, throw a TypeError. - 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. - 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. - 1. If |requestResponseArray| is not an empty array, then: - 1. Let |requestResponse| be |requestResponseArray|[0]. - 1. Let |fetchingRecord| be the corresponding fetching record for |requestResponse|[0] and |requestResponse|[1] in request to response map. - 1. Set |fetchingRecord|.\[[key]] to |operation|.{{CacheBatchOperation/request}} and |fetchingRecord|.\[[value]] to |operation|.{{CacheBatchOperation/response}}. - - 1. Else: - 1. Set a newly-created fetching record {\[[key]]: |operation|.{{CacheBatchOperation/request}}, \[[value]]: |operation|.{{CacheBatchOperation/response}}} to request to response map. - Note: The cache commit is allowed as long as the response's headers are available. - - 1. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception. - 1. Add an array [|operation|.|request|, |operation|.|response|] to |addedRecords|. - - 1. Add |operation|.|response| to |resultArray|. - - 1. Return |resultArray|. - - 1. And then, if an exception was thrown, then: - 1. Set the context object's request to response map to |itemsCopy|. - 1. Throw the exception - + 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. + 1. Let |addedRecords| be an empty array. + 1. Try running the following substeps atomically: + 1. Let |resultArray| be an empty array. + 1. For each |operation| in |operations| with the index |index|: + 1. If |operation|.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete" and |operation|.{{CacheBatchOperation/response}} is not null, throw a TypeError. + 1. If the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}, |operation|.{{CacheBatchOperation/options}}, and |addedRecords| as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception. + 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}} and |operation|.{{CacheBatchOperation/options}} as the arguments. + 1. For each |requestResponse| in |requestResponseArray|: + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. + 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: + 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. + 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. + 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. + 1. If |r|'s method is not `GET`, throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. + 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. + 1. If |requestResponseArray| is not an empty array, then: + 1. Let |requestResponse| be |requestResponseArray|[0]. + 1. Let |fetchingRecord| be the corresponding fetching record for |requestResponse|[0] and |requestResponse|[1] in request to response map. + 1. Set |fetchingRecord|.\[[key]] to |operation|.{{CacheBatchOperation/request}} and |fetchingRecord|.\[[value]] to |operation|.{{CacheBatchOperation/response}}. + 1. Else: + 1. Set a newly-created fetching record {\[[key]]: |operation|.{{CacheBatchOperation/request}}, \[[value]]: |operation|.{{CacheBatchOperation/response}}} to request to response map. + + Note: The cache commit is allowed as long as the response's headers are available. + + 1. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception. + 1. Add an array [|operation|.|request|, |operation|.|response|] to |addedRecords|. + 1. Add |operation|.|response| to |resultArray|. + 1. Return |resultArray|. + 1. And then, if an exception was thrown, then: + 1. Set the context object's request to response map to |itemsCopy|. + 1. Throw the exception @@ -3279,70 +3222,69 @@ Markup Shorthands: css no, markdown yes

Service Worker Script Request

- An HTTP request to fetch a service worker's script resource will include the following header: + An HTTP request to fetch a service worker's script resource will include the following header: - : `Service-Worker` - :: Indicates this request is a service worker's script resource request. + :: Indicates this request is a service worker's script resource request. + Note: This header helps administrators log the requests and detect threats. -

Service Worker Script Response

- An HTTP response to a service worker's script resource request can include the following header: + An HTTP response to a service worker's script resource request can include the following header: - : `Service-Worker-Allowed` - :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. + :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. + Note: The value is a URL. If a relative URL is given, it is parsed against the script's URL.
Default scope: -
-// Maximum allowed scope defaults to the path the script sits in
-// "/js" in this example
-navigator.serviceWorker.register("/js/sw.js").then(function() {
-  console.log("Install succeeded with the default scope '/js'.");
-});
+      
+        // Maximum allowed scope defaults to the path the script sits in
+        // "/js" in this example
+        navigator.serviceWorker.register("/js/sw.js").then(() => {
+          console.log("Install succeeded with the default scope '/js'.");
+        });
       
Upper path without Service-Worker-Allowed header: -
-// Set the scope to an upper path of the script location
-// Response has no Service-Worker-Allowed header
-navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).catch(function() {
-  console.error("Install failed due to the path restriction violation.");
-});
+      
+        // Set the scope to an upper path of the script location
+        // Response has no Service-Worker-Allowed header
+        navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).catch(() => {
+          console.error("Install failed due to the path restriction violation.");
+        });
       
Upper path with Service-Worker-Allowed header: -
-// Set the scope to an upper path of the script location
-// Response included "Service-Worker-Allowed : /"
-navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).then(function() {
-  console.log("Install succeeded as the max allowed scope was overriden to '/'.");
-});
+      
+        // Set the scope to an upper path of the script location
+        // Response included "Service-Worker-Allowed : /"
+        navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).then(() => {
+          console.log("Install succeeded as the max allowed scope was overriden to '/'.");
+        });
       
A path restriction voliation even with Service-Worker-Allowed header: -
-// Set the scope to an upper path of the script location
-// Response included "Service-Worker-Allowed : /foo"
-navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(function() {
-  console.error("Install failed as the scope is still out of the overriden maximum allowed scope.");
-});
+      
+        // Set the scope to an upper path of the script location
+        // Response included "Service-Worker-Allowed : /foo"
+        navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(() => {
+          console.error("Install failed as the scope is still out of the overriden maximum allowed scope.");
+        });
       
@@ -3350,10 +3292,10 @@ navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(functio

Syntax

- ABNF for the values of the headers used by the service worker's script resource requests and responses: + ABNF for the values of the headers used by the service worker's script resource requests and responses:
-    Service-Worker = %x73.63.72.69.70.74 ; "script", case-sensitive
+      Service-Worker = %x73.63.72.69.70.74 ; "script", case-sensitive
     
Note: The validation of the Service-Worker-Allowed header's values is done by URL parsing algorithm (in Update algorithm) instead of using ABNF. @@ -3363,6 +3305,7 @@ navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(functio

Acknowledgements

+ Deep thanks go to Andrew Betts for organizing and hosting a small workshop of like-minded individuals including: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. From the clarity of the day's discussions and the use-cases outlined there, much has become possible. Further thanks to Andrew for raising consciousness about the offline problem. His organization of EdgeConf and inclusion of Offline as a persistent topic there has created many opportunities and connections that have enabled this work to progress. Anne van Kesteren has generously lent his encyclopedic knowledge of Web Platform arcana and standards development experience throughout the development of the service worker. This specification would be incomplete without his previous work in describing the real-world behavior of URLs, HTTP Fetch, Promises, and DOM. Similarly, this specification would not be possible without Ian Hickson's rigorous Web Worker spec. Much thanks to him. From 181b7051ef4cbdc0dfe1eff02c0a26ee67f887c1 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 23 Nov 2016 14:53:34 +0000 Subject: [PATCH 04/17] Tidy up & ordered lists --- docs/index.bs | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 214df60c..e9e2842f 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -16,7 +16,7 @@ Abstract: This specification describes a method that enables applications to tak Abstract: Abstract: The core of this system is an event-driven Web Worker, which responds to events dispatched from documents and other sources. A system for managing installation, versions, and upgrades is provided. Abstract: -Abstract: The service worker is a generic entry point for event-driven background processing in the Web Platform that is . +Abstract: The service worker is a generic entry point for event-driven background processing in the Web Platform that is extensible by other specifications. Markup Shorthands: css no, markdown yes @@ -168,9 +168,9 @@ Markup Shorthands: css no, markdown yes : The handle fetch task source :: This task source is used for dispatching fetch events to service workers. : The handle functional event task source - :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. + :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. - Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events. For instance, a user agent may use a different task source for task events from other task sources. + Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events. For instance, a user agent may use a different task source for task events from other task sources.
@@ -482,7 +482,6 @@ Markup Shorthands: css no, markdown yes ready attribute *must* run these steps: - 1. If the context object's ready promise is settled, return the context object's ready promise. 1. Let |client| be the context object's service worker client. 1. Let |registration| be null. @@ -500,7 +499,6 @@ Markup Shorthands: css no, markdown yes 1. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Return context object's ready promise. - Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker.
@@ -548,8 +546,8 @@ Markup Shorthands: css no, markdown yes 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: 1. Let |array| be an empty array. - 1. For each Record {\[[key]], \[[value]]} |entry| of scope to registration map: - 1. If the origin of the result of parsing |entry|.\[[key]] is the same as |client|'s origin, and |entry|.\[[value]]'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |entry|.\[[value]] to the |array|. + 1. For each |key| → |value| of scope to registration map: + 1. If the origin of the result of parsing |key| is the same as |client|'s origin, and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. 1. Resolve |promise| with |array|. 1. Return |promise|.
@@ -1031,7 +1029,9 @@ Markup Shorthands: css no, markdown yes 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. 1. Wait for |task| to have executed. + Note: Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken. + 1. If |isClientEnumerable| is true, then: 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. Add |windowClient| to |matchedClients|. @@ -1122,7 +1122,7 @@ Markup Shorthands: css no, markdown yes Service workers have two lifecycle events, install and activate. Service workers use the {{ExtendableEvent}} interface for activate event and install event. - Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. + Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. Note: To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run Extend Service Worker Lifetime algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event. @@ -1139,7 +1139,7 @@ Markup Shorthands: css no, markdown yes 1. Add |f| to the extend lifetime promises. - Service workers and extensions that define event handlers *may* define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure. + Service workers and extensions that define event handlers *may* define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure. Service workers define the following behaviors for install event and activate event, respectively: @@ -1836,7 +1836,7 @@ Markup Shorthands: css no, markdown yes 1. For each |f| in |varyHeaders|: 1. If |f| matches "*", return a promise rejected with a TypeError. 1. If |response| is disturbed or locked, return a promise rejected with a TypeError. - 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated response and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. + 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated response and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. 1. If |response|'s body is non-null, run these substeps: 1. Let |dummyStream| be an empty ReadableStream object. 1. Set |response|'s body to a new body whose stream is |dummyStream|. @@ -2060,11 +2060,10 @@ Markup Shorthands: css no, markdown yes 1. If |serviceWorker|'s imported scripts updated flag is unset, then: 1. Let |response| be the result of fetching |request|. 1. If |response|'s unsafe response's type is not "error", and |response|'s status is an ok status, then: - 1. If there exists a corresponding Record |record| for |request|'s url in |serviceWorker|'s script resource map, set |record|.\[[value]] to |response|. - 1. Else, set a newly-created Record {\[[key]]: |url|, \[[value]]: |response|} to |serviceWorker|'s script resource map. + 1. Set script resource map[|request|'s url] to |response| 1. Return |response|. 1. Else: - 1. If there exists a corresponding Record |record| for |url| in |serviceWorker|'s script resource map, return |record|.\[[value]]. + 1. If script resource map[|url|] exists, return script resource map[|url|]. 1. Else, return a network error. @@ -2454,7 +2453,9 @@ Markup Shorthands: css no, markdown yes : Input :: |registration|, a service worker registration :: *force bypass cache flag*, an optional flag unset by default + Note: Implementers may use the *force bypass cache flag* to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs. + : Output :: None @@ -2606,6 +2607,7 @@ Markup Shorthands: css no, markdown yes 1. Create a new {{WorkerLocation}} object and associate it with |workerGlobalScope|. 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. 1. If |script| is a classic script, then run the classic script |script|. Otherwise, it is a module script; run the module script |script|. + Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. 1. If |script|'s has ever been evaluated flag is unset, then: @@ -2661,7 +2663,9 @@ Markup Shorthands: css no, markdown yes 1. If |request| is a potential-navigation-or-subresource request, then: 1. Return null. 1. Else if |request| is a non-subresource request, then: + Note: If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration. + 1. If |reservedClient| is not null and is an environment settings object, then: 1. If |reservedClient| is not a secure context, return null. 1. Else: @@ -2802,7 +2806,7 @@ Markup Shorthands: css no, markdown yes : Output :: None - 1. Assert: a Record with the \[[value]] equals to |registration| is contained in scope to registration map. + 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 contain the event type for this functional event, then: @@ -2848,8 +2852,7 @@ Markup Shorthands: css no, markdown yes : Output :: None - 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: - 1. Let |registration| be |entry|.\[[value]]. + 1. For each |scope| → |registration| of scope to registration map: 1. If |registration|'s installing worker |installingWorker| is not null, then: 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. 1. Else, set |registration|'s installing worker to null. @@ -2892,7 +2895,7 @@ Markup Shorthands: css no, markdown yes 1. Run the following steps atomically. 1. Let |scopeString| be serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be a new service worker registration whose scope url is set to |scope|. - 1. Set a newly-created Record {\[[key]]: |scopeString|, \[[value]]: |registration|} to scope to registration map. + 1. Set scope to registration map[|scopeString|] to |registration|. 1. Return |registration|. @@ -2924,7 +2927,8 @@ Markup Shorthands: css no, markdown yes 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. Delete a Record {\[[key]], \[[value]]} |entry| from scope to registration map where |registration|'s scope url is the result of parsing |entry|.\[[key]]. + 1. Let |scopeString| be serialized |registration|'s scope url with the *exclude fragment flag* set. + 1. Remove scope to registration map[scopeString].
@@ -3022,7 +3026,8 @@ Markup Shorthands: css no, markdown yes 1. Run the following steps atomically. 1. Let |clientURLString| be serialized |clientURL|. 1. Let |matchingScope| be the empty string. - 1. Set |matchingScope| to the longest \[[key]] in scope to registration map which the value of |clientURLString| starts with, if it exists. + 1. Let |allScopes| be the result of getting the keys from scope to registration map. + 1. Set |matchingScope| to the longest value in |allScopes| which the value of |clientURLString| starts with, if it exists. Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). @@ -3065,8 +3070,8 @@ Markup Shorthands: css no, markdown yes 1. Let |scopeString| be the empty string. 1. If |scope| is not null, set |scopeString| to serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be null. - 1. For each Record {\[[key]], \[[value]]} |entry| of its scope to registration map: - 1. If |scopeString| matches |entry|.\[[key]], set |registration| to |entry|.\[[value]]. + 1. For each |key| → |value| of scope to registration map: + 1. If |scopeString| matches |key|, set |registration| to |value|. 1. Return |registration|.
From d869ed0a96c434a1de3a6d328da32d6aff6a1ca8 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 23 Nov 2016 15:06:11 +0000 Subject: [PATCH 05/17] Be gone whitespace --- docs/index.bs | 271 +++++++++++++++++++++++++------------------------- 1 file changed, 136 insertions(+), 135 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index e9e2842f..30f3faef 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -36,7 +36,7 @@ Markup Shorthands: css no, markdown yes

Motivations

*This section is non-normative.* - + Web Applications traditionally assume that the network is reachable. This assumption pervades the platform. HTML documents are loaded over HTTP and traditionally fetch all of their sub-resources via subsequent HTTP requests. This places web content at a disadvantage versus other technology stacks. The service worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the service worker, conceptually, between the network and a document renderer, allowing the service worker to provide content for documents, even while offline. @@ -57,46 +57,46 @@ Markup Shorthands: css no, markdown yes

Service Worker

A service worker is a type of web worker. A service worker executes in the registering service worker client's origin. - + A service worker has an associated state, which is one of *parsed*, *installing*, *installed*, *activating*, *activated*, and *redundant*. It is initially *parsed*. A service worker has an associated script url (a URL). - + A service worker has an associated type which is either "classic" or "module". Unless stated otherwise, it is "classic". - + A service worker has an associated containing service worker registration (a service worker registration), which contains itself. - + A service worker has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration. A service worker has an associated global object (a {{ServiceWorkerGlobalScope}} object or null). A service worker is dispatched a set of lifecycle events, install and activate, and functional events including fetch. - + A service worker has an associated script resource (a script), which represents its own script resource. It is initially set to null. - + A script resource has an associated has ever been evaluated flag. It is initially unset. - + A script resource has an associated HTTPS state (an HTTPS state value). It is initially "none". - + A script resource has an associated referrer policy (a referrer policy). It is initially the empty string. - + A service worker has an associated script resource map which is an ordered map where the keys are URLs and the values are responses. - + A service worker has an associated skip waiting flag. Unless stated otherwise it is unset. - + A service worker has an associated imported scripts updated flag. It is initially unset. - + A service worker has an associated set of event types to handle whose element type is an event listener's event type. It is initially set to null. - + 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.

Lifetime

The lifetime of a service worker is tied to the execution lifetime of events and not references held by service worker clients to the {{ServiceWorker}} object. - + A user agent *may* terminate service workers at any time it: * Has no event to handle. @@ -108,26 +108,26 @@ Markup Shorthands: css no, markdown yes

Service Worker Registration

A service worker registration is a tuple of a scope url and a set of service workers, an installing worker, a waiting worker, and an active worker. A user agent *may* enable many service worker registrations at a single origin so long as the scope url of the service worker registration differs. A service worker registration of an identical scope url when one already exists in the user agent causes the existing service worker registration to be replaced. - + A service worker registration has an associated scope url (a URL). - + A service worker registration has an associated registering script url (a URL). - + A service worker registration has an associated installing worker (a service worker or null) whose state is *installing*. It is initially set to null. - + A service worker registration has an associated waiting worker (a service worker or null) whose state is *installed*. It is initially set to null. - + A service worker registration has an associated active worker (a service worker or null) whose state is either *activating* or *activated*. It is initially set to null. - + A service worker registration has an associated last update check time. It is initially set to null. - + 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 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 task queues are not processed by any event loops in and of itself.

Lifetime

- + A user agent *must* persistently keep a list of registered service worker registrations unless otherwise they are explicitly unregistered. A user agent has a scope to registration map that stores the entries of the tuple of service worker registration's scope url and the corresponding service worker registration. The lifetime of service worker registrations is beyond that of the {{ServiceWorkerRegistration}} objects which represent them within the lifetime of their corresponding service worker clients.
@@ -164,12 +164,12 @@ Markup Shorthands: css no, markdown yes

Task Sources

The following additional task sources are used by service workers. - + : The handle fetch task source :: This task source is used for dispatching fetch events to service workers. : The handle functional event task source :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. - + Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events. For instance, a user agent may use a different task source for task events from other task sources. @@ -259,7 +259,7 @@ Markup Shorthands: css no, markdown yes

{{ServiceWorker/postMessage(message, transfer)}}

The postMessage(|message|, |transfer|) method *must* run these steps: - + 1. If the {{ServiceWorker/state}} attribute value of the context object is "redundant", throw an "{{InvalidStateError}}" exception and abort these steps. 1. Let |serviceWorker| be the service worker represented by the context object. 1. Invoke Run Service Worker algorithm with |serviceWorker| as the argument. @@ -278,7 +278,7 @@ Markup Shorthands: css no, markdown yes 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|. - + The task *must* use the DOM manipulation task source. @@ -493,12 +493,12 @@ Markup Shorthands: css no, markdown yes 1. Wait until scope to registration map has a new entry. 1. Jump to the step labeled *CheckRegistration*. 1. If |registration|'s active worker is null, wait until |registration|'s active worker changes. - + Note: Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm. - + 1. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Return context object's ready promise. - + Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker. @@ -1029,9 +1029,9 @@ Markup Shorthands: css no, markdown yes 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. 1. Wait for |task| to have executed. - + Note: Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken. - + 1. If |isClientEnumerable| is true, then: 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. Add |windowClient| to |matchedClients|. @@ -1224,7 +1224,7 @@ Markup Shorthands: css no, markdown yes * wait to respond flag * respond-with entered flag * respond-with error flag - +

{{FetchEvent/request|event.request}}

@@ -1273,7 +1273,7 @@ Markup Shorthands: css no, markdown yes 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. 1. Add |r| to the extend lifetime promises. - + Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil(f)|event.waitUntil(r)}} is called. 1. Set the stop propagation flag and stop immediate propagation flag. @@ -1314,7 +1314,7 @@ Markup Shorthands: css no, markdown yes 1. 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 body's stream into |potentialResponse|. - + 1. Set the potential response to |potentialResponse|. 1. Else: 1. Set the respond-with error flag. @@ -1581,16 +1581,16 @@ Markup Shorthands: css no, markdown yes
         Link: </js/sw.js>; rel="serviceworker"; scope="/"
       
- + has more or less the same effect as a document being loaded in a secure context with the following link element:
         <link rel="serviceworker" href="/js/sw.js" scope="/">
       
- + which is more or less equivalent to the page containing javascript code like: - +
         navigator.serviceworker.register("/js/sw.js", { scope: "/" });
       
@@ -1771,6 +1771,7 @@ Markup Shorthands: css no, markdown yes 1. Run the following substeps in parallel: * Fetch |r|. * To process response for |response|, run these substeps: + 1. If |response|'s type is "error", or |response|'s status is not an ok status, reject |responsePromise| with a TypeError. 1. Else if |response|'s header list contains a header named `Vary`, then: 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. @@ -1910,7 +1911,7 @@ Markup Shorthands: css no, markdown yes 1. For each |requestResponse| in |requestResponseArray|: 1. Add |requestResponse|[0] to |resultArray|. 1. Resolve |promise| with |resultArray|. - + 1. Return |promise|.
@@ -1999,7 +2000,7 @@ Markup Shorthands: css no, markdown yes 1. Abort these steps. Note: After this step, the existing DOM objects (i.e. the currently referenced Cache, Request, and Response objects) should remain functional. - + 1. Else: 1. Return false. @@ -2036,7 +2037,7 @@ Markup Shorthands: css no, markdown yes * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy HTTP header containing the value |policy|, the user agent *must* enforce |policy| for |serviceWorker|. * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy-Report-Only HTTP header containing the value |policy|, the user agent *must* monitor |policy| for |serviceWorker|. - + The primary reason for this restriction is to mitigate a broad class of content injection vulnerabilities, such as cross-site scripting (XSS). @@ -2224,7 +2225,7 @@ Markup Shorthands: css no, markdown yes :: |job|, a job : Output :: none - + 1. If the job queue is empty, then: 1. Push |job| to the job queue and invoke Run Job. 1. Else: @@ -2240,7 +2241,7 @@ Markup Shorthands: css no, markdown yes :: none : Output :: none - + 1. Assert: the job queue is not empty. 1. Queue a task to run these steps: 1. Let |job| be the element in the front of the job queue. @@ -2248,7 +2249,7 @@ Markup Shorthands: css no, markdown yes 1. Else if |job|'s job type is *update*, run Update with |job| in parallel. Note: For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event. - + 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel. @@ -2259,7 +2260,7 @@ Markup Shorthands: css no, markdown yes :: |job|, a job : Output :: none - + 1. Assert: the top element in the job queue is |job|. 1. Pop the top element from the job queue. 1. If the job queue is not empty, invoke Run Job with the top element of the job queue. @@ -2273,7 +2274,7 @@ Markup Shorthands: css no, markdown yes :: |value|, any : Output :: none - + 1. If |job|'s client is not null, queue a task to resolve |job|'s promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. @@ -2287,7 +2288,7 @@ Markup Shorthands: css no, markdown yes :: |reason|, an exception : Output :: none - + 1. If |job|'s client is not null, queue a task to reject |job|'s promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. @@ -2305,14 +2306,14 @@ Markup Shorthands: css no, markdown yes :: |workerType|, a worker type : Output :: none - + 1. If |scriptURL| is failure, reject |promise| with a TypeError and abort these steps. 1. If |scriptURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. 1. If any of the strings in |scriptURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. 1. If |scopeURL| is null, set |scopeURL| to the result of parsing the string "./" with |scriptURL|. Note: The scope url for the registration is set to the location of the service worker script by default. - + 1. If |scopeURL| is failure, reject |promise| with a TypeError and abort these steps. 1. If |scopeURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. 1. If any of the strings in |scopeURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. @@ -2329,7 +2330,7 @@ Markup Shorthands: css no, markdown yes :: |job|, a job : Output :: |promise|, a promise - + 1. If the result of running Is origin potentially trustworthy with the origin of |job|'s script url as the argument is Not Trusted, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. @@ -2358,7 +2359,7 @@ Markup Shorthands: css no, markdown yes :: |job|, a job : Output :: none - + 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s scope url as the argument. 1. If |registration| is null or |registration|'s uninstalling flag is set, then: 1. Invoke Reject Job Promise with |job| and a TypeError. @@ -2374,19 +2375,19 @@ Markup Shorthands: css no, markdown yes :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". : *"module"* :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. - + To perform the fetch given |request|, run the following steps if the is top-level flag is set: 1. Append `Service-Worker`/`script` to |request|'s header list. - + Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. - + 1. Set |request|'s skip service worker flag and |request|'s redirect mode to "error". 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". - + Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. - + 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. @@ -2394,7 +2395,7 @@ Markup Shorthands: css no, markdown yes 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. - + 1. Set |httpsState| to |response|'s HTTPS state. 1. Set |referrerPolicy| to the result of parsing the `Referrer-Policy` header of |response|. 1. If |serviceWorkerAllowed| is failure, then: @@ -2412,22 +2413,22 @@ Markup Shorthands: css no, markdown yes 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Asynchronously complete these steps with a network error. 1. If |response|'s cache state is not "local", set |registration|'s last update check time to the current time. - + Issue: The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state. - + 1. Return true. - + If the algorithm asynchronously completes with null, then: 1. Invoke Reject Job Promise with |job| and a TypeError. Note: This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception. - + 1. If |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. 1. Invoke Finish Job with |job| and abort these steps. - + Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. - + 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Invoke Finish Job with |job| and abort these steps. @@ -2453,12 +2454,12 @@ Markup Shorthands: css no, markdown yes : Input :: |registration|, a service worker registration :: *force bypass cache flag*, an optional flag unset by default - + Note: Implementers may use the *force bypass cache flag* to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs. - + : Output :: None - + 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. 1. If |newestWorker| is null, abort these steps. 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, null, and null. @@ -2476,7 +2477,7 @@ Markup Shorthands: css no, markdown yes :: |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. Let |redundantWorker| be null. @@ -2493,9 +2494,9 @@ Markup Shorthands: css no, markdown yes 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: 1. Wait until |e|'s extensions allowed flag is unset. 1. If 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. - + 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: @@ -2529,7 +2530,7 @@ Markup Shorthands: css no, markdown yes :: |registration|, a service worker registration : Output :: None - + 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: @@ -2539,16 +2540,16 @@ Markup Shorthands: css no, markdown yes 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. - + 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: 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 global object from its application cache, if it has one. - + Note: Resources will now use the service worker registration instead of the existing application cache. - + 1. For each service worker client |client| who is using |registration|: 1. Set |client|'s active worker to |registration|'s active worker. 1. Invoke Notify Controller Change algorithm with |client| as the argument. @@ -2570,7 +2571,7 @@ Markup Shorthands: css no, markdown yes :: |serviceWorker|, a service worker : Output :: None - + 1. Let |script| be |serviceWorker|'s script resource. 1. Assert: |script| is not null. 1. If |serviceWorker| is already running, abort these steps. @@ -2580,7 +2581,7 @@ Markup Shorthands: css no, markdown yes * Let |realmExecutionContext| be the created JavaScript execution context. 1. Let |workerEventLoop| be a newly created event loop. 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: - + : The realm execution context :: Return |realmExecutionContext|. : The global object @@ -2599,7 +2600,7 @@ Markup Shorthands: css no, markdown yes :: Return |workerGlobalScope|'s url. : The HTTPS state :: Return |workerGlobalScope|'s HTTPS state. - + 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. 1. Set |workerGlobalScope|'s HTTPS state to |serviceWorker|'s script resource's HTTPS state. 1. Set |workerGlobalScope|'s referrer policy to |serviceWorker|'s script resource's referrer policy. @@ -2607,14 +2608,14 @@ Markup Shorthands: css no, markdown yes 1. Create a new {{WorkerLocation}} object and associate it with |workerGlobalScope|. 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. 1. If |script| is a classic script, then run the classic script |script|. Otherwise, it is a module script; run the module script |script|. - + Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. - + 1. If |script|'s has ever been evaluated flag is unset, then: 1. Set |workerGlobalScope|'s associated service worker's set of event types to handle to the set of event types created from |settingsObject|'s global object's associated list of event listeners' event types. Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. - + 1. Set |script|'s has ever been evaluated flag. 1. Run the responsible event loop specified by |settingsObject| until it is destroyed. 1. Empty |workerGlobalScope|'s list of active timers. @@ -2627,14 +2628,14 @@ Markup Shorthands: css no, markdown yes :: |serviceWorker|, a service worker : Output :: None - + 1. If |serviceWorker| is not running, abort these steps. 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s environment settings object's global object. 1. Set |serviceWorkerGlobalScope|'s closing flag to true. 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's task queues, queue them to |serviceWorker|'s containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's task queues without processing them. Note: This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded. - + 1. Abort the script currently running in |serviceWorker|. @@ -2647,7 +2648,7 @@ Markup Shorthands: css no, markdown yes :: |request|, a request : Output :: |response|, a response - +
1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. @@ -2663,9 +2664,9 @@ Markup Shorthands: css no, markdown yes 1. If |request| is a potential-navigation-or-subresource request, then: 1. Return null. 1. Else if |request| is a non-subresource request, then: - + Note: If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration. - + 1. If |reservedClient| is not null and is an environment settings object, then: 1. If |reservedClient| is not a secure context, return null. 1. Else: @@ -2674,9 +2675,9 @@ Markup Shorthands: css no, markdown yes 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s url as the argument. 1. If |registration| is null or |registration|'s active worker is null, return null. 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. - + Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. - + 1. Else if |request| is a subresource request, then: 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. 1. Else, return null. @@ -2685,9 +2686,9 @@ Markup Shorthands: css no, markdown yes 1. Return null and continue running these steps in parallel. 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. 1. Abort these steps. - + Note: To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. - + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: @@ -2704,11 +2705,11 @@ Markup Shorthands: css no, markdown yes 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. 1. Else, set |response| to |e|'s potential response. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. - + The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. - + 1. Wait for |task| to have executed or been discarded. 1. If |respondWithEntered| is false, then: 1. If |eventCanceled| is true, return a network error and continue running these steps in parallel. @@ -2733,15 +2734,15 @@ Markup Shorthands: css no, markdown yes :: |request|, a request : Output :: |response|, a response - +
1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. 1. Let |eventCanceled| be false. 1. If |request| is not a subresource request, return null and abort these steps. - + Note: Foreign fetch only allows intercepting of subresource requests. Navigation requests can be intercepted by the regular fetch event anyway, so there is no benefit to supporting those requests here as well. - + 1. If |request|'s client is not a secure context, return null and abort these steps. 1. Let |activeWorker| be the result of running the [[#foreign-fetch-scope-match-algorithm]] algorithm passing |request|'s url as the argument. 1. If |activeWorker| is null, return null. @@ -2752,7 +2753,7 @@ Markup Shorthands: css no, markdown yes 1. If |activeWorker|'s list of foreign fetch origins is empty, set |originMatches| to true. 1. For each |origin| in |activeWorker|'s list of foreign fetch origins: 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. - + 1. If |originMatches| is false, return null. 1. Let |r| be a new {{Request}} object associated with |request|. 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. @@ -2779,11 +2780,11 @@ Markup Shorthands: css no, markdown yes 1. Else set |internalResponse|'s CORS-exposed header-name list to |headers|. 1. Set |response| to a CORS filtered response of |internalResponse|. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. - + The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. - + 1. Wait for |task| to have executed or been discarded. 1. If |respondWithEntered| is false, then: 1. If |eventCanceled| is true, then: @@ -2805,7 +2806,7 @@ Markup Shorthands: css no, markdown yes :: |callbackSteps|, an algorithm : 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. @@ -2813,15 +2814,15 @@ Markup Shorthands: css no, markdown yes 1. Return and continue running these steps in parallel. 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. 1. Abort these steps. - + Note: To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. - + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to invoke |callbackSteps| with |activeWorker|'s environment settings object's global object as its argument. - + The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. - + 1. Wait for |task| to have executed or been discarded. 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. @@ -2830,12 +2831,12 @@ Markup Shorthands: css no, markdown yes

Handle Service Worker Client Unload

The user agent *must* run these steps when a service worker client unloads by unloading, being killed, or terminating. - + : Input :: |client|, a service worker client : Output :: None - + 1. Run the following steps atomically. 1. Let |registration| be the service worker registration used by |client|. 1. If |registration| is null, abort these steps. @@ -2851,7 +2852,7 @@ Markup Shorthands: css no, markdown yes :: None : Output :: None - + 1. For each |scope| → |registration| of scope to registration map: 1. If |registration|'s installing worker |installingWorker| is not null, then: 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. @@ -2867,7 +2868,7 @@ Markup Shorthands: css no, markdown yes :: |job|, a job : Output :: none - + 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. @@ -2878,9 +2879,9 @@ Markup Shorthands: css no, markdown yes 1. Set |registration|'s uninstalling flag. 1. Invoke Resolve Job Promise with |job| and true. 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. - + Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. - + 1. Invoke Finish Job with |job|. @@ -2891,7 +2892,7 @@ Markup Shorthands: css no, markdown yes :: |scope|, a URL : Output :: |registration|, a service worker registration - + 1. Run the following steps atomically. 1. Let |scopeString| be serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be a new service worker registration whose scope url is set to |scope|. @@ -2906,7 +2907,7 @@ Markup Shorthands: css no, markdown yes :: |registration|, a service worker registration : Output :: None - + 1. Run the following steps atomically. 1. Let |redundantWorker| be null. 1. If |registration|'s installing worker is not null, then: @@ -2940,7 +2941,7 @@ Markup Shorthands: css no, markdown yes :: |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|. @@ -2954,7 +2955,7 @@ Markup Shorthands: css no, markdown yes 1. Set |registration|'s 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 active worker, or null if |registration|’s active worker is null. - + The task *must* use |registrationObject|'s relevant settings object's responsible event loop and the DOM manipulation task source. @@ -2966,7 +2967,7 @@ Markup Shorthands: css no, markdown yes :: |state|, a service worker's state : 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|: @@ -2974,22 +2975,22 @@ Markup Shorthands: css no, markdown yes 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, event.waitUntil(|f|) 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" - + 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, event.waitUntil(|f|) 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* @@ -2998,7 +2999,7 @@ Markup Shorthands: css no, markdown yes 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. @@ -3009,7 +3010,7 @@ Markup Shorthands: css no, markdown yes :: |client|, a service worker client : Output :: None - + 1. Assert: |client| is not null. 1. If |client| is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object |client| is associated with. The task *must* use |client|'s responsible event loop and the DOM manipulation task source. @@ -3022,15 +3023,15 @@ Markup Shorthands: css no, markdown yes :: |clientURL|, a URL : Output :: |registration|, a service worker registration - + 1. Run the following steps atomically. 1. Let |clientURLString| be serialized |clientURL|. 1. Let |matchingScope| be the empty string. 1. Let |allScopes| be the result of getting the keys from scope to registration map. 1. Set |matchingScope| to the longest value in |allScopes| which the value of |clientURLString| starts with, if it exists. - + Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). - + 1. Let |parsedMatchingScope| be null. 1. If |matchingScope| is not the empty string, set |parsedMatchingScope| to the result of parsing |matchingScope|. 1. Let |registration| be the result of running Get Registration algorithm passing |parsedMatchingScope| as the argument. @@ -3045,7 +3046,7 @@ Markup Shorthands: css no, markdown yes :: |requestURL|, a URL : Output :: |worker|, a service worker - + 1. Run the following steps atomically. 1. Let |registration| be the result of running the [[#scope-match-algorithm]] algorithm passing |requestURL| as the argument. 1. If |registration| is null, return null. @@ -3065,7 +3066,7 @@ Markup Shorthands: css no, markdown yes :: |scope|, a URL : Output :: |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 serialized |scope| with the *exclude fragment flag* set. @@ -3082,7 +3083,7 @@ Markup Shorthands: css no, markdown yes :: |registration|, a service worker registration : Output :: |worker|, a service worker - + 1. Run the following steps atomically. 1. Let |newestWorker| be null. 1. If |registration|'s installing worker is not null, set |newestWorker| to |registration|'s installing worker. @@ -3098,7 +3099,7 @@ Markup Shorthands: css no, markdown yes :: |client|, a service worker client : Output :: |clientObject|, a {{Client}} object - + 1. Let |clientObject| be a new {{Client}} object. 1. Set |clientObject|'s service worker client to |client|. 1. Set |clientObject|'s reserved state to true if |client|'s execution ready flag is unset, and false otherwise. @@ -3115,7 +3116,7 @@ Markup Shorthands: css no, markdown yes :: |ancestorOrigins|, an array : Output :: |windowClient|, a {{WindowClient}} object - + 1. Let |windowClient| be a new {{WindowClient}} object. 1. Set |windowClient|'s service worker client to |client|. 1. Set |windowClient|'s visibility state to |visibilityState|. @@ -3133,7 +3134,7 @@ Markup Shorthands: css no, markdown yes :: |targetStorage|, an array that has [{{Request}}, {{Response}}] pairs as its elements, optional : Output :: |resultArray|, an array that has [{{Request}}, {{Response}}] pairs as its elements - + 1. Let |requestArray| be an empty array. 1. Let |responseArray| be an empty array. 1. Let |resultArray| be an empty array. @@ -3181,7 +3182,7 @@ Markup Shorthands: css no, markdown yes :: |operations|, an array of {{CacheBatchOperation}} dictionary objects : Output :: |promise|, a promise resolves with an array of {{Response}} objects. - + 1. Let |p| be a promise resolved with no value. 1. Return the result of transforming |p| with a fulfillment handler that performs the following substeps in parallel: 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. @@ -3242,7 +3243,7 @@ Markup Shorthands: css no, markdown yes : `Service-Worker-Allowed` :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. - + Note: The value is a URL. If a relative URL is given, it is parsed against the script's URL.
@@ -3310,7 +3311,7 @@ Markup Shorthands: css no, markdown yes

Acknowledgements

- + Deep thanks go to Andrew Betts for organizing and hosting a small workshop of like-minded individuals including: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. From the clarity of the day's discussions and the use-cases outlined there, much has become possible. Further thanks to Andrew for raising consciousness about the offline problem. His organization of EdgeConf and inclusion of Offline as a persistent topic there has created many opportunities and connections that have enabled this work to progress. Anne van Kesteren has generously lent his encyclopedic knowledge of Web Platform arcana and standards development experience throughout the development of the service worker. This specification would be incomplete without his previous work in describing the real-world behavior of URLs, HTTP Fetch, Promises, and DOM. Similarly, this specification would not be possible without Ian Hickson's rigorous Web Worker spec. Much thanks to him. From 9ad8a7772dea83fee1f96aaa13ceebc11bd46a55 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 24 Nov 2016 16:14:03 +0000 Subject: [PATCH 06/17] All linking errors gone! --- docs/index.bs | 870 +++++++++++++++++++++++++++----------------------- 1 file changed, 469 insertions(+), 401 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 30f3faef..df602037 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -16,11 +16,86 @@ Abstract: This specification describes a method that enables applications to tak Abstract: Abstract: The core of this system is an event-driven Web Worker, which responds to events dispatched from documents and other sources. A system for managing installation, versions, and upgrades is provided. Abstract: -Abstract: The service worker is a generic entry point for event-driven background processing in the Web Platform that is extensible by other specifications. +Abstract: The service worker is a generic entry point for event-driven background processing in the Web Platform that is extensible by other specifications. Markup Shorthands: css no, markdown yes -
+
+
+
+spec: push; urlPrefix: https://w3c.github.io/push-api/
+    type: event
+        text: push; url: h-the-push-event
+
+spec: ecma-262; urlPrefix: http://tc39.github.io/ecma262/
+    type: dfn
+        text: Assert; url: sec-algorithm-conventions
+        text: [[Call]]; url: sec-ecmascript-function-objects-call-thisargument-argumentslist
+        text: promise; url: sec-promise-objects
+        text: DetachArrayBuffer; url: sec-detacharraybuffer
+        url: sec-list-and-record-specification-type
+            text: List
+            text: Record
+        text: map objects; url: sec-map-objects
+        text: InitializeHostDefinedRealm; url: sec-initializehostdefinedrealm
+        text: execution context; url: sec-execution-contexts
+
+spec: page-visibility; urlPrefix: https://www.w3.org/TR/page-visibility/
+    type: enum; text: VisibilityState; url: VisibilityState
+    type: attribute; text: visibilityState; for: Document; url: dom-document-visibilitystate
+
+spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
+    type: attribute
+        urlPrefix: comms.html
+            text: origin; for: MessageEvent; url: dom-messageevent-origin
+            text: source; for: MessageEvent; url: dom-messageevent-source
+            text: ports; for: MessageEvent; url: dom-messageevent-ports
+    type: dfn
+        urlPrefix: browsers.html
+            text: ancestor origins array; for: Location; url: concept-location-ancestor-origins-array
+        urlPrefix: syntax.html
+            text: delay the load event; for: document; url: delay-the-load-event
+
+spec: fetch; urlPrefix: https://fetch.spec.whatwg.org/
+    type: dfn
+        text: response; for: Response; url: concept-response-response
+        text: request; for: Request; url: concept-request-request
+        text: HTTP fetch; for: /; url: concept-http-fetch
+
+spec: rfc5988; urlPrefix: https://tools.ietf.org/html/rfc5988
+    type: dfn
+        text: context IRI; url: section-5.2
+        text: target attribute; url: section-5.4
+        text: target IRI; url: section-5.1
+
+spec: rfc7230; urlPrefix: https://tools.ietf.org/html/rfc7230
+    type: dfn
+        text: field-value; for: http; url: section-3.2
+
+spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
+    type: dfn
+        text: Vary; url: section-7.1.4
+
+spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-referrer-policy/
+    type: dfn
+        text: Parse a referrer policy from a Referrer-Policy header; url: parse-referrer-policy-from-header
+
+ +
 {
   "unsanctioned-tracking": {
     "href": "https://www.w3.org/2001/tag/doc/unsanctioned-tracking/",
@@ -39,15 +114,15 @@ Markup Shorthands: css no, markdown yes
 
   Web Applications traditionally assume that the network is reachable. This assumption pervades the platform. HTML documents are loaded over HTTP and traditionally fetch all of their sub-resources via subsequent HTTP requests. This places web content at a disadvantage versus other technology stacks.
 
-  The service worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the service worker, conceptually, between the network and a document renderer, allowing the service worker to provide content for documents, even while offline.
+  The service worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the service worker, conceptually, between the network and a document renderer, allowing the service worker to provide content for documents, even while offline.
 
-  Web developers familiar with previous attempts to solve the offline problem have reported a deficit of flexibility in those solutions. As a result, the service worker is highly procedural, providing a maximum of flexibility at the price of additional complexity for developers. Part of this complexity arises from the need to keep service workers responsive in the face of a single-threaded execution model. As a result, APIs exposed by service workers are almost entirely asynchronous, a pattern familiar in other JavaScript contexts but accentuated here by the need to avoid blocking document and resource loading.
+  Web developers familiar with previous attempts to solve the offline problem have reported a deficit of flexibility in those solutions. As a result, the service worker is highly procedural, providing a maximum of flexibility at the price of additional complexity for developers. Part of this complexity arises from the need to keep service workers responsive in the face of a single-threaded execution model. As a result, APIs exposed by service workers are almost entirely asynchronous, a pattern familiar in other JavaScript contexts but accentuated here by the need to avoid blocking document and resource loading.
 
-  Developers using the HTML5 Application Cache have also reported that several attributes of the design contribute to unrecoverable errors. A key design principle of the service worker is that errors should *always* be recoverable. Many details of the update process of service workers are designed to avoid these hazards.
+  Developers using the HTML5 Application Cache have also reported that several attributes of the design contribute to unrecoverable errors. A key design principle of the service worker is that errors should *always* be recoverable. Many details of the update process of service workers are designed to avoid these hazards.
 
-  Service workers are started and kept alive by their relationship to events, not documents. This design borrows heavily from developer and vendor experience with Shared Workers and Chrome Background Pages. A key lesson from these systems is the necessity to time-limit the execution of background processing contexts, both to conserve resources and to ensure that background context loss and restart is top-of-mind for developers. As a result, service workers bear more than a passing resemblance to Chrome Event Pages, the successor to Background Pages. Service workers may be started by user agents *without an attached document* and may be killed by the user agent at nearly any time. Conceptually, service workers can be thought of as Shared Workers that can start, process events, and die without ever handling messages from documents. Developers are advised to keep in mind that service workers may be started and killed many times a second.
+  Service workers are started and kept alive by their relationship to events, not documents. This design borrows heavily from developer and vendor experience with Shared Workers and Chrome Background Pages. A key lesson from these systems is the necessity to time-limit the execution of background processing contexts, both to conserve resources and to ensure that background context loss and restart is top-of-mind for developers. As a result, service workers bear more than a passing resemblance to Chrome Event Pages, the successor to Background Pages. Service workers may be started by user agents *without an attached document* and may be killed by the user agent at nearly any time. Conceptually, service workers can be thought of as Shared Workers that can start, process events, and die without ever handling messages from documents. Developers are advised to keep in mind that service workers may be started and killed many times a second.
 
-  Service workers are generic, event-driven, time-limited script contexts that run at an origin. These properties make them natural endpoints for a range of runtime services that may outlive the context of a particular document, e.g. handling push notifications, background data synchronization, responding to resource requests from other origins, or receiving centralized updates to expensive-to-calculate data (e.g., geolocation or gyroscope).
+  Service workers are generic, event-driven, time-limited script contexts that run at an origin. These properties make them natural endpoints for a range of runtime services that may outlive the context of a particular document, e.g. handling push notifications, background data synchronization, responding to resource requests from other origins, or receiving centralized updates to expensive-to-calculate data (e.g., geolocation or gyroscope).
 
@@ -56,48 +131,48 @@ Markup Shorthands: css no, markdown yes

Service Worker

- A service worker is a type of web worker. A service worker executes in the registering service worker client's origin. + A service worker is a type of web worker. A service worker executes in the registering service worker client's origin. - A service worker has an associated state, which is one of *parsed*, *installing*, *installed*, *activating*, *activated*, and *redundant*. It is initially *parsed*. + A service worker has an associated state, which is one of *parsed*, *installing*, *installed*, *activating*, *activated*, and *redundant*. It is initially *parsed*. - A service worker has an associated script url (a URL). + A service worker has an associated script url (a URL). - A service worker has an associated type which is either "classic" or "module". Unless stated otherwise, it is "classic". + A service worker has an associated type which is either "classic" or "module". Unless stated otherwise, it is "classic". - A service worker has an associated containing service worker registration (a service worker registration), which contains itself. + A service worker has an associated containing service worker registration (a service worker registration), which contains itself. - A service worker has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration. + A service worker has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration. A service worker has an associated global object (a {{ServiceWorkerGlobalScope}} object or null). - A service worker is dispatched a set of lifecycle events, install and activate, and functional events including fetch. + A service worker is dispatched a set of lifecycle events, install and activate, and functional events including fetch. - A service worker has an associated script resource (a script), which represents its own script resource. It is initially set to null. + A service worker has an associated script resource (a script), which represents its own script resource. It is initially set to null. A script resource has an associated has ever been evaluated flag. It is initially unset. A script resource has an associated HTTPS state (an HTTPS state value). It is initially "none". - A script resource has an associated referrer policy (a referrer policy). It is initially the empty string. + A script resource has an associated referrer policy (a referrer policy). It is initially the empty string. - A service worker has an associated script resource map which is an ordered map where the keys are URLs and the values are responses. + A service worker has an associated script resource map which is an ordered map where the keys are URLs and the values are responses. - A service worker has an associated skip waiting flag. Unless stated otherwise it is unset. + A service worker has an associated skip waiting flag. Unless stated otherwise it is unset. - A service worker has an associated imported scripts updated flag. It is initially unset. + A service worker has an associated imported scripts updated flag. It is initially unset. - A service worker has an associated set of event types to handle whose element type is an event listener's event type. It is initially set to null. + A service worker has an associated set of event types to handle whose element type is an event listener's event type. It is initially set to null. - 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 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. + A service worker has an associated list of foreign fetch origins whose element type is a URL. It is initially empty.

Lifetime

- The lifetime of a service worker is tied to the execution lifetime of events and not references held by service worker clients to the {{ServiceWorker}} object. + The lifetime of a service worker is tied to the execution lifetime of events and not references held by service worker clients to the {{ServiceWorker}} object. - A user agent *may* terminate service workers at any time it: + A user agent *may* terminate service workers at any time it: * Has no event to handle. * Detects abnormal operation: such as infinite loops and tasks exceeding imposed time limits (if any) while handling the events. @@ -107,28 +182,28 @@ Markup Shorthands: css no, markdown yes

Service Worker Registration

- A service worker registration is a tuple of a scope url and a set of service workers, an installing worker, a waiting worker, and an active worker. A user agent *may* enable many service worker registrations at a single origin so long as the scope url of the service worker registration differs. A service worker registration of an identical scope url when one already exists in the user agent causes the existing service worker registration to be replaced. + A service worker registration is a tuple of a scope url and a set of service workers, an installing worker, a waiting worker, and an active worker. A user agent *may* enable many service worker registrations at a single origin so long as the scope url of the service worker registration differs. A service worker registration of an identical scope url when one already exists in the user agent causes the existing service worker registration to be replaced. - A service worker registration has an associated scope url (a URL). + A service worker registration has an associated scope url (a URL). - A service worker registration has an associated registering script url (a URL). + A service worker registration has an associated registering script url (a URL). - A service worker registration has an associated installing worker (a service worker or null) whose state is *installing*. It is initially set to null. + A service worker registration has an associated installing worker (a service worker or null) whose state is *installing*. It is initially set to null. - A service worker registration has an associated waiting worker (a service worker or null) whose state is *installed*. It is initially set to null. + A service worker registration has an associated waiting worker (a service worker or null) whose state is *installed*. It is initially set to null. - A service worker registration has an associated active worker (a service worker or null) whose state is either *activating* or *activated*. It is initially set to null. + A service worker registration has an associated active worker (a service worker or null) whose state is either *activating* or *activated*. It is initially set to null. - A service worker registration has an associated last update check time. It is initially set to null. + A service worker registration has an associated last update check time. It is initially set to null. - A service worker registration has an associated uninstalling flag. It is initially unset. + 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 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 task queues are not processed by any event loops in and of itself. + 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 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 task queues are not processed by any event loops in and of itself.

Lifetime

- A user agent *must* persistently keep a list of registered service worker registrations unless otherwise they are explicitly unregistered. A user agent has a scope to registration map that stores the entries of the tuple of service worker registration's scope url and the corresponding service worker registration. The lifetime of service worker registrations is beyond that of the {{ServiceWorkerRegistration}} objects which represent them within the lifetime of their corresponding service worker clients. + A user agent *must* persistently keep a list of registered service worker registrations unless otherwise they are explicitly unregistered. A user agent has a scope to registration map that stores the entries of the tuple of service worker registration's scope url and the corresponding service worker registration. The lifetime of service worker registrations is beyond that of the {{ServiceWorkerRegistration}} objects which represent them within the lifetime of their corresponding service worker clients.
@@ -137,13 +212,13 @@ Markup Shorthands: css no, markdown yes A service worker client is a type of environment or environment settings object. - A service worker client has an algorithm defined as the origin that returns the service worker client's creation URL's origin if the service worker client is a type of environment, and the service worker client's origin otherwise. + A service worker client has an algorithm defined as the origin that returns the service worker client's creation URL's origin if the service worker client is a type of environment, and the service worker client's origin otherwise. - A window client is a service worker client whose global object is a {{Window}} object. + A window client is a service worker client whose global object is a {{Window}} object. - A dedicated worker client is a service worker client whose global object is a {{DedicatedWorkerGlobalScope}} object. + A dedicated worker client is a service worker client whose global object is a {{DedicatedWorkerGlobalScope}} object. - A shared worker client is a service worker client whose global object is a {{SharedWorkerGlobalScope}} object. + A shared worker client is a service worker client whose global object is a {{SharedWorkerGlobalScope}} object. A worker client is either a dedicated worker client or a shared worker client.
@@ -151,24 +226,24 @@ Markup Shorthands: css no, markdown yes

Selection and Use

- A service worker client independently selects and uses a service worker registration for its own loading and its subresources. The selection of a service worker registration, upon a non-subresource request, is a process of either matching a service worker registration from scope to registration map or inheriting an existing service worker registration from its parent or owner context depending on the request's url. + A service worker client independently selects and uses a service worker registration for its own loading and its subresources. The selection of a service worker registration, upon a non-subresource request, is a process of either matching a service worker registration from scope to registration map or inheriting an existing service worker registration from its parent or owner context depending on the request's url. - When the request's url is not local, a service worker client matches a service worker registration from scope to registration map. That is, the service worker client attempts to consult a service worker registration whose scope url matches its creation URL. + When the request's url is not local, a service worker client matches a service worker registration from scope to registration map. That is, the service worker client attempts to consult a service worker registration whose scope url matches its creation URL. - When the request's url is local, if the service worker client's responsible browsing context is a nested browsing context or the service worker client is a worker client, the service worker client inherits the service worker registration from its parent browsing context's environment or one of the worker's Documents' environment, respectively, if it exists. + When the request's url is local, if the service worker client's responsible browsing context is a nested browsing context or the service worker client is a worker client, the service worker client inherits the service worker registration from its parent browsing context's environment or one of the worker's Documents' environment, respectively, if it exists. - If the selection was successful, the selected service worker registration's active worker starts to control the service worker client. Otherwise, the flow returns to fetch where it falls back to the default behavior. When a service worker client is controlled by an active worker, it is considered that the service worker client is using the active worker's containing service worker registration. + If the selection was successful, the selected service worker registration's active worker starts to control the service worker client. Otherwise, the flow returns to fetch where it falls back to the default behavior. When a service worker client is controlled by an active worker, it is considered that the service worker client is using the active worker's containing service worker registration.

Task Sources

- The following additional task sources are used by service workers. + The following additional task sources are used by service workers. : The handle fetch task source - :: This task source is used for dispatching fetch events to service workers. + :: This task source is used for dispatching fetch events to service workers. : The handle functional event task source - :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. + :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events. For instance, a user agent may use a different task source for task events from other task sources.
@@ -176,9 +251,9 @@ Markup Shorthands: css no, markdown yes

User Agent Shutdown

- A user agent *must* maintain the state of its stored service worker registrations across restarts with the following rules: + A user agent *must* maintain the state of its stored service worker registrations across restarts with the following rules: - * An installing worker does not persist but discarded. If the installing worker was the only service worker for the service worker registration, the service worker registration is discarded. + * An installing worker does not persist but discarded. If the installing worker was the only service worker for the service worker registration, the service worker registration is discarded. * A waiting worker promotes to an active worker. To attain this, the user agent *must* invoke Handle User Agent Shutdown when it terminates. @@ -228,14 +303,14 @@ Markup Shorthands: css no, markdown yes }; - A {{ServiceWorker}} object represents a service worker. Each {{ServiceWorker}} object is associated with a service worker. Multiple separate objects implementing the {{ServiceWorker}} interface across documents and workers can all be associated with the same service worker simultaneously. + A {{ServiceWorker}} object represents a service worker. Each {{ServiceWorker}} object is associated with a service worker. Multiple separate objects implementing the {{ServiceWorker}} interface across documents and workers can all be associated with the same service worker simultaneously. - A {{ServiceWorker}} object has an associated {{ServiceWorkerState}} object which is itself associated with service worker's state. + A {{ServiceWorker}} object has an associated {{ServiceWorkerState}} object which is itself associated with service worker's state.

{{ServiceWorker/scriptURL}}

- The scriptURL attribute *must* return the service worker's serialized script url. + The scriptURL attribute *must* return the service worker's serialized script url.
For example, consider a document created by a navigation to https://example.com/app.html which matches via the following registration call which has been previously executed: @@ -261,7 +336,7 @@ Markup Shorthands: css no, markdown yes The postMessage(|message|, |transfer|) method *must* run these steps: 1. If the {{ServiceWorker/state}} attribute value of the context object is "redundant", throw an "{{InvalidStateError}}" exception and abort these steps. - 1. Let |serviceWorker| be the service worker represented by the context object. + 1. Let |serviceWorker| be the service worker represented by the context object. 1. Invoke Run Service Worker algorithm with |serviceWorker| as the argument. 1. Let |destination| be the {{ServiceWorkerGlobalScope}} object associated with |serviceWorker|. 1. Let |targetRealm| be |destination|'s Realm. @@ -272,7 +347,7 @@ Markup Shorthands: css no, markdown yes 1. Queue a task that runs the following steps: 1. Create an event |e| that uses the {{ExtendableMessageEvent}} interface, with the event type {{message!!event}}, which does not bubble and is not cancelable. 1. Let the {{ExtendableMessageEvent/data}} attribute of |e| be initialized to |clonedMessage|. - 1. Let the {{ExtendableMessageEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |incumbentSettings|'s origin. + 1. Let the {{ExtendableMessageEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |incumbentSettings|'s origin. 1. If |incumbentGlobal| is a {{ServiceWorkerGlobalScope}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{ServiceWorker}} object that represents |incumbentGlobal|'s service worker. 1. Else if |incumbentGlobal| is a {{Window}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{WindowClient}} object that represents |incumbentGlobal|'s browsing context. 1. Else, let it be initialized to a new {{Client}} object that represents the worker associated with |incumbentGlobal|. @@ -324,14 +399,14 @@ Markup Shorthands: css no, markdown yes }; - A {{ServiceWorkerRegistration}} object represents a service worker registration. Each {{ServiceWorkerRegistration}} object is associated with a service worker registration (a service worker registration). Multiple separate objects implementing the {{ServiceWorkerRegistration}} interface across documents and workers can all be associated with the same service worker registration simultaneously. + A {{ServiceWorkerRegistration}} object represents a service worker registration. Each {{ServiceWorkerRegistration}} object is associated with a service worker registration (a service worker registration). Multiple separate objects implementing the {{ServiceWorkerRegistration}} interface across documents and workers can all be associated with the same service worker registration simultaneously.
installing attribute *must* return the value to which it was last set. - Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.
@@ -339,7 +414,7 @@ Markup Shorthands: css no, markdown yes waiting attribute *must* return the value to which it was last set. - Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.
@@ -347,13 +422,13 @@ Markup Shorthands: css no, markdown yes active attribute *must* return the value to which it was last set. - Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.

{{ServiceWorkerRegistration/scope}}

- The scope attribute *must* return service worker registration's serialized scope url. + The scope attribute *must* return service worker registration's serialized scope url.
In the example in section 3.1.1, the value of registration.scope, obtained from navigator.serviceWorker.ready.then(registration => console.log(registration.scope)) for example, will be "https://example.com/". @@ -370,7 +445,7 @@ Markup Shorthands: css no, markdown yes 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. 1. If |newestWorker| is null, reject |p| with an "{{InvalidStateError}}" exception and abort these steps. 1. If the context object's relevant settings object's global object |globalObject| is a {{ServiceWorkerGlobalScope}} object, and |globalObject|'s associated service worker's state is *installing*, reject |p| with an "{{InvalidStateError}}" exception and abort these steps. - 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, |p|, and the context object's relevant settings object |client|. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, |p|, and the context object's relevant settings object. 1. Set |job|'s worker type to |newestWorker|'s type. 1. Invoke Schedule Job with |job|. 1. Return |p|. @@ -379,12 +454,12 @@ Markup Shorthands: css no, markdown yes
- 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 < afor="/">service worker clients (including itself) using this service worker registration unload. That is, the {{ServiceWorkerRegistration/unregister()}} method only affects subsequent navigations. unregister() method *must* run these steps: 1. Let |p| be a promise. - 1. Let |job| be the result of running Create Job with *unregister*, the scope url of the service worker registration, null, |p|, and the context object's relevant settings object |client|. + 1. Let |job| be the result of running Create Job with *unregister*, the scope url of the service worker registration, null, |p|, and the context object's relevant settings object. 1. Invoke Schedule Job with |job|. 1. Return |p|.
@@ -404,7 +479,7 @@ Markup Shorthands: css no, markdown yes
- +
install {{InstallEvent}}[Lifecycle event] The service worker's containing service worker registration's installing worker changes. (See step 11.2 of the Install algorithm.)[Lifecycle event] The service worker's containing service worker registration's installing worker changes. (See step 11.2 of the Install algorithm.)
activate {{ExtendableEvent}}[Lifecycle event] The service worker's containing service worker registration's active worker changes. (See step 12.2 of the Activate algorithm.)[Lifecycle event] The service worker's containing service worker registration's active worker changes. (See step 12.2 of the Activate algorithm.)
fetch {{FetchEvent}}[Functional event] The http fetch invokes Handle Fetch with request. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.)[Functional event] The http fetch invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.)
foreignfetch {{FetchEvent}}[Functional event] The http fetch invokes [[#on-foreign-fetch-request-algorithm]] with request. As a result of performing [[#on-foreign-fetch-request-algorithm]], the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.)[Functional event] The http fetch invokes [[#on-foreign-fetch-request-algorithm]] with |request|. As a result of performing [[#on-foreign-fetch-request-algorithm]], the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.)
message
onupdatefoundupdatefoundupdatefound
@@ -458,7 +533,7 @@ Markup Shorthands: css no, markdown yes The user agent *must* create a {{ServiceWorkerContainer}} object when a {{Navigator}} object or a {{WorkerNavigator}} object is created and associate it with that object. - A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the service worker registrations, and provides access to the state of the service worker registrations and their associated service workers. + A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the service worker registrations, and provides access to the state of the service worker registrations and their associated service workers. A {{ServiceWorkerContainer}} has an associated service worker client, which is a service worker client whose global object is associated with the {{Navigator}} object or the {{WorkerNavigator}} object that the {{ServiceWorkerContainer}} is retrieved from. @@ -474,7 +549,7 @@ Markup Shorthands: css no, markdown yes 1. Let |client| be the context object's service worker client. 1. Return the {{ServiceWorker}} object that represents |client|'s active service worker. - Note: {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.
@@ -499,13 +574,13 @@ Markup Shorthands: css no, markdown yes 1. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Return context object's ready promise. - Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker. + Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker.
- Note: The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a service worker registration for the given scope url. If successful, a service worker registration ties the provided |scriptURL| to a scope url, which is subsequently used for navigation matching. + Note: The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a service worker registration for the given scope url. If successful, a service worker registration ties the provided |scriptURL| to a scope url, which is subsequently used for navigation matching. register(|scriptURL|, |options|) method *must* run these steps: @@ -526,7 +601,7 @@ Markup Shorthands: css no, markdown yes 1. Let |client| be the context object's service worker client. 1. Let |clientURL| be the result of parsing |clientURL| with the context object's relevant settings object's API base URL. 1. If |clientURL| is failure, return a promise rejected with a TypeError. - 1. If the origin of |clientURL| is not |client|'s origin, return a |promise| rejected with a "{{SecurityError}}" exception. + 1. If the origin of |clientURL| is not |client|'s origin, return a |promise| rejected with a "{{SecurityError}}" exception. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: 1. Let |registration| be the result of running Match Service Worker Registration algorithm with |clientURL| as its argument. @@ -546,8 +621,8 @@ Markup Shorthands: css no, markdown yes 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: 1. Let |array| be an empty array. - 1. For each |key| → |value| of scope to registration map: - 1. If the origin of the result of parsing |key| is the same as |client|'s origin, and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. + 1. For each |key| → |value| of scope to registration map: + 1. If the origin of the result of parsing |key| is the same as |client|'s origin, and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. 1. Resolve |promise| with |array|. 1. Return |promise|.
@@ -573,7 +648,7 @@ Markup Shorthands: css no, markdown yes oncontrollerchange - controllerchange + controllerchange onmessage @@ -640,7 +715,7 @@ Markup Shorthands: css no, markdown yes controllerchange {{Event}} - The service worker client's active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a service worker causes activation of the service worker registration to occur while service worker clients are using the service worker registration, {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the service worker that controls the service worker client.) + The service worker client's active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a service worker causes activation of the service worker registration to occur while service worker clients are using the service worker registration, {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the service worker that controls the service worker client.) @@ -712,9 +787,9 @@ Markup Shorthands: css no, markdown yes };
- A {{ServiceWorkerGlobalScope}} object represents the global execution context of a service worker. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a service worker). + A {{ServiceWorkerGlobalScope}} object represents the global execution context of a service worker. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a service worker). - Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a service worker is started, kept alive and killed by their relationship to events, not service worker clients. Any type of synchronous requests must not be initiated inside of a service worker. + Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a service worker is started, kept alive and killed by their relationship to events, not service worker clients. Any type of synchronous requests must not be initiated inside of a service worker.

{{ServiceWorkerGlobalScope/clients}}

@@ -731,15 +806,15 @@ Markup Shorthands: css no, markdown yes

{{ServiceWorkerGlobalScope/skipWaiting()}}

- Note: The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this service worker to progress from the registration's waiting position to active even while service worker clients are using the registration. + Note: The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this service worker to progress from the registration's waiting position to active even while service worker clients are using the registration. skipWaiting() method *must* run these steps: 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. Set service worker's skip waiting flag. - 1. If service worker's state is *installed*, then: - 1. Run Activate algorithm passing service worker's registration as the argument. + 1. Set service worker's skip waiting flag. + 1. If service worker's state is *installed*, then: + 1. Run Activate algorithm passing service worker's registration as the argument. 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -767,11 +842,11 @@ Markup Shorthands: css no, markdown yes onfetch - fetch + fetch onforeignfetch - foreignfetch + foreignfetch onmessage @@ -804,7 +879,7 @@ Markup Shorthands: css no, markdown yes }; - A {{Client}} object has an associated service worker client (a service worker client). + A {{Client}} object has an associated service worker client (a service worker client). A {{Client}} object has an associated reserved state, which is either true or false. @@ -847,9 +922,9 @@ Markup Shorthands: css no, markdown yes 1. Add a task that runs the following steps to |destination|'s client message queue: 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type message, which does not bubble and is not cancelable. 1. Let the data attribute of |e| be initialized to |clonedMessage|. - 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s origin. - 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the service worker associated with |sourceSettings|'s global object. - 1. Let the ports attribute of |e| be initialized to |newPorts|. + 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s origin. + 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the service worker associated with |sourceSettings|'s global object. + 1. Let the ports attribute of |e| be initialized to |newPorts|. 1. Dispatch |e| at |destination|.
@@ -902,7 +977,7 @@ Markup Shorthands: css no, markdown yes 1. Let |url| be the result of parsing |url| with the context object's relevant settings object's API base URL. 1. If |url| is failure, return a promise rejected with a TypeError. - 1. If |url| is about:blank, return a promise rejected with a TypeError. + 1. If |url| is about:blank, return a promise rejected with a TypeError. 1. If the context object's associated service worker client's active service worker is not the context object's relevant global object's service worker, return a promise rejected with a TypeError. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: @@ -920,7 +995,7 @@ Markup Shorthands: css no, markdown yes 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. 1. Wait for |task| to have executed (including its asynchronous steps). 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. - 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: 1. Resolve |promise| with null. 1. Abort these steps. 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. @@ -967,7 +1042,7 @@ Markup Shorthands: css no, markdown yes 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: + 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: 1. If |client|'s id is not |id|, continue to the next iteration of the loop. 1. If |client| is a type of environment, then: 1. If |client|’s creation URL is not a potentially trustworthy URL, reject |promise| with a "{{SecurityError}}" exception and abort these steps. @@ -1002,7 +1077,7 @@ Markup Shorthands: css no, markdown yes 1. Let |promise| be a new promise. 1. Run these substeps in parallel: 1. Let |targetClients| be an empty array. - 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: + 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: 1. If |client| is a type of environment, then: 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. 1. Else: @@ -1013,7 +1088,7 @@ Markup Shorthands: css no, markdown yes 1. If |client|'s execution ready flag is unset, continue to the next iteration of the loop. 1. Add |client| to |targetClients|. 1. Let |matchedClients| be an empty array. - 1. For each service worker client |client| in |targetClients|: + 1. For each service worker client |client| in |targetClients|: 1. If |options|.{{ClientQueryOptions/type}} is "window" or "all", and |client| is a type of environment or is a window client, then: 1. Let |browsingContext| be null. 1. Let |isClientEnumerable| be true. @@ -1052,7 +1127,7 @@ Markup Shorthands: css no, markdown yes The openWindow(|url|) method *must* run these steps: 1. Let |url| be the result of parsing |url| with the context object's relevant settings object's API base URL. 1. If |url| is failure, return a promise rejected with a TypeError. - 1. If |url| is about:blank, return a promise rejected with a TypeError. + 1. If |url| is about:blank, return a promise rejected with a TypeError. 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: @@ -1069,7 +1144,7 @@ Markup Shorthands: css no, markdown yes 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. 1. Wait for |task| to have executed (including its asynchronous steps). 1. If |openWindowFailed| is true, reject |promise| with a TypeError and abort these steps. - 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: 1. Resolve |promise| with null. 1. Abort these steps. 1. Let |client| be the result of running Create Window Client algorithm with |newContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. @@ -1085,7 +1160,7 @@ Markup Shorthands: css no, markdown yes 1. If the service worker is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. For each service worker client |client| whose origin is the same as the service worker's origin: + 1. For each service worker client |client| whose origin is the same as the service worker's origin: 1. If |client| is a type of environment, then: 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. 1. Else: @@ -1120,16 +1195,16 @@ Markup Shorthands: css no, markdown yes An {{ExtendableEvent}} object has an associated extensions allowed flag. It is initially set. - Service workers have two lifecycle events, install and activate. Service workers use the {{ExtendableEvent}} interface for activate event and install event. + Service workers have two lifecycle events, install and activate. Service workers use the {{ExtendableEvent}} interface for activate event and install event. - Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. + Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. Note: To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run Extend Service Worker Lifetime algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event.
-

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

+

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

- {{ExtendableEvent/waitUntil(f)}} method extends the lifetime of the event. + {{ExtendableEvent/waitUntil()}} method extends the lifetime of the event. waitUntil(|f|) method *must* run these steps: @@ -1139,12 +1214,12 @@ Markup Shorthands: css no, markdown yes 1. Add |f| to the extend lifetime promises.
- Service workers and extensions that define event handlers *may* define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure. + Service workers and extensions that define event handlers *may* define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure. - Service workers define the following behaviors for install event and activate event, respectively: + Service workers define the following behaviors for install event and activate event, respectively: - * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. - * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries. + * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. + * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries.
@@ -1170,12 +1245,12 @@ Markup Shorthands: css no, markdown yes registerForeignFetch(|options|) method *must* run these steps: 1. If the dispatch flag is unset, then: - 1. Throw an "InvalidStateError" exception. + 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. 1. If |options|.{{ForeignFetchOptions/origins}} is empty throw a TypeError and abort these steps. 1. Let |originURLs| be an empty list of URLs. 1. If the value of |options|.{{ForeignFetchOptions/origins}} is not a single string equal to a single U+002A ASTERISK character (*): - 1. For each |origin| in |options|.|origins|: + 1. For each |origin| in |options|.origins: 1. If the value of |origin| is not an absolute-URL string, throw a TypeError and abort these steps. 1. Add the result of parsing |origin| to |originURLs|. 1. If |options|.{{ForeignFetchOptions/scopes}} is empty throw a TypeError and abort these steps. @@ -1187,8 +1262,8 @@ Markup Shorthands: css no, markdown yes 1. Let |subScopeString| be the serialized |subScopeURL|. 1. If |subScopeString| does not start with |scopeString|, throw a TypeError and abort these steps. 1. Add |subScopeURL| to |subScopeURLs|. - 1. Set this service worker's list of foreign fetch scopes to |subScopeURLs|. - 1. Set this service worker's list of foreign fetch origins to |originURLs|. + 1. Set this service worker's list of foreign fetch scopes to |subScopeURLs|. + 1. Set this service worker's list of foreign fetch origins to |originURLs|.
@@ -1217,9 +1292,9 @@ Markup Shorthands: css no, markdown yes }; - Service workers have an essential functional event fetch. For fetch event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. + Service workers have an essential functional event fetch. For fetch event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. - Each event using {{FetchEvent}} interface has an associated potential response (a response), initially set to null, and the following associated flags that are initially unset: + Each event using {{FetchEvent}} interface has an associated potential response (a response), initially set to null, and the following associated flags that are initially unset: * wait to respond flag * respond-with entered flag @@ -1261,7 +1336,7 @@ Markup Shorthands: css no, markdown yes

{{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: @@ -1274,7 +1349,7 @@ Markup Shorthands: css no, markdown yes 1. Abort these steps. 1. Add |r| to the extend lifetime promises. - Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil(f)|event.waitUntil(r)}} is called. + 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 respond-with entered flag. @@ -1292,34 +1367,34 @@ Markup Shorthands: css no, markdown yes 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, except for its body. - 1. If |response|'s body is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|'s body's stream. + 1. Let |potentialResponse| be a copy of |response|'s associated response, except for its body. + 1. If |response|'s body is non-null, run these substeps: + 1. Let |reader| be the result of getting a reader from |response|'s 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 body's stream with |reader|. + 1. Let |promise| be the result of reading a chunk a chunk from |response|'s 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, error |newStream| with a TypeError. - 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. - 1. Let |newStream| be the result of constructing a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. + 1. When |promise| is fulfilled with a value that matches with neither of the above patterns, or |promise| is rejected, error |newStream| with a TypeError. + 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. + 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. 1. Set |potentialResponse|'s 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 close |newStream| and set |done| to true. + 1. Otherwise, if |bytes| is empty and |end-of-body| is true, then 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. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. + 1. 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 body's stream into |potentialResponse|. + Note: These substeps are meant to produce the observable equivalent of "piping" |response|'s body's stream into |potentialResponse|. 1. Set the potential response to |potentialResponse|. 1. Else: 1. Set the respond-with error flag. - Note: If the 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 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 wait to respond flag. @@ -1350,9 +1425,9 @@ Markup Shorthands: css no, markdown yes }; - Service workers have a functional event foreignfetch. For foreignfetch events, service workers use the {{ForeignFetchEvent}} interface which extends the {{ExtendableEvent}} interface. + Service workers have a functional event foreignfetch. For foreignfetch events, service workers use the {{ForeignFetchEvent}} interface which extends the {{ExtendableEvent}} interface. - Each event using {{ForeignFetchEvent}} interface has an associated potential response (a response), initially set to null, an associated origin (a {{USVString}} or null), initially set to null, an associated list of exposed headers (whose element type is a byte string), initially set to an empty list, and the following associated flags that are initially unset: + Each event using {{ForeignFetchEvent}} interface has an associated potential response (a response), initially set to null, an associated origin (a {{USVString}} or null), initially set to null, an associated list of exposed headers (whose element type is a byte string), initially set to an empty list, and the following associated flags that are initially unset: * wait to respond flag * respond-with entered flag @@ -1373,7 +1448,7 @@ Markup Shorthands: css no, markdown yes

{{ForeignFetchEvent/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: @@ -1403,31 +1478,31 @@ Markup Shorthands: css no, markdown yes 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|.{{ForeignFetchResponse/response}}'s associated response, except for its body. + 1. Let |potentialResponse| be a copy of |response|.{{ForeignFetchResponse/response}}'s associated response, except for its body. 1. If |response|.{{ForeignFetchResponse/response}}'s body is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/response}}'s body's stream. + 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/response}}'s 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|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. + 1. Let |promise| be the result of reading a chunk a chunk from |response|.{{ForeignFetchResponse/response}}'s 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, error |newStream| with a TypeError. - 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. - 1. Let |newStream| be the result of constructing a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. + 1. When |promise| is fulfilled with a value that matches with neither of the above patterns, or |promise| is rejected, error |newStream| with a TypeError. + 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. + 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. 1. Set |potentialResponse|'s 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 close |newStream| and set |done| to true. + 1. Otherwise, if |bytes| is empty and |end-of-body| is true, then 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. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. + 1. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. 1. Set the potential response to |potentialResponse|. 1. Else: 1. Set the respond-with error flag. - Note: If the respond-with error flag is set, a network error is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 19.1.) Otherwise, a filtered version of |response| is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 20.1.) + Note: If the respond-with error flag is set, a network error is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 19.1.) Otherwise, a filtered version of |response| is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 20.1.) 1. Unset the wait to respond flag. @@ -1457,7 +1532,7 @@ Markup Shorthands: css no, markdown yes }; - Service workers define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, service workers use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface. + Service workers define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, service workers use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface.

{{ExtendableMessageEvent/data|event.data}}

@@ -1468,7 +1543,7 @@ Markup Shorthands: css no, markdown yes

{{ExtendableMessageEvent/origin|event.origin}}

- The origin attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string. It represents the origin of the service worker client that sent the message. + The origin attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string. It represents the origin of the service worker client that sent the message.
@@ -1517,12 +1592,12 @@ Markup Shorthands: css no, markdown yes fetch {{FetchEvent}} - [Functional event] The http fetch invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) + [Functional event] The http fetch invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) foreignfetch {{FetchEvent}} - [Functional event] The http fetch invokes [[#on-foreign-fetch-request-algorithm]] with |request|. As a result of performing [[#on-foreign-fetch-request-algorithm]], the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) + [Functional event] The http fetch invokes [[#on-foreign-fetch-request-algorithm]] with |request|. As a result of performing [[#on-foreign-fetch-request-algorithm]], the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) message @@ -1546,8 +1621,8 @@ Markup Shorthands: css no, markdown yes 1. If the Link header has an "anchor" parameter, abort these steps. 1. Let |contextURL| be the result of parsing the context IRI of the Link header. - 1. If the result of running Is origin potentially trustworthy with the origin of |contextURL| is Not Trusted, abort these steps. - 1. Let |request| be the request for which this header was received in the response. + 1. If the result of running potentially trustworthy origin with the origin of |contextURL| is Not Trusted, abort these steps. + 1. Let |request| be the request for which this header was received in the response. 1. If |request|'s client is not a secure context, abort these steps. 1. Let |scriptURL| be the result of parsing the target IRI of the Link header. 1. Let |scopeURL| be null. @@ -1573,12 +1648,12 @@ Markup Shorthands: css no, markdown yes 1. If |promise| rejected, queue a task to fire an event named error at the <{link}> element. 1. If |promise| resolved, queue a task to fire an event named load at the <{link}> element. - The serviceworker link element *must not* delay the load event of the element's node document. + The serviceworker link element *must not* delay the load event of the element's node document.
A resource being loaded with the following response header: -
+      
         Link: </js/sw.js>; rel="serviceworker"; scope="/"
       
@@ -1616,7 +1691,7 @@ Markup Shorthands: css no, markdown yes

Caches

- To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An origin can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across origins, and they are completely isolated from the browser's HTTP cache. + To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An origin can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across origins, and they are completely isolated from the browser's HTTP cache.

Constructs

@@ -1627,15 +1702,15 @@ Markup Shorthands: css no, markdown yes A request to response map is a List of fetching records. - A name to cache map is a List of the Record {\[[key]], \[[value]]} where \[[key]] is a string that represents a name of the {{Cache}} object and \[[value]] is a {{Cache}} object. + A name to cache map is an ordered map where the keys are strings that represents a name of the {{Cache}} object, and the values are {{Cache}} objects. - Each origin has an associated name to cache map. + Each origin has an associated name to cache map.

Understanding Cache Lifetimes

- The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the service worker script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the service worker that can safely operate on. + The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the service worker script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the service worker that can safely operate on.
@@ -1717,10 +1792,10 @@ Markup Shorthands: css no, markdown yes 1. Let |r| be null. 1. If the optional argument |request| is not omitted, then: 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.|ignoreMethod| is false, return a promise resolved with an empty array. + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with an empty array. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: 1. Let |responseArray| be an empty array. @@ -1733,7 +1808,7 @@ Markup Shorthands: css no, markdown yes 1. Let |entries| be the result of running Query Cache algorithm passing a {{Request}} object associated with |r| and |options| as the arguments. 1. For each |entry| of |entries|: 1. Let |response| be null. - 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, set |response| to a copy of |incumbentRecord|.\[[value]]. + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record in request to response map is not null, set |response| to a copy of |incumbentRecord|.\[[value]]. 1. Else, set |response| to a copy of |entry|[1]. 1. Add |response| to |responseArray|. 1. Resolve |promise| with |responseArray|. @@ -1758,18 +1833,18 @@ Markup Shorthands: css no, markdown yes 1. Let |responsePromiseArray| be an empty array. 1. Let |requestArray| be an empty array. 1. For each |request| whose type is {{Request}} in |requests|: - 1. Let |r| be |request|'s request. + 1. Let |r| be |request|'s request. 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. 1. For each |request| in |requests|: - 1. Let |r| be the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |r| be the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. If |r|'s url's scheme is not one of "http" and "https", then: - 1. Terminate all the ongoing fetches initiated by |requests| with reason *fatal*. + 1. Terminate service worker all the ongoing fetches initiated by |requests| with reason *fatal*. 1. Break the loop. 1. Set |r|'s initiator to "fetch" and destination to "subresource". 1. Add a {{Request}} object associated with |r| to |requestArray|. 1. Let |responsePromise| be a new promise. 1. Run the following substeps in parallel: - * Fetch |r|. + * Fetch |r|. * To process response for |response|, run these substeps: 1. If |response|'s type is "error", or |response|'s status is not an ok status, reject |responsePromise| with a TypeError. @@ -1784,8 +1859,8 @@ Markup Shorthands: css no, markdown yes Note: This step ensures that the promise for this fetch resolves as soon as the response's headers become available. - * To process response body for |response|, do nothing. - * To process response end-of-file for |response|, do nothing. + * To process response for |response|, do nothing. + * To process response done for |response|, do nothing. 1. Add |responsePromise| to |responsePromiseArray|. 1. Let |p| be waiting for all of |responsePromiseArray|. 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |responseArray|, performs the following substeps in parallel: @@ -1802,7 +1877,7 @@ Markup Shorthands: css no, markdown yes 1. For each |response| in |responses|: 1. Let |responseBodyPromise| be a new promise. 1. Run the following substeps in parallel: - 1. Wait for either end-of-file to have been pushed to |response|'s associated response |r|'s body or for |r| to have a termination reason. + 1. Wait for either end-of-file to have been pushed to |response|'s associated response |r|'s body or for |r| to have a termination reason. 1. If |r| had a termination reason, then: 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. @@ -1827,20 +1902,20 @@ Markup Shorthands: css no, markdown yes 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. + 1. Set |r| to |request|'s request. 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. If |r|'s url's scheme is not one of "http" and "https", return a promise rejected with a TypeError. - 1. If |response|'s associated response's header list contains a header named `Vary`, then: + 1. If |response|'s associated response's header list contains a header named `Vary`, then: 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. 1. For each |f| in |varyHeaders|: 1. If |f| matches "*", return a promise rejected with a TypeError. 1. If |response| is disturbed or locked, return a promise rejected with a TypeError. - 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated response and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. + 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated response and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. 1. If |response|'s body is non-null, run these substeps: - 1. Let |dummyStream| be an empty ReadableStream object. - 1. Set |response|'s body to a new body whose stream is |dummyStream|. + 1. Let |dummyStream| be an empty {{ReadableStream}} object. + 1. Set |response|'s body to a new body whose stream is |dummyStream|. 1. Let |reader| be the result of getting a reader from |dummyStream|. 1. Read all bytes from |dummyStream| with |reader|. 1. Let |operations| be an empty array. @@ -1851,7 +1926,7 @@ Markup Shorthands: css no, markdown yes 1. Add |o| to |operations|. 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: - 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated response |r|'s body or for |r| to have a termination reason. + 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated response |r|'s body or for |r| to have a termination reason. 1. If |r| had a termination reason, then: 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. @@ -1873,10 +1948,10 @@ Markup Shorthands: css no, markdown yes 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.|ignoreMethod| is false, return a promise resolved with false. + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with false. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |operations| be an empty array. 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "delete". @@ -1903,10 +1978,10 @@ Markup Shorthands: css no, markdown yes 1. Else: 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.|ignoreMethod| is false, resolve |promise| with an empty array. + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, resolve |promise| with an empty array. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing a {{Request}} object that represents |r| and |options| as the arguments. 1. For each |requestResponse| in |requestResponseArray|: 1. Add |requestResponse|[0] to |resultArray|. @@ -1935,7 +2010,7 @@ Markup Shorthands: css no, markdown yes The user agent *must* create a {{CacheStorage}} object when a {{Window}} object or a {{WorkerGlobalScope}} object is created and associate it with that global object. - A {{CacheStorage}} object represents a name to cache map of its associated global object's environment settings object's origin. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously. + A {{CacheStorage}} object represents a name to cache map of its associated global object's environment settings object's origin. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously.

{{CacheStorage/match(request, options)}}

@@ -1944,17 +2019,17 @@ Markup Shorthands: css no, markdown yes 1. If |options|.{{CacheQueryOptions/cacheName}} is present, then: 1. Return a new promise |p| and run the following substeps in parallel: - 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: - 1. If |options|.{{CacheQueryOptions/cacheName}} matches |entry|.\[[key]], then: - 1. Resolve |p| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |entry|.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. For each |cacheName| → |cache| of name to cache map: + 1. If |options|.{{CacheQueryOptions/cacheName}} matches |cacheName|, then: + 1. Resolve |p| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache| as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) 1. Abort these steps. 1. Resolve |p| with undefined. 1. Else: 1. Let |p| be a promise resolved with undefined. - 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: + 1. For each cacheName → |cache| of name to cache map: 1. Set |p| to the result of transforming itself with a fulfillment handler that, when called with argument |v|, performs the following substeps in parallel: 1. If |v| is not undefined, return |v|. - 1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |entry|.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache|] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) 1. Return |p|.
@@ -1963,9 +2038,9 @@ Markup Shorthands: css no, markdown yes has(|cacheName|) method *must* run these steps: - 1. Return a promise |p| resolved with the result of running the following substeps: - 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: - 1. If |cacheName| matches |entry|.\[[key]], then: + 1. Return a promise resolved with the result of running the following substeps: + 1. For each |key| → value of name to cache map: + 1. If |cacheName| matches |key|, then: 1. Return true. 1. Return false.
@@ -1977,12 +2052,12 @@ Markup Shorthands: css no, markdown yes 1. Let |p| be a new promise. 1. Run the following substeps: - 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: - 1. If |cacheName| matches |entry|.\[[key]], then: - 1. Resolve |p| with a new {{Cache}} object which is a copy of |entry|.\[[value]]. + 1. For each |key| → |value| of name to cache map: + 1. If |cacheName| matches |key|, then: + 1. Resolve |p| with a new {{Cache}} object which is a copy of |value|. 1. Abort these steps. 1. Let |cache| be a new {{Cache}} object. - 1. Set a newly-created Record {\[[key]]: |cacheName|, \[[value]]: |cache|} to name to cache map. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. + 1. Set name to cache map[|cacheName|] to |cache|. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. 1. Resolve |p| with |cache|. 1. Return |p|.
@@ -1995,7 +2070,7 @@ Markup Shorthands: css no, markdown yes 1. Let |p| be the result of running the algorithm specified in {{CacheStorage/has(cacheName)}} method with |cacheName| as the argument. 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |cacheExists|, performs the following substeps in parallel: 1. If |cacheExists| is true, then: - 1. Delete a Record {\[[key]], \[[value]]} |entry| from its name to cache map where |cacheName| matches entry.\[[key]]. + 1. Delete a Record {\[[key]], \[[value]]} entry from its name to cache map where |cacheName| matches entry.\[[key]]. 1. Return true. 1. Abort these steps. @@ -2012,11 +2087,8 @@ Markup Shorthands: css no, markdown yes Note: The promise returned from this method resolves with the sequence of keys, cache names in DOMString, in insertion order. - 1. Let |resultArray| be an empty array. - 1. Return a promise |p| resolved with the result of running the following substeps: - 1. For each Record {\[[key]], \[[value]]} |entry| of its name to cache map, in key insertion order: - 1. Add |entry|.\[[key]] to |resultArray|. - 1. Return |resultArray|. + 1. Let |cacheKeys| be the result of getting the keys of name to cache map. + 1. Return |cacheKeys|.
@@ -2027,13 +2099,13 @@ Markup Shorthands: css no, markdown yes

Secure Context

- Service workers *must* execute in secure contexts. Service worker clients *must* also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts. + Service workers *must* execute in secure contexts. < afor="/">Service worker clients *must* also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts.

Content Security Policy

- Whenever a user agent invokes Run Service Worker algorithm with a service worker |serviceWorker|: + Whenever a user agent invokes Run Service Worker algorithm with a service worker |serviceWorker|: * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy HTTP header containing the value |policy|, the user agent *must* enforce |policy| for |serviceWorker|. * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy-Report-Only HTTP header containing the value |policy|, the user agent *must* monitor |policy| for |serviceWorker|. @@ -2049,22 +2121,22 @@ Markup Shorthands: css no, markdown yes *This section is non-normative.* - A Service worker executes in the registering service worker client's origin. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other origins. Therefore, service workers cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that service workers create the opportunity for a bad actor to turn a bad day into a bad eternity. + A Service worker executes in the registering service worker client's origin. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other origins. Therefore, service workers cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that service workers create the opportunity for a bad actor to turn a bad day into a bad eternity.

{{WorkerGlobalScope/importScripts(urls)}}

- When the importScripts(|urls|) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent *must* import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and |urls|, and with the following steps to perform the fetch given the request |request|: + When the importScripts(|urls|) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent *must* import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and |urls|, and with the following steps to perform the fetch given the request |request|: 1. Let |serviceWorker| be |request|'s client's global object's service worker. 1. If |serviceWorker|'s imported scripts updated flag is unset, then: 1. Let |response| be the result of fetching |request|. 1. If |response|'s unsafe response's type is not "error", and |response|'s status is an ok status, then: - 1. Set script resource map[|request|'s url] to |response| + 1. Set script resource map[|request|'s url] to |response| 1. Return |response|. 1. Else: - 1. If script resource map[|url|] exists, return script resource map[|url|]. + 1. If script resource map[|url|] exists, return script resource map[|url|]. 1. Else, return a network error.
@@ -2074,8 +2146,8 @@ Markup Shorthands: css no, markdown yes *This section is non-normative.* - Applications tend to cache items that come from a CDN or other origin. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to fetch many sorts of off-origin resources when appropriate CORS headers are set. - Service workers enable this by allowing {{Cache|Caches}} to fetch and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding responses are basic filtered response, the objects stored are {{Response}} objects whose corresponding responses are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding responses are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases. + Applications tend to cache items that come from a CDN or other origin. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to fetch many sorts of off-origin resources when appropriate CORS headers are set. + Service workers enable this by allowing {{Cache|Caches}} to fetch and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding responses are basic filtered response, the objects stored are {{Response}} objects whose corresponding responses are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding responses are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases.
@@ -2085,33 +2157,26 @@ Markup Shorthands: css no, markdown yes The implementers are encouraged to note: - * Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching fetch event. - * Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with service workers. + * Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching fetch event. + * Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with service workers.

Privacy

- Service workers introduce new persistent storage features including scope to registration map (for service worker registrations and their service workers), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages *should* be cleared when users intend to clear them and *should* maintain and interoperate with existing user controls e.g. purging all existing persistent storages. + Service workers introduce new persistent storage features including scope to registration map (for service worker registrations and their service workers), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages *should* be cleared when users intend to clear them and *should* maintain and interoperate with existing user controls e.g. purging all existing persistent storages.
-
-

Storage Considerations

- - Service workers *should* take a dependency on Quota Management API that extends the ServiceWorkerGlobalScope with the event listeners {{ServiceWorkerGlobalScope/onbeforeevicted}} and {{ServiceWorkerGlobalScope/onevicted}} to detect a storage pressure and give pre-eviction information to the application. - The cache write operations in service workers when failed due to exceeding the granted quota limit *should* throw "{{QuotaExceededError}}" exception. - -

Extensibility

- Service workers are extensible from other specifications. + Service workers are extensible from other specifications.

Define API bound to Service Worker Registration

- Specifications *may* define an API tied to a service worker registration by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it *may* define the specification specific attributes and methods: + Specifications *may* define an API tied to a service worker registration by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it *may* define the specification specific attributes and methods:
       partial interface ServiceWorkerRegistration {
@@ -2151,9 +2216,9 @@ Markup Shorthands: css no, markdown yes
   

Request Functional Event Dispatch

- To request a functional event dispatch to a service worker, specifications *may* invoke Handle Functional Event algorithm with its service worker registration |registration| and the algorithm |callbackSteps| as the arguments. + To request a functional event dispatch to a service worker, specifications *may* invoke Handle Functional Event algorithm with its service worker registration registration and the algorithm |callbackSteps| as the arguments. - Specifications *may* define an algorithm |callbackSteps| where the corresponding functional event can be created and fired with specification specific objects. The algorithm is passed |globalObject| (a {{ServiceWorkerGlobalScope}} object) at which it *may* fire its functional events. This algorithm is called on a task queued by Handle Functional Event algorithm. + Specifications *may* define an algorithm |callbackSteps| where the corresponding functional event can be created and fired with specification specific objects. The algorithm is passed globalObject (a {{ServiceWorkerGlobalScope}} object) at which it *may* fire its functional events. This algorithm is called on a task queued by Handle Functional Event algorithm. Note: See an example hook defined in Notifications API.
@@ -2164,9 +2229,9 @@ Markup Shorthands: css no, markdown yes The following definitions are the user agent's internal data structures used throughout the specification. - A scope to registration map is an ordered map where the keys are scope urls and the values are service worker registrations. + A scope to registration map is an ordered map where the keys are scope URLs and the values are service worker registrations. - A job is an abstraction of one of register, update, and unregister request for a service worker registration. + A job is an abstraction of one of register, update, and unregister request for a service worker registration.
A job has a job type, which is one of *register*, *update*, and *unregister*. @@ -2177,7 +2242,7 @@ Markup Shorthands: css no, markdown yes A job has a worker type ("classic" or "module"). - A job has a client (a service worker client). It is initially null. + A job has a client (a service worker client). It is initially null. A job has a referrer (a URL or null). @@ -2191,35 +2256,35 @@ Markup Shorthands: css no, markdown yes Two jobs are equivalent when their job type is the same and: - * For *register* and *update* jobs, both their scope url and the script url are the same. - * For *unregister* jobs, their scope url is the same. + * For *register* and *update* jobs, both their scope url and the script url are the same. + * For *unregister* jobs, their scope url is the same. - A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue *should* satisfy the general properties of FIFO queue. A user agent *must* maintain a separate job queue for each service worker registration keyed by its scope url. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's scope url. + A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue *should* satisfy the general properties of FIFO queue. A user agent *must* maintain a separate job queue for each service worker registration keyed by its scope url. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's scope url. -
-

Create Job

+
+

Create Job

: Input :: |jobType|, a job type :: |scopeURL|, a URL :: |scriptURL|, a URL :: |promise|, a promise - :: |client|, a service worker client + :: |client|, a service worker client : Output :: |job|, a job 1. Let |job| be a new job. 1. Set |job|'s job type to |jobType|. - 1. Set |job|'s scope url to |scopeURL|. - 1. Set |job|'s script url to |scriptURL|. - 1. Set |job|'s promise to |promise|. + 1. Set |job|'s scope url to |scopeURL|. + 1. Set |job|'s script url to |scriptURL|. + 1. Set |job|'s job promise to |promise|. 1. Set |job|'s client to |client|. 1. If |client| is not null, set |job|'s referrer to |client|'s creation URL. 1. Return |job|.
-
-

Schedule Job

+
+

Schedule Job

: Input :: |job|, a job @@ -2230,12 +2295,12 @@ Markup Shorthands: css no, markdown yes 1. Push |job| to the job queue and invoke Run Job. 1. Else: 1. Let |lastJob| be the element at the back of the job queue. - 1. If |job| is equivalent to |lastJob| and |lastJob|'s promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. + 1. If |job| is equivalent to |lastJob| and |lastJob|'s job promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. 1. Else, push |job| to the job queue.
-
-

Run Job

+
+

Run Job

: Input :: none @@ -2253,8 +2318,8 @@ Markup Shorthands: css no, markdown yes 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel.
-
-

Finish Job

+
+

Finish Job

: Input :: |job|, a job @@ -2266,8 +2331,8 @@ Markup Shorthands: css no, markdown yes 1. If the job queue is not empty, invoke Run Job with the top element of the job queue.
-
-

Resolve Job Promise

+
+

Resolve Job Promise

: Input :: |job|, a job @@ -2275,13 +2340,13 @@ Markup Shorthands: css no, markdown yes : Output :: none - 1. If |job|'s client is not null, queue a task to resolve |job|'s promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |job|'s client is not null, queue a task to resolve |job|'s job promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
-
-

Reject Job Promise

+
+

Reject Job Promise

: Input :: |job|, a job @@ -2289,19 +2354,19 @@ Markup Shorthands: css no, markdown yes : Output :: none - 1. If |job|'s client is not null, queue a task to reject |job|'s promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |job|'s client is not null, queue a task to reject |job|'s job promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
-
-

Start Register

+
+

Start Register

: Input :: |scopeURL|, a URL or failure or null :: |scriptURL|, a URL or failure :: |promise|, a promise - :: |client|, a service worker client + :: |client|, a service worker client :: |referrer|, a URL :: |workerType|, a worker type : Output @@ -2323,58 +2388,58 @@ Markup Shorthands: css no, markdown yes 1. Invoke [[#schedule-job-algorithm]] with |job|.
-
-

Register

+
+

Register

: Input :: |job|, a job : Output - :: |promise|, a promise + :: none - 1. If the result of running Is origin potentially trustworthy with the origin of |job|'s script url as the argument is Not Trusted, then: + 1. If the result of running potentially trustworthy origin with the origin of |job|'s script url as the argument is Not Trusted, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. - 1. If the origin of |job|'s script url is not |job|'s referrer's origin, then: + 1. If the origin of |job|'s script url is not |job|'s referrer's origin, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. - 1. If the origin of |job|'s scope url is not |job|'s referrer's origin, then: + 1. If the origin of |job|'s scope url is not |job|'s referrer's origin, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 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 scope url as the argument. + 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s 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 and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: + 1. If |newestWorker| is not null and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Invoke Finish Job with |job| and abort these steps. 1. Else: - 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. + 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. 1. Invoke Update algorithm passing |job| as the argument.
-
-

Update

+
+

Update

: Input :: |job|, a job : Output :: none - 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s scope url as the argument. + 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s scope url as the argument. 1. If |registration| is null or |registration|'s uninstalling flag is set, then: 1. Invoke Reject Job Promise with |job| and a 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. - 1. If |job|'s job type is *update*, and |newestWorker|'s script url does not equal |job|'s script url with the *exclude fragments flag* set, then: + 1. If |job|'s job type is *update*, and |newestWorker|'s script url does not equal |job|'s script url with the *exclude fragments flag* set, then: 1. Invoke Reject Job Promise with |job| and a TypeError. 1. Invoke Finish Job with |job| and abort these steps. 1. Let |httpsState| be "none". 1. Let |referrerPolicy| be the empty string. 1. Switching on |job|'s worker type, run these substeps with the following options: : *"classic"* - :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". + :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". : *"module"* - :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. + :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. To perform the fetch given |request|, run the following steps if the is top-level flag is set: @@ -2382,30 +2447,30 @@ Markup Shorthands: css no, markdown yes Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. - 1. Set |request|'s skip service worker flag and |request|'s redirect mode to "error". + 1. Set |request|'s skip-service-worker flag and |request|'s redirect mode to "error". 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. - 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. + 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Asynchronously complete these steps with a network error. - 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. + 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. 1. Set |httpsState| to |response|'s HTTPS state. - 1. Set |referrerPolicy| to the result of parsing the `Referrer-Policy` header of |response|. + 1. Set |referrerPolicy| to the result of parse a referrer policy from a Referrer-Policy header of |response|. 1. If |serviceWorkerAllowed| is failure, then: 1. Asynchronously complete these steps with a network error. - 1. Let |scopeURL| be |registration|'s scope url. + 1. Let |scopeURL| be |registration|'s scope url. 1. Let |maxScopeString| be null. 1. If |serviceWorkerAllowed| is null, then: - 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". + 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". 1. Else: - 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. + 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s path (including empty strings), separated from each other by "/". 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s path (including empty strings), separated from each other by "/". 1. If |scopeString| starts with |maxScopeString|, do nothing. @@ -2429,15 +2494,15 @@ Markup Shorthands: css no, markdown yes Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. - 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: + 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Invoke Finish Job with |job| and abort these steps. 1. Else: - 1. Let |worker| be a new service worker. + 1. Let |worker| be a new service worker. 1. Generate a unique opaque string and set |worker|'s id to the value. - 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. + 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. 1. Set |worker|'s script resource's HTTPS state to |httpsState|. - 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. + 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. 1. Invoke Run Service Worker algorithm with |worker| as the argument. 1. If an uncaught runtime script error occurs during the above step, then: 1. Invoke Reject Job Promise with |job| and a TypeError. @@ -2446,13 +2511,13 @@ Markup Shorthands: css no, markdown yes 1. Invoke Install algorithm with |job|, |worker|, and |registration| as its arguments.
-
-

Soft Update

+
+

Soft Update

The user agent *may* call this as often as it likes to check for updates. : Input - :: |registration|, a service worker registration + :: |registration|, a service worker registration :: *force bypass cache flag*, an optional flag unset by default Note: Implementers may use the *force bypass cache flag* to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs. @@ -2462,19 +2527,19 @@ Markup Shorthands: css no, markdown yes 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. 1. If |newestWorker| is null, abort these steps. - 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, null, and null. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, null, and null. 1. Set |job|'s worker type to |newestWorker|'s type. 1. Set |job|'s force bypass cache flag if its *force bypass cache flag* is set. 1. Invoke Schedule Job with |job|.
-
-

Install

+
+

Install

: Input :: |job|, a job - :: |worker|, a service worker - :: |registration|, a service worker registration + :: |worker|, a service worker + :: |registration|, a service worker registration : Output :: none @@ -2483,19 +2548,19 @@ Markup Shorthands: css no, markdown yes 1. Let |redundantWorker| be null. 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. Assert: |job|'s promise is not null. + 1. Assert: |job|'s job promise is not null. 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 scope url and all the service workers whose containing service worker registration is |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 scope url and all the service workers whose containing service worker registration is |registration|. 1. Let |installingWorker| be |registration|'s installing worker. 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. 1. Queue a task |task| to run the following substeps: 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type install, which does not bubble and is not cancelable. - 1. Dispatch |e| at |installingWorker|'s environment settings object's global object |globalObject|. + 1. Dispatch |e| at |installingWorker|'s environment settings object's global object. 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: 1. Wait until |e|'s extensions allowed flag is unset. 1. If 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 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. @@ -2508,7 +2573,7 @@ Markup Shorthands: css no, markdown yes 1. Set |registration|'s installing worker's imported scripts updated flag. 1. If |registration|'s waiting worker is not null, then: 1. Set |redundantWorker| to |registration|'s waiting worker. - 1. Terminate |redundantWorker|. + 1. Terminate service worker |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. @@ -2519,15 +2584,15 @@ Markup Shorthands: css no, markdown yes 1. Invoke Finish Job with |job| and abort these steps. 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. 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 |waitingWorker| is not null and |waitingWorker|'s skip waiting flag is not set, invoke Activate algorithm with |registration| as its argument.
-
-

Activate

+
+

Activate

: Input - :: |registration|, a service worker registration + :: |registration|, a service worker registration : Output :: None @@ -2536,7 +2601,7 @@ Markup Shorthands: css no, markdown yes 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. Terminate service worker |redundantWorker|. 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. @@ -2544,13 +2609,13 @@ Markup Shorthands: css no, markdown yes 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. - 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: + 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: 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 global object from its application cache, if it has one. Note: Resources will now use the service worker registration instead of the existing application cache. - 1. For each service worker client |client| who is using |registration|: + 1. 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. @@ -2559,16 +2624,16 @@ Markup Shorthands: css no, markdown yes 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type activate, which does not bubble and is not cancelable. 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. - 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 |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.
-
-

Run Service Worker

+
+

Run Service Worker

: Input - :: |serviceWorker|, a service worker + :: |serviceWorker|, a service worker : Output :: None @@ -2576,9 +2641,9 @@ Markup Shorthands: css no, markdown yes 1. Assert: |script| is not null. 1. If |serviceWorker| is already running, abort these steps. 1. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context. - 1. Call the JavaScript InitializeHostDefinedRealm() abstract operation with the following customizations: + 1. Call the JavaScript InitializeHostDefinedRealm abstract operation with the following customizations: * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. - * Let |realmExecutionContext| be the created JavaScript execution context. + * Let |realmExecutionContext| be the created execution context. 1. Let |workerEventLoop| be a newly created event loop. 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: @@ -2593,17 +2658,17 @@ Markup Shorthands: css no, markdown yes : The API URL character encoding :: Return UTF-8. : The API base URL - :: Return |serviceWorker|'s script url. - : The origin - :: Return its registering service worker client's origin. + :: Return |serviceWorker|'s script url. + : The origin + :: Return its registering service worker client's origin. : The creation URL :: Return |workerGlobalScope|'s url. : The HTTPS state :: Return |workerGlobalScope|'s HTTPS state. - 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. + 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. 1. Set |workerGlobalScope|'s HTTPS state to |serviceWorker|'s script resource's HTTPS state. - 1. Set |workerGlobalScope|'s referrer policy to |serviceWorker|'s script resource's referrer policy. + 1. Set |workerGlobalScope|'s referrer policy to |serviceWorker|'s script resource's referrer policy. 1. Set |workerGlobalScope|'s type to |serviceWorker|'s type. 1. Create a new {{WorkerLocation}} object and associate it with |workerGlobalScope|. 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. @@ -2621,11 +2686,11 @@ Markup Shorthands: css no, markdown yes 1. Empty |workerGlobalScope|'s list of active timers.
-
-

Terminate Service Worker

+
+

Terminate Service Worker

: Input - :: |serviceWorker|, a service worker + :: |serviceWorker|, a service worker : Output :: None @@ -2639,15 +2704,15 @@ Markup Shorthands: css no, markdown yes 1. Abort the script currently running in |serviceWorker|.
-
-

Handle Fetch

+
+

Handle Fetch

- The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context. + The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context. : Input - :: |request|, a request + :: |request|, a request : Output - :: |response|, a response + :: |response|, a response
1. Let |handleFetchFailed| be false. @@ -2655,7 +2720,7 @@ Markup Shorthands: css no, markdown yes 1. Let |eventCanceled| be false. 1. Let |r| be a new {{Request}} object associated with |request|. 1. Let |headersObject| be |r|'s {{Request/headers}} attribute value. - 1. Set |headersObject|'s guard to *immutable*. + 1. Set |headersObject|'s guard to *immutable*. 1. Let |response| be null. 1. Let |registration| be null. 1. Let |client| be |request|'s client. @@ -2676,7 +2741,7 @@ Markup Shorthands: css no, markdown yes 1. If |registration| is null or |registration|'s active worker is null, return null. 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. - Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. + Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. 1. Else if |request| is a subresource request, then: 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. @@ -2692,7 +2757,7 @@ Markup Shorthands: css no, markdown yes 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. + 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. @@ -2706,7 +2771,7 @@ Markup Shorthands: css no, markdown yes 1. Else, set |response| to |e|'s potential response. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. @@ -2722,20 +2787,22 @@ Markup Shorthands: css no, markdown yes 1. Else: 1. Return |response| and continue running these steps in parallel. 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. +
-
-

Handle Foreign Fetch

+
+

Handle Foreign Fetch

- The [[#on-foreign-fetch-request-algorithm]] algorithm is the entry point for the fetch handling handed to the service worker context to handle foreign fetch requests. + The [[#on-foreign-fetch-request-algorithm]] algorithm is the entry point for the fetch handling handed to the service worker context to handle foreign fetch requests. : Input - :: |request|, a request + :: |request|, a request : Output - :: |response|, a response + :: |response|, a response
+ 1. ok 1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. 1. Let |eventCanceled| be false. @@ -2748,17 +2815,16 @@ Markup Shorthands: css no, markdown yes 1. If |activeWorker| is null, return null. 1. If |activeWorker|'s state is *activating*, then: 1. Wait for |activeWorker|'s state to become *activated*. - 1. If |activeWorker|'s origin is the same as |request|'s origin, return null. + 1. If |activeWorker|'s origin is the same as |request|'s origin, return null. 1. Let |originMatches| be false. 1. If |activeWorker|'s list of foreign fetch origins is empty, set |originMatches| to true. 1. For each |origin| in |activeWorker|'s list of foreign fetch origins: 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. - 1. If |originMatches| is false, return null. 1. Let |r| be a new {{Request}} object associated with |request|. 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. + 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. @@ -2781,7 +2847,7 @@ Markup Shorthands: css no, markdown yes 1. Set |response| to a CORS filtered response of |internalResponse|. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. @@ -2795,11 +2861,12 @@ Markup Shorthands: css no, markdown yes 1. Return a network error. 1. Else: 1. Return |response|. +
-
-

Handle Functional Event

+
+

Handle Functional Event

: Input :: |registration|, a service worker registration @@ -2827,33 +2894,33 @@ Markup Shorthands: css no, markdown yes 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|.
-
-

Handle Service Worker Client Unload

+
+

Handle Service Worker Client Unload

- The user agent *must* run these steps when a service worker client unloads by unloading, being killed, or terminating. + The user agent *must* run these steps when a service worker client unloads by unloading, being killed, or terminating. : Input - :: |client|, a service worker client + :: |client|, a service worker client : Output :: None 1. Run the following steps atomically. - 1. Let |registration| be the service worker registration used by |client|. + 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 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.
-
-

Handle User Agent Shutdown

+
+

Handle User Agent Shutdown

: Input :: None : Output :: None - 1. For each |scope| → |registration| of scope to registration map: + 1. For each scope → |registration| of scope to registration map: 1. If |registration|'s installing worker |installingWorker| is not null, then: 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. 1. Else, set |registration|'s installing worker to null. @@ -2861,50 +2928,50 @@ Markup Shorthands: css no, markdown yes 1. Invoke Activate with |registration|.
-
-

Unregister

+
+

Unregister

: Input :: |job|, a job : Output :: none - 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: + 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. - 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s scope url as the argument. + 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s scope url as the argument. 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. Invoke Resolve Job Promise with |job| and true. - 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. + 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. 1. Invoke Finish Job with |job|.
-
-

Set Registration

+
+

Set Registration

: Input :: |scope|, a URL : Output - :: |registration|, a service worker registration + :: |registration|, a service worker registration 1. Run the following steps atomically. 1. Let |scopeString| be serialized |scope| with the *exclude fragment flag* set. - 1. Let |registration| be a new service worker registration whose scope url is set to |scope|. - 1. Set scope to registration map[|scopeString|] to |registration|. + 1. Let |registration| be a new service worker registration whose scope url is set to |scope|. + 1. Set scope to registration map[|scopeString|] to |registration|. 1. Return |registration|.
-
-

Clear Registration

+
+

Clear Registration

: Input - :: |registration|, a service worker registration + :: |registration|, a service worker registration : Output :: None @@ -2912,33 +2979,33 @@ Markup Shorthands: css no, markdown yes 1. Let |redundantWorker| be null. 1. If |registration|'s installing worker is not null, then: 1. Set |redundantWorker| to |registration|'s installing worker. - 1. Terminate |redundantWorker|. + 1. Terminate service worker |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. Terminate service worker |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. Terminate service worker |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 scope url with the *exclude fragment flag* set. - 1. Remove scope to registration map[scopeString]. + 1. Let |scopeString| be serialized |registration|'s scope url with the *exclude fragment flag* set. + 1. Remove scope to registration map[|scopeString|].
-
-

Update Registration State

+
+

Update Registration State

: Input - :: |registration|, a service worker registration + :: |registration|, a service worker registration :: |target|, a string (one of "installing", "waiting", and "active") - :: |source|, a service worker or null + :: |source|, a service worker or null : Output :: None @@ -2959,12 +3026,12 @@ Markup Shorthands: css no, markdown yes The task *must* use |registrationObject|'s relevant settings object's responsible event loop and the DOM manipulation task source.
-
-

Update Worker State

+
+

Update Worker State

: Input - :: |worker|, a service worker - :: |state|, a service worker's state + :: |worker|, a service worker + :: |state|, a service worker's state : Output :: None @@ -2976,58 +3043,59 @@ Markup Shorthands: css no, markdown yes : *installing* :: "installing" - Note: The service worker in this state is considered an installing worker. During this state, event.waitUntil(|f|) 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. + 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" - Note: The service worker in this state is considered a waiting worker. + 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, event.waitUntil(|f|) 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*. + 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. + 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. + 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

+
+

Notify Controller Change

: Input - :: |client|, a service worker client + :: |client|, a service worker client : Output :: None 1. Assert: |client| is not null. 1. If |client| is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object |client| is associated with. + The task *must* use |client|'s responsible event loop and the DOM manipulation task source.
-
-

Match Service Worker Registration

+
+

Match Service Worker Registration

: Input :: |clientURL|, a URL : Output - :: |registration|, a service worker registration + :: |registration|, a service worker registration 1. Run the following steps atomically. 1. Let |clientURLString| be serialized |clientURL|. 1. Let |matchingScope| be the empty string. - 1. Let |allScopes| be the result of getting the keys from scope to registration map. + 1. Let |allScopes| be the result of getting the keys from scope to registration map. 1. Set |matchingScope| to the longest value in |allScopes| which the value of |clientURLString| starts with, if it exists. Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). @@ -3039,13 +3107,13 @@ Markup Shorthands: css no, markdown yes 1. Return |registration|.
-
-

Match Service Worker for Foreign Fetch

+
+

Match Service Worker for Foreign Fetch

: Input :: |requestURL|, a URL : Output - :: |worker|, a service worker + :: |worker|, a service worker 1. Run the following steps atomically. 1. Let |registration| be the result of running the [[#scope-match-algorithm]] algorithm passing |requestURL| as the argument. @@ -3055,34 +3123,34 @@ Markup Shorthands: css no, markdown yes 1. Let |requestURLString| be the serialized |requestURL|. 1. For each URL |scope| in |worker|'s list of foreign fetch scopes: 1. Let |scopeString| be the serialized |scope|. - 1. If |requestString| starts with |scopeString| return |worker|. + 1. If |requestURLString| starts with |scopeString| return |worker|. 1. Return null.
-
-

Get Registration

+
+

Get Registration

: Input :: |scope|, a URL : Output - :: |registration|, a service worker registration + :: |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 serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be null. - 1. For each |key| → |value| of scope to registration map: + 1. For each |key| → |value| of scope to registration map: 1. If |scopeString| matches |key|, set |registration| to |value|. 1. Return |registration|.
-
-

Get Newest Worker

+
+

Get Newest Worker

: Input - :: |registration|, a service worker registration + :: |registration|, a service worker registration : Output - :: |worker|, a service worker + :: |newestWorker|, a service worker 1. Run the following steps atomically. 1. Let |newestWorker| be null. @@ -3092,11 +3160,11 @@ Markup Shorthands: css no, markdown yes 1. Return |newestWorker|.
-
-

Create Client

+
+

Create Client

: Input - :: |client|, a service worker client + :: |client|, a service worker client : Output :: |clientObject|, a {{Client}} object @@ -3106,11 +3174,11 @@ Markup Shorthands: css no, markdown yes 1. Return |clientObject|.
-
-

Create Window Client

+
+

Create Window Client

: Input - :: |client|, a service worker client + :: |client|, a service worker client :: |visibilityState|, a string :: |focusState|, a boolean :: |ancestorOrigins|, an array @@ -3125,8 +3193,8 @@ Markup Shorthands: css no, markdown yes 1. Return |windowClient|.
-
-

Query Cache

+
+

Query Cache

: Input :: |request|, a {{Request}} object @@ -3138,13 +3206,13 @@ Markup Shorthands: css no, markdown yes 1. Let |requestArray| be an empty array. 1. Let |responseArray| be an empty array. 1. Let |resultArray| be an empty array. - 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.|method| is not `GET`, return |resultArray|. + 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.method is not `GET`, return |resultArray|. 1. Let |cachedURL| and |requestURL| be null. 1. If the optional argument |targetStorage| is omitted, then: 1. For each fetching record |entry| of its request to response map, in key insertion order: - 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. - 1. If |options|.|ignoreSearch| is true, then: + 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. + 1. If |options|.ignoreSearch is true, then: 1. Set |cachedURL|'s query to the empty string. 1. Set |requestURL|'s query to the empty string. 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: @@ -3152,8 +3220,8 @@ Markup Shorthands: css no, markdown yes 1. Add a copy of |entry|.\[[value]] to |responseArray|. 1. Else: 1. For each |record| in |targetStorage|: - 1. Set |cachedURL| to |record|[0]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. + 1. Set |cachedURL| to |record|[0]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: 1. Set |cachedURL|'s query to the empty string. 1. Set |requestURL|'s query to the empty string. @@ -3162,7 +3230,7 @@ Markup Shorthands: css no, markdown yes 1. Add |record|[1] to |responseArray|. 1. For each |cachedResponse| in |responseArray| with the index |index|: 1. Let |cachedRequest| be the |index|th element in |requestArray|. - 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: + 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. 1. Continue to the next iteration of the loop. 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. @@ -3175,21 +3243,21 @@ Markup Shorthands: css no, markdown yes 1. Return |resultArray|.
-
-

Batch Cache Operations

+
+

Batch Cache Operations

: Input :: |operations|, an array of {{CacheBatchOperation}} dictionary objects : Output :: |promise|, a promise resolves with an array of {{Response}} objects. - 1. Let |p| be a promise resolved with no value. - 1. Return the result of transforming |p| with a fulfillment handler that performs the following substeps in parallel: + 1. Let |promise| be a promise resolved with no value. + 1. Return the result of transforming |promise| with a fulfillment handler that performs the following substeps in parallel: 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. 1. Let |addedRecords| be an empty array. 1. Try running the following substeps atomically: 1. Let |resultArray| be an empty array. - 1. For each |operation| in |operations| with the index |index|: + 1. For each |operation| in |operations|: 1. If |operation|.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError. 1. If |operation|.{{CacheBatchOperation/type}} matches "delete" and |operation|.{{CacheBatchOperation/response}} is not null, throw a TypeError. 1. If the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}, |operation|.{{CacheBatchOperation/options}}, and |addedRecords| as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception. @@ -3198,7 +3266,7 @@ Markup Shorthands: css no, markdown yes 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. - 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. + 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. 1. If |r|'s method is not `GET`, throw a TypeError. 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. @@ -3213,8 +3281,8 @@ Markup Shorthands: css no, markdown yes Note: The cache commit is allowed as long as the response's headers are available. 1. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception. - 1. Add an array [|operation|.|request|, |operation|.|response|] to |addedRecords|. - 1. Add |operation|.|response| to |resultArray|. + 1. Add an array [|operation|.request, |operation|.response] to |addedRecords|. + 1. Add |operation|.response to |resultArray|. 1. Return |resultArray|. 1. And then, if an exception was thrown, then: 1. Set the context object's request to response map to |itemsCopy|. @@ -3228,10 +3296,10 @@ Markup Shorthands: css no, markdown yes

Service Worker Script Request

- An HTTP request to fetch a service worker's script resource will include the following header: + An HTTP request to fetch a service worker's script resource will include the following header: : `Service-Worker` - :: Indicates this request is a service worker's script resource request. + :: Indicates this request is a service worker's script resource request. Note: This header helps administrators log the requests and detect threats.
@@ -3239,10 +3307,10 @@ Markup Shorthands: css no, markdown yes

Service Worker Script Response

- An HTTP response to a service worker's script resource request can include the following header: + An HTTP response to a service worker's script resource request can include the following header: : `Service-Worker-Allowed` - :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. + :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. Note: The value is a URL. If a relative URL is given, it is parsed against the script's URL. @@ -3298,7 +3366,7 @@ Markup Shorthands: css no, markdown yes

Syntax

- ABNF for the values of the headers used by the service worker's script resource requests and responses: + ABNF for the values of the headers used by the service worker's script resource requests and responses:
       Service-Worker = %x73.63.72.69.70.74 ; "script", case-sensitive

From 91e85aaa8b2bd6e54f1c484399056a1d1c0ba462 Mon Sep 17 00:00:00 2001
From: Jake Archibald 
Date: Thu, 24 Nov 2016 17:49:54 +0000
Subject: [PATCH 07/17] Reindenting EVERYTHING

---
 docs/index.bs | 1546 ++++++++++++++++++++++++-------------------------
 1 file changed, 772 insertions(+), 774 deletions(-)

diff --git a/docs/index.bs b/docs/index.bs
index df602037..9e891fa9 100644
--- a/docs/index.bs
+++ b/docs/index.bs
@@ -226,13 +226,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
   

Selection and Use

- A service worker client independently selects and uses a service worker registration for its own loading and its subresources. The selection of a service worker registration, upon a non-subresource request, is a process of either matching a service worker registration from scope to registration map or inheriting an existing service worker registration from its parent or owner context depending on the request's url. + A service worker client independently selects and uses a service worker registration for its own loading and its subresources. The selection of a service worker registration, upon a non-subresource request, is a process of either matching a service worker registration from scope to registration map or inheriting an existing service worker registration from its parent or owner context depending on the request's url. - When the request's url is not local, a service worker client matches a service worker registration from scope to registration map. That is, the service worker client attempts to consult a service worker registration whose scope url matches its creation URL. + When the request's url is not local, a service worker client matches a service worker registration from scope to registration map. That is, the service worker client attempts to consult a service worker registration whose scope url matches its creation URL. When the request's url is local, if the service worker client's responsible browsing context is a nested browsing context or the service worker client is a worker client, the service worker client inherits the service worker registration from its parent browsing context's environment or one of the worker's Documents' environment, respectively, if it exists. - If the selection was successful, the selected service worker registration's active worker starts to control the service worker client. Otherwise, the flow returns to fetch where it falls back to the default behavior. When a service worker client is controlled by an active worker, it is considered that the service worker client is using the active worker's containing service worker registration. + If the selection was successful, the selected service worker registration's active worker starts to control the service worker client. Otherwise, the flow returns to fetch where it falls back to the default behavior. When a service worker client is controlled by an active worker, it is considered that the service worker client is using the active worker's containing service worker registration.
@@ -241,11 +241,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The following additional task sources are used by service workers. : The handle fetch task source - :: This task source is used for dispatching fetch events to service workers. + :: This task source is used for dispatching fetch events to service workers. : The handle functional event task source :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. - Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events. For instance, a user agent may use a different task source for task events from other task sources. + Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events.
@@ -313,7 +313,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The scriptURL attribute *must* return the service worker's serialized script url.
- For example, consider a document created by a navigation to https://example.com/app.html which matches via the following registration call which has been previously executed: + For example, consider a document created by a navigation to https://example.com/app.html which matches via the following registration call which has been previously executed:
           // Script on the page https://example.com/app.html
@@ -345,14 +345,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
         1. Let |clonedMessage| be |cloneRecord|.\[[Clone]].
         1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order.
         1. Queue a task that runs the following steps:
-          1. Create an event |e| that uses the {{ExtendableMessageEvent}} interface, with the event type {{message!!event}}, which does not bubble and is not cancelable.
-          1. Let the {{ExtendableMessageEvent/data}} attribute of |e| be initialized to |clonedMessage|.
-          1. Let the {{ExtendableMessageEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |incumbentSettings|'s origin.
-          1. If |incumbentGlobal| is a {{ServiceWorkerGlobalScope}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{ServiceWorker}} object that represents |incumbentGlobal|'s service worker.
-          1. Else if |incumbentGlobal| is a {{Window}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{WindowClient}} object that represents |incumbentGlobal|'s browsing context.
-          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. Create an event |e| that uses the {{ExtendableMessageEvent}} interface, with the event type {{message!!event}}, which does not bubble and is not cancelable.
+            1. Let the {{ExtendableMessageEvent/data}} attribute of |e| be initialized to |clonedMessage|.
+            1. Let the {{ExtendableMessageEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |incumbentSettings|'s origin.
+            1. If |incumbentGlobal| is a {{ServiceWorkerGlobalScope}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{ServiceWorker}} object that represents |incumbentGlobal|'s service worker.
+            1. Else if |incumbentGlobal| is a {{Window}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{WindowClient}} object that represents |incumbentGlobal|'s browsing context.
+            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|.
 
             The task *must* use the DOM manipulation task source.
     
@@ -454,7 +454,7 @@ 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 < afor="/">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 navigations. unregister() method *must* run these steps: @@ -562,16 +562,16 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |registration| be null. 1. Let |clientURL| be |client|'s creation URL. 1. Run the following substeps in parallel: - 1. *CheckRegistration*: If the result of running Match Service Worker Registration algorithm with |clientURL| as its argument is not null, then: - 1. Set |registration| to the result value. - 1. Else: - 1. Wait until scope to registration map has a new entry. - 1. Jump to the step labeled *CheckRegistration*. - 1. If |registration|'s active worker is null, wait until |registration|'s active worker changes. + 1. *CheckRegistration*: If the result of running Match Service Worker Registration algorithm with |clientURL| as its argument is not null, then: + 1. Set |registration| to the result value. + 1. Else: + 1. Wait until scope to registration map has a new entry. + 1. Jump to the step labeled *CheckRegistration*. + 1. If |registration|'s active worker is null, wait until |registration|'s active worker changes. - Note: Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm. + Note: Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm. - 1. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Return context object's ready promise. Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker. @@ -604,11 +604,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the origin of |clientURL| is not |client|'s origin, return a |promise| rejected with a "{{SecurityError}}" exception. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. Let |registration| be the result of running Match Service Worker Registration algorithm with |clientURL| as its argument. - 1. If |registration| is not null, then: - 1. Resolve |promise| with the {{ServiceWorkerRegistration}} object which represents |registration|. - 1. Else: - 1. Resolve |promise| with undefined. + 1. Let |registration| be the result of running Match Service Worker Registration algorithm with |clientURL| as its argument. + 1. If |registration| is not null, then: + 1. Resolve |promise| with the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Else: + 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -620,10 +620,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |client| be the context object's service worker client. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. Let |array| be an empty array. - 1. For each |key| → |value| of scope to registration map: - 1. If the origin of the result of parsing |key| is the same as |client|'s origin, and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. - 1. Resolve |promise| with |array|. + 1. Let |array| be an empty array. + 1. For each |key| → |value| of scope to registration map: + 1. If the origin of the result of parsing |key| is the same as |client|'s origin, and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. + 1. Resolve |promise| with |array|. 1. Return |promise|.
@@ -812,10 +812,10 @@ 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. If service worker's state is *installed*, then: - 1. Run Activate algorithm passing service worker's registration as the argument. - 1. Resolve |promise| with undefined. + 1. Set service worker's skip waiting flag. + 1. If service worker's state is *installed*, then: + 1. Run Activate algorithm passing service worker's registration as the argument. + 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -920,12 +920,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |clonedMessage| be |cloneRecord|.\[[Clone]]. 1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order. 1. Add a task that runs the following steps to |destination|'s client message queue: - 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type message, which does not bubble and is not cancelable. - 1. Let the data attribute of |e| be initialized to |clonedMessage|. - 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s origin. - 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the service worker associated with |sourceSettings|'s global object. - 1. Let the ports attribute of |e| be initialized to |newPorts|. - 1. Dispatch |e| at |destination|. + 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type message, which does not bubble and is not cancelable. + 1. Let the data attribute of |e| be initialized to |clonedMessage|. + 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s origin. + 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the service worker associated with |sourceSettings|'s global object. + 1. Let the ports attribute of |e| be initialized to |newPorts|. + 1. Dispatch |e| at |destination|.
@@ -954,19 +954,19 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. - 1. Let |visibilityState| be null. - 1. Let |focusState| be false. - 1. Let |ancestorOrigins| be the empty array. - 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: - 1. Run the focusing steps with |browsingContext|. - 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. - 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. - 1. Wait for |task| to have executed. - 1. Let |windowClient| be the result of running Create Window Client algorithm with the context object's associated service worker client, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. - 1. If |windowClient|'s focus state is true, resolve |promise| with |windowClient|. - 1. Else, reject |promise| with a TypeError. + 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: + 1. Run the focusing steps with |browsingContext|. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed. + 1. Let |windowClient| be the result of running Create Window Client algorithm with the context object's associated service worker client, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. If |windowClient|'s focus state is true, resolve |promise| with |windowClient|. + 1. Else, reject |promise| with a TypeError. 1. Return |promise|.
@@ -981,25 +981,25 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the context object's associated service worker client's active service worker is not the context object's relevant global object's service worker, return a promise rejected with a TypeError. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. - 1. If |browsingContext| has discarded its {{Document}}, reject |promise| with a TypeError and abort these steps. - 1. Let |navigateFailed| to false. - 1. Let |visibilityState| be null. - 1. Let |focusState| be false. - 1. Let |ancestorOrigins| be the empty array. - 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: - 1. *HandleNavigate*: Navigate |browsingContext| to |url| with exceptions enabled. The source browsing context must be |browsingContext|. - 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |navigateFailed| to true. - 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. - 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. - 1. Wait for |task| to have executed (including its asynchronous steps). - 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. - 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: - 1. Resolve |promise| with null. - 1. Abort these steps. - 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. - 1. Resolve |promise| with |windowClient|. + 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. + 1. If |browsingContext| has discarded its {{Document}}, reject |promise| with a TypeError and abort these steps. + 1. Let |navigateFailed| to false. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: + 1. *HandleNavigate*: Navigate |browsingContext| to |url| with exceptions enabled. The source browsing context must be |browsingContext|. + 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |navigateFailed| to true. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed (including its asynchronous steps). + 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. + 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. Resolve |promise| with null. + 1. Abort these steps. + 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |windowClient|. 1. Return |promise|.
@@ -1042,30 +1042,30 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: - 1. If |client|'s id is not |id|, continue to the next iteration of the loop. - 1. If |client| is a type of environment, then: - 1. If |client|’s creation URL is not a potentially trustworthy URL, reject |promise| with a "{{SecurityError}}" exception and abort these steps. - 1. Else: - 1. If |client| is not a secure context, reject |promise| with a "{{SecurityError}}" exception and abort these steps. - 1. If |client| is a type of environment or is a window client, then: - 1. Let |browsingContext| be null. - 1. Let |visibilityState| be null. - 1. Let |focusState| be false. - 1. Let |ancestorOrigins| be the empty array. - 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. - 1. Else, set |browsingContext| to |client|'s global object's browsing context. - 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: - 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. - 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. - 1. Wait for |task| to have executed. - 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. - 1. Resolve |promise| with |windowClient| and abort these steps. - 1. Else: - 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. - 1. Resolve |promise| with |clientObject| and abort these steps. - 1. Resolve |promise| with undefined. + 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: + 1. If |client|'s id is not |id|, continue to the next iteration of the loop. + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, reject |promise| with a "{{SecurityError}}" exception and abort these steps. + 1. Else: + 1. If |client| is not a secure context, reject |promise| with a "{{SecurityError}}" exception and abort these steps. + 1. If |client| is a type of environment or is a window client, then: + 1. Let |browsingContext| be null. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. + 1. Else, set |browsingContext| to |client|'s global object's browsing context. + 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed. + 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |windowClient| and abort these steps. + 1. Else: + 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. + 1. Resolve |promise| with |clientObject| and abort these steps. + 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -1076,48 +1076,48 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |targetClients| be an empty array. - 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: - 1. If |client| is a type of environment, then: - 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. - 1. Else: - 1. If |client| is not a secure context, continue to the next iteration of the loop. - 1. If |options|.{{ClientQueryOptions/includeUncontrolled}} is false, then: - 1. If |client|'s active service worker is not the associated service worker, continue to the next iteration of the loop. - 1. If |options|.{{ClientQueryOptions/includeReserved}} is false, then: - 1. If |client|'s execution ready flag is unset, continue to the next iteration of the loop. - 1. Add |client| to |targetClients|. - 1. Let |matchedClients| be an empty array. - 1. For each service worker client |client| in |targetClients|: - 1. If |options|.{{ClientQueryOptions/type}} is "window" or "all", and |client| is a type of environment or is a window client, then: - 1. Let |browsingContext| be null. - 1. Let |isClientEnumerable| be true. - 1. Let |visibilityState| be the empty string. - 1. Let |focusState| be false. - 1. Let |ancestorOrigins| be the empty array. - 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. - 1. Else, set |browsingContext| to |client|'s global object's browsing context. - 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: - 1. If |browsingContext| has been discarded, set |isClientEnumerable| to false and abort these steps. - 1. If |client| is a window client and |client|'s responsible document is not |browsingContext|'s active document, set |isClientEnumerable| to false and abort these steps. - 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. - 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. - 1. Wait for |task| to have executed. - - Note: Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken. - - 1. If |isClientEnumerable| is true, then: - 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. - 1. Add |windowClient| to |matchedClients|. - 1. Else if |options|.{{ClientQueryOptions/type}} is "worker" or "all" and |client| is a dedicated worker client, or |options|.{{ClientQueryOptions/type}} is "sharedworker" or "all" and |client| is a shared worker client, then: - 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. - 1. Add |clientObject| to |matchedClients|. - 1. Sort |matchedClients| such that: - * {{WindowClient}} objects are always placed before {{Client}} objects whose associated service worker clients are worker clients. - * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their service worker clients' creation order. - * {{Client}} objects whose associated service worker clients are worker clients are placed next sorted in their service worker clients' creation order. - 1. Resolve |promise| with |matchedClients|. + 1. Let |targetClients| be an empty array. + 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. + 1. Else: + 1. If |client| is not a secure context, continue to the next iteration of the loop. + 1. If |options|.{{ClientQueryOptions/includeUncontrolled}} is false, then: + 1. If |client|'s active service worker is not the associated service worker, continue to the next iteration of the loop. + 1. If |options|.{{ClientQueryOptions/includeReserved}} is false, then: + 1. If |client|'s execution ready flag is unset, continue to the next iteration of the loop. + 1. Add |client| to |targetClients|. + 1. Let |matchedClients| be an empty array. + 1. For each service worker client |client| in |targetClients|: + 1. If |options|.{{ClientQueryOptions/type}} is "window" or "all", and |client| is a type of environment or is a window client, then: + 1. Let |browsingContext| be null. + 1. Let |isClientEnumerable| be true. + 1. Let |visibilityState| be the empty string. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. + 1. Else, set |browsingContext| to |client|'s global object's browsing context. + 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: + 1. If |browsingContext| has been discarded, set |isClientEnumerable| to false and abort these steps. + 1. If |client| is a window client and |client|'s responsible document is not |browsingContext|'s active document, set |isClientEnumerable| to false and abort these steps. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed. + + Note: Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken. + + 1. If |isClientEnumerable| is true, then: + 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Add |windowClient| to |matchedClients|. + 1. Else if |options|.{{ClientQueryOptions/type}} is "worker" or "all" and |client| is a dedicated worker client, or |options|.{{ClientQueryOptions/type}} is "sharedworker" or "all" and |client| is a shared worker client, then: + 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. + 1. Add |clientObject| to |matchedClients|. + 1. Sort |matchedClients| such that: + * {{WindowClient}} objects are always placed before {{Client}} objects whose associated service worker clients are worker clients. + * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their service worker clients' creation order. + * {{Client}} objects whose associated service worker clients are worker clients are placed next sorted in their service worker clients' creation order. + 1. Resolve |promise| with |matchedClients|. 1. Return |promise|.
@@ -1131,24 +1131,24 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |newContext| be a new top-level browsing context. - 1. Let |openWindowFailed| to false. - 1. Let |visibilityState| be null. - 1. Let |focusState| be false. - 1. Let |ancestorOrigins| be the empty array. - 1. Queue a task |task| to run the following substeps on |newContext|'s {{Window}} object's environment settings object's responsible event loop using the user interaction task source: - 1. *HandleNavigate*: Navigate |newContext| to |url| with exceptions enabled and replacement enabled. - 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |openWindowFailed| to true. - 1. Set |visibilityState| to |newContext|'s active document's {{Document/visibilityState}} attribute value. - 1. Set |focusState| to the result of running the has focus steps with |newContext|'s active document as the argument. - 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. - 1. Wait for |task| to have executed (including its asynchronous steps). - 1. If |openWindowFailed| is true, reject |promise| with a TypeError and abort these steps. - 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: - 1. Resolve |promise| with null. - 1. Abort these steps. - 1. Let |client| be the result of running Create Window Client algorithm with |newContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. - 1. Resolve |promise| with |client|. + 1. Let |newContext| be a new top-level browsing context. + 1. Let |openWindowFailed| to false. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on |newContext|'s {{Window}} object's environment settings object's responsible event loop using the user interaction task source: + 1. *HandleNavigate*: Navigate |newContext| to |url| with exceptions enabled and replacement enabled. + 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |openWindowFailed| to true. + 1. Set |visibilityState| to |newContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |newContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Wait for |task| to have executed (including its asynchronous steps). + 1. If |openWindowFailed| is true, reject |promise| with a TypeError and abort these steps. + 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. Resolve |promise| with null. + 1. Abort these steps. + 1. Let |client| be the result of running Create Window Client algorithm with |newContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |client|. 1. Return |promise|.
@@ -1160,18 +1160,18 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the service worker is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. For each service worker client |client| whose origin is the same as the service worker's origin: - 1. If |client| is a type of environment, then: - 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. - 1. Else: - 1. If |client| is not a secure context, continue to the next iteration of the loop. - 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 service worker's containing service worker registration, continue to the next iteration of the loop. - 1. If |client|'s active service worker is not the service worker, then: - 1. Invoke Handle Service Worker Client Unload with |client| as the argument. - 1. Set |client|'s active service worker to service worker. - 1. Invoke Notify Controller Change algorithm with |client| as the argument. - 1. Resolve |promise| with undefined. + 1. For each service worker client |client| whose origin is the same as the service worker's origin: + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. + 1. Else: + 1. If |client| is not a secure context, continue to the next iteration of the loop. + 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 service worker's containing service worker registration, continue to the next iteration of the loop. + 1. If |client|'s active service worker is not the service worker, then: + 1. Invoke Handle Service Worker Client Unload with |client| as the argument. + 1. Set |client|'s active service worker to service worker. + 1. Invoke Notify Controller Change algorithm with |client| as the argument. + 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -1202,15 +1202,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Note: To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run Extend Service Worker Lifetime algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event.
-

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

+

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

{{ExtendableEvent/waitUntil()}} method extends the lifetime of the event. waitUntil(|f|) method *must* run these steps: 1. If the extensions allowed flag is unset, then: - 1. Throw an "{{InvalidStateError}}" exception. - 1. Abort these steps. + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. 1. Add |f| to the extend lifetime promises.
@@ -1245,23 +1245,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe registerForeignFetch(|options|) method *must* run these steps: 1. If the dispatch flag is unset, then: - 1. Throw an "{{InvalidStateError}}" exception. - 1. Abort these steps. + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. 1. If |options|.{{ForeignFetchOptions/origins}} is empty throw a TypeError and abort these steps. 1. Let |originURLs| be an empty list of URLs. 1. If the value of |options|.{{ForeignFetchOptions/origins}} is not a single string equal to a single U+002A ASTERISK character (*): - 1. For each |origin| in |options|.origins: - 1. If the value of |origin| is not an absolute-URL string, throw a TypeError and abort these steps. - 1. Add the result of parsing |origin| to |originURLs|. + 1. For each |origin| in |options|.origins: + 1. If the value of |origin| is not an absolute-URL string, throw a TypeError and abort these steps. + 1. Add the result of parsing |origin| to |originURLs|. 1. If |options|.{{ForeignFetchOptions/scopes}} is empty throw a TypeError and abort these steps. 1. Let |scopeString| be the context object's relevant global object's service worker's containing service worker registration's scope url, serialized. 1. Let |subScopeURLs| be an empty list of URLs. 1. For each |subScope| in |options|.{{ForeignFetchOptions/scopes}}: - 1. Let |subScopeURL| be the result of parsing |subScope| with context object's relevant settings object's API base URL. - 1. If |subScopeURL| is failure, throw a TypeError and abort these steps. - 1. Let |subScopeString| be the serialized |subScopeURL|. - 1. If |subScopeString| does not start with |scopeString|, throw a TypeError and abort these steps. - 1. Add |subScopeURL| to |subScopeURLs|. + 1. Let |subScopeURL| be the result of parsing |subScope| with context object's relevant settings object's API base URL. + 1. If |subScopeURL| is failure, throw a TypeError and abort these steps. + 1. Let |subScopeString| be the serialized |subScopeURL|. + 1. If |subScopeString| does not start with |scopeString|, throw a TypeError and abort these steps. + 1. Add |subScopeURL| to |subScopeURLs|. 1. Set this service worker's list of foreign fetch scopes to |subScopeURLs|. 1. Set this service worker's list of foreign fetch origins to |originURLs|.
@@ -1342,61 +1342,61 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
1. If the dispatch flag is unset, then: - 1. Throw an "{{InvalidStateError}}" exception. - 1. Abort these steps. + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. 1. If the respond-with entered flag is set, then: - 1. Throw an "{{InvalidStateError}}" exception. - 1. Abort these steps. + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. 1. Add |r| to the extend lifetime promises. - Note: {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil()|event.waitUntil(r)}} is called. + 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 respond-with entered flag. 1. Set the 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 respond-with error flag. - 1. If |r| resolved with |response|, then: - 1. If |response| is a {{Response}} object, then: - 1. If |response| is disturbed or locked, then: - 1. Set the 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, except for its body. - 1. If |response|'s body is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|'s 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 a chunk from |response|'s 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, error |newStream| with a TypeError. - 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. - 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. - 1. Set |potentialResponse|'s 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 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. 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 body's stream into |potentialResponse|. - - 1. Set the potential response to |potentialResponse|. - 1. Else: + 1. Wait until |r| settles. + 1. If |r| rejected, then: 1. Set the respond-with error flag. + 1. If |r| resolved with |response|, then: + 1. If |response| is a {{Response}} object, then: + 1. If |response| is disturbed or locked, then: + 1. Set the 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, except for its body. + 1. If |response|'s body is non-null, run these substeps: + 1. Let |reader| be the result of getting a reader from |response|'s 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 a chunk from |response|'s 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, error |newStream| with a TypeError. + 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. + 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. + 1. Set |potentialResponse|'s 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 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. 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 body's stream into |potentialResponse|. + + 1. Set the potential response to |potentialResponse|. + 1. Else: + 1. Set the respond-with error flag. - Note: If the 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 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 wait to respond flag. + 1. Unset the wait to respond flag.
@@ -1454,57 +1454,57 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
1. If the dispatch flag is unset, then: - 1. Throw an "{{InvalidStateError}}" exception. - 1. Abort these steps. + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. 1. If the respond-with entered flag is set, then: - 1. Throw an "{{InvalidStateError}}" exception. - 1. Abort these steps. + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. 1. Add |r| to the extend lifetime promises. 1. Set the stop propagation flag and stop immediate propagation flag. 1. Set the respond-with entered flag. 1. Set the 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 respond-with error flag. - 1. If |r| resolved with |response|, then: - 1. If |response| is a {{ForeignFetchResponse}}, then: - 1. Set the origin to |response|.{{ForeignFetchResponse/origin}}. - 1. Set the list of exposed headers to |response|.{{ForeignFetchResponse/headers}}. - 1. If |response|.{{ForeignFetchResponse/response}} is disturbed or locked, then: + 1. Wait until |r| settles. + 1. If |r| rejected, then: 1. Set the 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|.{{ForeignFetchResponse/response}}'s associated response, except for its body. - 1. If |response|.{{ForeignFetchResponse/response}}'s body is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/response}}'s 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 a chunk from |response|.{{ForeignFetchResponse/response}}'s 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, error |newStream| with a TypeError. - 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. - 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. - 1. Set |potentialResponse|'s 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 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. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. - 1. Set the potential response to |potentialResponse|. - 1. Else: - 1. Set the respond-with error flag. + 1. If |r| resolved with |response|, then: + 1. If |response| is a {{ForeignFetchResponse}}, then: + 1. Set the origin to |response|.{{ForeignFetchResponse/origin}}. + 1. Set the list of exposed headers to |response|.{{ForeignFetchResponse/headers}}. + 1. If |response|.{{ForeignFetchResponse/response}} is disturbed or locked, then: + 1. Set the 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|.{{ForeignFetchResponse/response}}'s associated response, except for its body. + 1. If |response|.{{ForeignFetchResponse/response}}'s body is non-null, run these substeps: + 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/response}}'s 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 a chunk from |response|.{{ForeignFetchResponse/response}}'s 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, error |newStream| with a TypeError. + 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. + 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. + 1. Set |potentialResponse|'s 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 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. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. + 1. Set the potential response to |potentialResponse|. + 1. Else: + 1. Set the respond-with error flag. - Note: If the respond-with error flag is set, a network error is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 19.1.) Otherwise, a filtered version of |response| is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 20.1.) + Note: If the respond-with error flag is set, a network error is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 19.1.) Otherwise, a filtered version of |response| is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 20.1.) - 1. Unset the wait to respond flag. + 1. Unset the wait to respond flag.
@@ -1644,9 +1644,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Invoke [[#start-register-algorithm]] with |scopeURL|, |scriptURL|, |promise|, |client|, |client|'s creation URL and |workerType|. 1. Run the following substeps in parallel: - 1. Wait until |promise| settles. - 1. If |promise| rejected, queue a task to fire an event named error at the <{link}> element. - 1. If |promise| resolved, queue a task to fire an event named load at the <{link}> element. + 1. Wait until |promise| settles. + 1. If |promise| rejected, queue a task to fire an event named error at the <{link}> element. + 1. If |promise| resolved, queue a task to fire an event named load at the <{link}> element. The serviceworker link element *must not* delay the load event of the element's node document. @@ -1772,15 +1772,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |p| be the result of running the algorithm specified in {{Cache/matchAll(request, options)}} method with |request| and |options| as the arguments. - 1. Wait until |p| settles. - 1. If |p| rejects with an exception, then: - 1. Reject |promise| with that exception. - 1. Else if |p| resolves with an array, |responseArray|, then: - 1. If |responseArray| is an empty array, then: - 1. Resolve |promise| with undefined. - 1. Else: - 1. Resolve |promise| with the first element of |responseArray|. + 1. Let |p| be the result of running the algorithm specified in {{Cache/matchAll(request, options)}} method with |request| and |options| as the arguments. + 1. Wait until |p| settles. + 1. If |p| rejects with an exception, then: + 1. Reject |promise| with that exception. + 1. Else if |p| resolves with an array, |responseArray|, then: + 1. If |responseArray| is an empty array, then: + 1. Resolve |promise| with undefined. + 1. Else: + 1. Resolve |promise| with the first element of |responseArray|. 1. Return |promise|.
@@ -1791,27 +1791,27 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If the optional argument |request| is not omitted, then: - 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with an empty array. - 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with an empty array. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |responseArray| be an empty array. - 1. If the optional argument |request| is omitted, then: - 1. For each fetching record |entry| of its request to response map, in key insertion order: - 1. Add a copy of |entry|.\[[value]] to |responseArray|. - 1. Resolve |promise| with |responseArray|. - 1. Abort these steps. - 1. Else: - 1. Let |entries| be the result of running Query Cache algorithm passing a {{Request}} object associated with |r| and |options| as the arguments. - 1. For each |entry| of |entries|: - 1. Let |response| be null. - 1. If the incumbent record |incumbentRecord| of the corresponding fetching record in request to response map is not null, set |response| to a copy of |incumbentRecord|.\[[value]]. - 1. Else, set |response| to a copy of |entry|[1]. - 1. Add |response| to |responseArray|. - 1. Resolve |promise| with |responseArray|. + 1. Let |responseArray| be an empty array. + 1. If the optional argument |request| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Add a copy of |entry|.\[[value]] to |responseArray|. + 1. Resolve |promise| with |responseArray|. + 1. Abort these steps. + 1. Else: + 1. Let |entries| be the result of running Query Cache algorithm passing a {{Request}} object associated with |r| and |options| as the arguments. + 1. For each |entry| of |entries|: + 1. Let |response| be null. + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record in request to response map is not null, set |response| to a copy of |incumbentRecord|.\[[value]]. + 1. Else, set |response| to a copy of |entry|[1]. + 1. Add |response| to |responseArray|. + 1. Resolve |promise| with |responseArray|. 1. Return |promise|.
@@ -1833,66 +1833,65 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |responsePromiseArray| be an empty array. 1. Let |requestArray| be an empty array. 1. For each |request| whose type is {{Request}} in |requests|: - 1. Let |r| be |request|'s request. - 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. + 1. Let |r| be |request|'s request. + 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. 1. For each |request| in |requests|: - 1. Let |r| be the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. - 1. If |r|'s url's scheme is not one of "http" and "https", then: - 1. Terminate service worker all the ongoing fetches initiated by |requests| with reason *fatal*. - 1. Break the loop. - 1. Set |r|'s initiator to "fetch" and destination to "subresource". - 1. Add a {{Request}} object associated with |r| to |requestArray|. - 1. Let |responsePromise| be a new promise. - 1. Run the following substeps in parallel: - * Fetch |r|. - * To process response for |response|, run these substeps: - - 1. If |response|'s type is "error", or |response|'s status is not an ok status, reject |responsePromise| with a TypeError. - 1. Else if |response|'s header list contains a header named `Vary`, then: - 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. - 1. Let |matchAsterisk| be false. - 1. For each |f| in |varyHeaders|: - 1. If |f| matches "*", set |matchAsterisk| to true and break the loop. - 1. If |matchAsterisk| is true, reject |responsePromise| with a TypeError. - 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". - 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". - - Note: This step ensures that the promise for this fetch resolves as soon as the response's headers become available. - - * To process response for |response|, do nothing. - * To process response done for |response|, do nothing. - 1. Add |responsePromise| to |responsePromiseArray|. + 1. Let |r| be the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s url's scheme is not one of "http" and "https", then: + 1. Terminate service worker all the ongoing fetches initiated by |requests| with reason *fatal*. + 1. Break the loop. + 1. Set |r|'s initiator to "fetch" and destination to "subresource". + 1. Add a {{Request}} object associated with |r| to |requestArray|. + 1. Let |responsePromise| be a new promise. + 1. Run the following substeps in parallel: + * Fetch |r|. + * To process response for |response|, run these substeps: + 1. If |response|'s type is "error", or |response|'s status is not an ok status, reject |responsePromise| with a TypeError. + 1. Else if |response|'s header list contains a header named `Vary`, then: + 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. Let |matchAsterisk| be false. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", set |matchAsterisk| to true and break the loop. + 1. If |matchAsterisk| is true, reject |responsePromise| with a TypeError. + 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". + 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". + + Note: This step ensures that the promise for this fetch resolves as soon as the response's headers become available. + + * To process response for |response|, do nothing. + * To process response done for |response|, do nothing. + 1. Add |responsePromise| to |responsePromiseArray|. 1. Let |p| be waiting for all of |responsePromiseArray|. 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |responseArray|, performs the following substeps in parallel: - 1. Let |operations| be an empty array. - 1. For each |response| in |responseArray| with the index |index|: - 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. - 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "put". - 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to |requestArray|[|index|]. - 1. Set the {{CacheBatchOperation/response}} dictionary member of |o| to |response|. - 1. Add |o| to |operations|. - 1. Let |resultPromise| be the result of running Batch Cache Operations algorithm passing |operations| as the argument. - 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: - 1. Let |responseBodyPromiseArray| be an empty array. - 1. For each |response| in |responses|: - 1. Let |responseBodyPromise| be a new promise. - 1. Run the following substeps in parallel: - 1. Wait for either end-of-file to have been pushed to |response|'s associated response |r|'s body or for |r| to have a termination reason. - 1. If |r| had a termination reason, then: - 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: - 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. - 1. Else: - 1. Delete |fetchingRecord| from request to response map. - 1. Reject |responseBodyPromise| with a TypeError. - 1. Else: - 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. - 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. - 1. For each |invalidRecord| in |invalidRecords|: - 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. - 1. Resolve |responseBodyPromise| with |response|. - 1. Add |responseBodyPromise| to |responseBodyPromiseArray|. - 1. Let |q| be waiting for all of |responseBodyPromiseArray|. - 1. Return the result of transforming |q| with a fulfillment handler that returns undefined. + 1. Let |operations| be an empty array. + 1. For each |response| in |responseArray| with the index |index|: + 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. + 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "put". + 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to |requestArray|[|index|]. + 1. Set the {{CacheBatchOperation/response}} dictionary member of |o| to |response|. + 1. Add |o| to |operations|. + 1. Let |resultPromise| be the result of running Batch Cache Operations algorithm passing |operations| as the argument. + 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: + 1. Let |responseBodyPromiseArray| be an empty array. + 1. For each |response| in |responses|: + 1. Let |responseBodyPromise| be a new promise. + 1. Run the following substeps in parallel: + 1. Wait for either end-of-file to have been pushed to |response|'s associated response |r|'s body or for |r| to have a termination reason. + 1. If |r| had a termination reason, then: + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: + 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. + 1. Else: + 1. Delete |fetchingRecord| from request to response map. + 1. Reject |responseBodyPromise| with a TypeError. + 1. Else: + 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. + 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. + 1. For each |invalidRecord| in |invalidRecords|: + 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. + 1. Resolve |responseBodyPromise| with |response|. + 1. Add |responseBodyPromise| to |responseBodyPromiseArray|. + 1. Let |q| be waiting for all of |responseBodyPromiseArray|. + 1. Return the result of transforming |q| with a fulfillment handler that returns undefined.
@@ -1902,22 +1901,22 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. + 1. Set |r| to |request|'s request. + 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. - 1. If |r|'s url's scheme is not one of "http" and "https", return a promise rejected with a TypeError. + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s url's scheme is not one of "http" and "https", return a promise rejected with a TypeError. 1. If |response|'s associated response's header list contains a header named `Vary`, then: - 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. - 1. For each |f| in |varyHeaders|: - 1. If |f| matches "*", return a promise rejected with a TypeError. + 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", return a promise rejected with a TypeError. 1. If |response| is disturbed or locked, return a promise rejected with a TypeError. 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated response and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. 1. If |response|'s body is non-null, run these substeps: - 1. Let |dummyStream| be an empty {{ReadableStream}} object. - 1. Set |response|'s body to a new body whose stream is |dummyStream|. - 1. Let |reader| be the result of getting a reader from |dummyStream|. - 1. Read all bytes from |dummyStream| with |reader|. + 1. Let |dummyStream| be an empty {{ReadableStream}} object. + 1. Set |response|'s body to a new body whose stream is |dummyStream|. + 1. Let |reader| be the result of getting a reader from |dummyStream|. + 1. Read all bytes from |dummyStream| with |reader|. 1. Let |operations| be an empty array. 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "put". @@ -1926,19 +1925,19 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Add |o| to |operations|. 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: - 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated response |r|'s body or for |r| to have a termination reason. - 1. If |r| had a termination reason, then: - 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: - 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. + 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated response |r|'s body or for |r| to have a termination reason. + 1. If |r| had a termination reason, then: + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: + 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. + 1. Else: + 1. Delete |fetchingRecord| from request to response map. + 1. Throw a TypeError. 1. Else: - 1. Delete |fetchingRecord| from request to response map. - 1. Throw a TypeError. - 1. Else: - 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. - 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. - 1. For each |invalidRecord| in |invalidRecords|: - 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. - 1. Return undefined. + 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. + 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. + 1. For each |invalidRecord| in |invalidRecords|: + 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. + 1. Return undefined.
@@ -1948,10 +1947,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with false. + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with false. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |operations| be an empty array. 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "delete". @@ -1960,8 +1959,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Add |o| to |operations|. 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. 1. Return the result of transforming |resultPromise| with a fulfillment handler, when called with argument |responseArray|, performs the following substeps in parallel: - 1. If |responseArray| is not null, return true. - 1. Else, return false. + 1. If |responseArray| is not null, return true. + 1. Else, return false.
@@ -1971,22 +1970,21 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |resultArray| be an empty array. - 1. If the optional argument |request| is omitted, then: - 1. For each fetching record |entry| of its request to response map, in key insertion order: - 1. Add |entry|.\[[key]] to |resultArray|. - 1. Else: - 1. Let |r| be null. - 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, resolve |promise| with an empty array. - 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. - 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing a {{Request}} object that represents |r| and |options| as the arguments. - 1. For each |requestResponse| in |requestResponseArray|: - 1. Add |requestResponse|[0] to |resultArray|. - 1. Resolve |promise| with |resultArray|. - + 1. Let |resultArray| be an empty array. + 1. If the optional argument |request| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Add |entry|.\[[key]] to |resultArray|. + 1. Else: + 1. Let |r| be null. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s request. + 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, resolve |promise| with an empty array. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing a {{Request}} object that represents |r| and |options| as the arguments. + 1. For each |requestResponse| in |requestResponseArray|: + 1. Add |requestResponse|[0] to |resultArray|. + 1. Resolve |promise| with |resultArray|. 1. Return |promise|.
@@ -2018,19 +2016,19 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe match(|request|, |options|) method *must* run these steps: 1. If |options|.{{CacheQueryOptions/cacheName}} is present, then: - 1. Return a new promise |p| and run the following substeps in parallel: - 1. For each |cacheName| → |cache| of name to cache map: - 1. If |options|.{{CacheQueryOptions/cacheName}} matches |cacheName|, then: - 1. Resolve |p| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache| as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) - 1. Abort these steps. - 1. Resolve |p| with undefined. + 1. Return a new promise |p| and run the following substeps in parallel: + 1. For each |cacheName| → |cache| of name to cache map: + 1. If |options|.{{CacheQueryOptions/cacheName}} matches |cacheName|, then: + 1. Resolve |p| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache| as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. Abort these steps. + 1. Resolve |p| with undefined. 1. Else: - 1. Let |p| be a promise resolved with undefined. - 1. For each cacheName → |cache| of name to cache map: - 1. Set |p| to the result of transforming itself with a fulfillment handler that, when called with argument |v|, performs the following substeps in parallel: - 1. If |v| is not undefined, return |v|. - 1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache|] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) - 1. Return |p|. + 1. Let |p| be a promise resolved with undefined. + 1. For each cacheName → |cache| of name to cache map: + 1. Set |p| to the result of transforming itself with a fulfillment handler that, when called with argument |v|, performs the following substeps in parallel: + 1. If |v| is not undefined, return |v|. + 1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache|] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. Return |p|.
@@ -2039,10 +2037,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe has(|cacheName|) method *must* run these steps: 1. Return a promise resolved with the result of running the following substeps: - 1. For each |key| → value of name to cache map: - 1. If |cacheName| matches |key|, then: - 1. Return true. - 1. Return false. + 1. For each |key| → value of name to cache map: + 1. If |cacheName| matches |key|, then: + 1. Return true. + 1. Return false.
@@ -2052,13 +2050,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |p| be a new promise. 1. Run the following substeps: - 1. For each |key| → |value| of name to cache map: - 1. If |cacheName| matches |key|, then: - 1. Resolve |p| with a new {{Cache}} object which is a copy of |value|. - 1. Abort these steps. - 1. Let |cache| be a new {{Cache}} object. - 1. Set name to cache map[|cacheName|] to |cache|. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. - 1. Resolve |p| with |cache|. + 1. For each |key| → |value| of name to cache map: + 1. If |cacheName| matches |key|, then: + 1. Resolve |p| with a new {{Cache}} object which is a copy of |value|. + 1. Abort these steps. + 1. Let |cache| be a new {{Cache}} object. + 1. Set name to cache map[|cacheName|] to |cache|. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. + 1. Resolve |p| with |cache|. 1. Return |p|.
@@ -2069,15 +2067,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |p| be the result of running the algorithm specified in {{CacheStorage/has(cacheName)}} method with |cacheName| as the argument. 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |cacheExists|, performs the following substeps in parallel: - 1. If |cacheExists| is true, then: - 1. Delete a Record {\[[key]], \[[value]]} entry from its name to cache map where |cacheName| matches entry.\[[key]]. - 1. Return true. - 1. Abort these steps. + 1. If |cacheExists| is true, then: + 1. Delete a Record {\[[key]], \[[value]]} entry from its name to cache map where |cacheName| matches entry.\[[key]]. + 1. Return true. + 1. Abort these steps. - Note: After this step, the existing DOM objects (i.e. the currently referenced Cache, Request, and Response objects) should remain functional. + Note: After this step, the existing DOM objects (i.e. the currently referenced Cache, Request, and Response objects) should remain functional. - 1. Else: - 1. Return false. + 1. Else: + 1. Return false.
@@ -2099,7 +2097,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Secure Context

- Service workers *must* execute in secure contexts. < afor="/">Service worker clients *must* also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts. + Service workers *must* execute in secure contexts. Service worker clients *must* also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts.
@@ -2131,13 +2129,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |serviceWorker| be |request|'s client's global object's service worker. 1. If |serviceWorker|'s imported scripts updated flag is unset, then: - 1. Let |response| be the result of fetching |request|. - 1. If |response|'s unsafe response's type is not "error", and |response|'s status is an ok status, then: - 1. Set script resource map[|request|'s url] to |response| - 1. Return |response|. + 1. Let |response| be the result of fetching |request|. + 1. If |response|'s unsafe response's type is not "error", and |response|'s status is an ok status, then: + 1. Set script resource map[|request|'s url] to |response| + 1. Return |response|. 1. Else: - 1. If script resource map[|url|] exists, return script resource map[|url|]. - 1. Else, return a network error. + 1. If script resource map[|url|] exists, return script resource map[|url|]. + 1. Else, return a network error.
@@ -2292,11 +2290,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: none 1. If the job queue is empty, then: - 1. Push |job| to the job queue and invoke Run Job. + 1. Push |job| to the job queue and invoke Run Job. 1. Else: - 1. Let |lastJob| be the element at the back of the job queue. - 1. If |job| is equivalent to |lastJob| and |lastJob|'s job promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. - 1. Else, push |job| to the job queue. + 1. Let |lastJob| be the element at the back of the job queue. + 1. If |job| is equivalent to |lastJob| and |lastJob|'s job promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. + 1. Else, push |job| to the job queue.
@@ -2309,13 +2307,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Assert: the job queue is not empty. 1. Queue a task to run these steps: - 1. Let |job| be the element in the front of the job queue. - 1. If |job|'s job type is *register*, run Register with |job| in parallel. - 1. Else if |job|'s job type is *update*, run Update with |job| in parallel. + 1. Let |job| be the element in the front of the job queue. + 1. If |job|'s job type is *register*, run Register with |job| in parallel. + 1. Else if |job|'s job type is *update*, run Update with |job| in parallel. - Note: For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event. + Note: For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event. - 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel. + 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel.
@@ -2342,7 +2340,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |job|'s client is not null, queue a task to resolve |job|'s job promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
@@ -2356,7 +2354,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |job|'s client is not null, queue a task to reject |job|'s job promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
@@ -2377,7 +2375,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If any of the strings in |scriptURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. 1. If |scopeURL| is null, set |scopeURL| to the result of parsing the string "./" with |scriptURL|. - Note: The scope url for the registration is set to the location of the service worker script by default. + Note: The scope url for the registration is set to the location of the service worker script by default. 1. If |scopeURL| is failure, reject |promise| with a TypeError and abort these steps. 1. If |scopeURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. @@ -2397,23 +2395,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: none 1. If the result of running potentially trustworthy origin with the origin of |job|'s script url as the argument is Not Trusted, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. 1. If the origin of |job|'s script url is not |job|'s referrer's origin, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. 1. If the origin of |job|'s scope url is not |job|'s referrer's origin, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 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 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 and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: - 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. - 1. Invoke Finish Job with |job| and abort these steps. + 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 and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Invoke Finish Job with |job| and abort these steps. 1. Else: - 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. + 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. 1. Invoke Update algorithm passing |job| as the argument.
@@ -2427,87 +2425,87 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s scope url as the argument. 1. If |registration| is null or |registration|'s uninstalling flag is set, then: - 1. Invoke Reject Job Promise with |job| and a TypeError. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Invoke Reject Job Promise with |job| and a 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. 1. If |job|'s job type is *update*, and |newestWorker|'s script url does not equal |job|'s script url with the *exclude fragments flag* set, then: - 1. Invoke Reject Job Promise with |job| and a TypeError. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Invoke Reject Job Promise with |job| and a TypeError. + 1. Invoke Finish Job with |job| and abort these steps. 1. Let |httpsState| be "none". 1. Let |referrerPolicy| be the empty string. 1. Switching on |job|'s worker type, run these substeps with the following options: - : *"classic"* - :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". - : *"module"* - :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. + : *"classic"* + :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". + : *"module"* + :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. - To perform the fetch given |request|, run the following steps if the is top-level flag is set: + To perform the fetch given |request|, run the following steps if the is top-level flag is set: - 1. Append `Service-Worker`/`script` to |request|'s header list. + 1. Append `Service-Worker`/`script` to |request|'s header list. - Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. + Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. - 1. Set |request|'s skip-service-worker flag and |request|'s redirect mode to "error". - 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: - 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". + 1. Set |request|'s skip-service-worker flag and |request|'s redirect mode to "error". + 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". - Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. + Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. - 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. - 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Asynchronously complete these steps with a network error. - 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. - - Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. - - 1. Set |httpsState| to |response|'s HTTPS state. - 1. Set |referrerPolicy| to the result of parse a referrer policy from a Referrer-Policy header of |response|. - 1. If |serviceWorkerAllowed| is failure, then: - 1. Asynchronously complete these steps with a network error. - 1. Let |scopeURL| be |registration|'s scope url. - 1. Let |maxScopeString| be null. - 1. If |serviceWorkerAllowed| is null, then: - 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". - 1. Else: - 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. - 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s path (including empty strings), separated from each other by "/". - 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s path (including empty strings), separated from each other by "/". - 1. If |scopeString| starts with |maxScopeString|, do nothing. - 1. Else: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Asynchronously complete these steps with a network error. - 1. If |response|'s cache state is not "local", set |registration|'s last update check time to the current time. + 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. + 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. - Issue: The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state. + Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. - 1. Return true. + 1. Set |httpsState| to |response|'s HTTPS state. + 1. Set |referrerPolicy| to the result of parse a referrer policy from a Referrer-Policy header of |response|. + 1. If |serviceWorkerAllowed| is failure, then: + 1. Asynchronously complete these steps with a network error. + 1. Let |scopeURL| be |registration|'s scope url. + 1. Let |maxScopeString| be null. + 1. If |serviceWorkerAllowed| is null, then: + 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". + 1. Else: + 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. + 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s path (including empty strings), separated from each other by "/". + 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s path (including empty strings), separated from each other by "/". + 1. If |scopeString| starts with |maxScopeString|, do nothing. + 1. Else: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + 1. If |response|'s cache state is not "local", set |registration|'s last update check time to the current time. - If the algorithm asynchronously completes with null, then: + Issue: The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state. - 1. Invoke Reject Job Promise with |job| and a TypeError. + 1. Return true. - Note: This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception. + If the algorithm asynchronously completes with null, then: - 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. Invoke Reject Job Promise with |job| and a TypeError. + + Note: This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception. - Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. + 1. If |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. + + Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: - 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. - 1. Invoke Finish Job with |job| and abort these steps. - 1. Else: - 1. Let |worker| be a new service worker. - 1. Generate a unique opaque string and set |worker|'s id to the value. - 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. - 1. Set |worker|'s script resource's HTTPS state to |httpsState|. - 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. - 1. Invoke Run Service Worker algorithm with |worker| as the argument. - 1. If an uncaught runtime script error occurs during the above step, then: - 1. Invoke Reject Job Promise with |job| and a TypeError. - 1. If |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Invoke Finish Job with |job| and abort these steps. + 1. Else: + 1. Let |worker| be a new service worker. + 1. Generate a unique opaque string and set |worker|'s id to the value. + 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. + 1. Set |worker|'s script resource's HTTPS state to |httpsState|. + 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. + 1. Invoke Run Service Worker algorithm with |worker| as the argument. + 1. If an uncaught runtime script error occurs during the above step, then: + 1. Invoke Reject Job Promise with |job| and a TypeError. + 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. Invoke Install algorithm with |job|, |worker|, and |registration| as its arguments.
@@ -2550,38 +2548,38 @@ 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 promise is not null. 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 scope url and all the service workers whose containing service worker registration is |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 scope url and all the service workers whose containing service worker registration is |registration|. 1. Let |installingWorker| be |registration|'s installing worker. 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type install, which does not bubble and is not cancelable. - 1. Dispatch |e| at |installingWorker|'s environment settings object's global object. - 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: - 1. Wait until |e|'s extensions allowed flag is unset. - 1. If the result of waiting for all of |e|'s extend lifetime promises rejected, set |installFailed| to true. + 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type install, which does not bubble and is not cancelable. + 1. Dispatch |e| at |installingWorker|'s environment settings object's global object. + 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: + 1. Wait until |e|'s extensions allowed flag is unset. + 1. If 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 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. Set |redundantWorker| to |registration|'s installing worker. - 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 |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Set |redundantWorker| to |registration|'s installing worker. + 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 |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. 1. Set |registration|'s installing worker's imported scripts updated flag. 1. If |registration|'s waiting worker is not null, then: - 1. Set |redundantWorker| to |registration|'s waiting worker. - 1. Terminate service worker |redundantWorker|. - 1. The user agent *may* abort in-flight requests triggered by |redundantWorker|. + 1. Set |redundantWorker| to |registration|'s waiting worker. + 1. Terminate service worker |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. If |registration|'s waiting worker's skip waiting flag is set, then: - 1. Run Activate algorithm passing |registration| as the argument. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Run Activate algorithm passing |registration| as the argument. + 1. Invoke Finish Job with |job| and abort these steps. 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. @@ -2599,31 +2597,31 @@ 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 service worker |redundantWorker|. + 1. Set |redundantWorker| to |registration|'s active worker. + 1. Wait for |redundantWorker| to finish handling any in-progress requests. + 1. Terminate service worker |redundantWorker|. 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. - 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. + 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. - 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: - 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 global object from its application cache, if it has one. + 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: + 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 global object from its application cache, if it has one. - Note: Resources will now use the service worker registration instead of the existing application cache. + 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. 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: - 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type activate, which does not bubble and is not cancelable. - 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. - 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. + 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type activate, which does not bubble and is not cancelable. + 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. 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. @@ -2642,29 +2640,29 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |serviceWorker| is already running, abort these steps. 1. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context. 1. Call the JavaScript InitializeHostDefinedRealm abstract operation with the following customizations: - * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. - * Let |realmExecutionContext| be the created execution context. + * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. + * Let |realmExecutionContext| be the created execution context. 1. Let |workerEventLoop| be a newly created event loop. 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: - : The realm execution context - :: Return |realmExecutionContext|. - : The global object - :: Return |workerGlobalScope|. - : The responsible event loop - :: Return |workerEventLoop|. - : The referrer policy - :: Return |workerGlobalScope|'s referrer policy. - : The API URL character encoding - :: Return UTF-8. - : The API base URL - :: Return |serviceWorker|'s script url. - : The origin - :: Return its registering service worker client's origin. - : The creation URL - :: Return |workerGlobalScope|'s url. - : The HTTPS state - :: Return |workerGlobalScope|'s HTTPS state. + : The realm execution context + :: Return |realmExecutionContext|. + : The global object + :: Return |workerGlobalScope|. + : The responsible event loop + :: Return |workerEventLoop|. + : The referrer policy + :: Return |workerGlobalScope|'s referrer policy. + : The API URL character encoding + :: Return UTF-8. + : The API base URL + :: Return |serviceWorker|'s script url. + : The origin + :: Return its registering service worker client's origin. + : The creation URL + :: Return |workerGlobalScope|'s url. + : The HTTPS state + :: Return |workerGlobalScope|'s HTTPS state. 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. 1. Set |workerGlobalScope|'s HTTPS state to |serviceWorker|'s script resource's HTTPS state. @@ -2674,14 +2672,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. 1. If |script| is a classic script, then run the classic script |script|. Otherwise, it is a module script; run the module script |script|. - Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. + Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. 1. If |script|'s has ever been evaluated flag is unset, then: - 1. Set |workerGlobalScope|'s associated service worker's set of event types to handle to the set of event types created from |settingsObject|'s global object's associated list of event listeners' event types. + 1. Set |workerGlobalScope|'s associated service worker's set of event types to handle to the set of event types created from |settingsObject|'s global object's associated list of event listeners' event types. - Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. + Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. - 1. Set |script|'s has ever been evaluated flag. + 1. Set |script|'s has ever been evaluated flag. 1. Run the responsible event loop specified by |settingsObject| until it is destroyed. 1. Empty |workerGlobalScope|'s list of active timers.
@@ -2699,7 +2697,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Set |serviceWorkerGlobalScope|'s closing flag to true. 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's task queues, queue them to |serviceWorker|'s containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's task queues without processing them. - Note: This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded. + Note: This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded. 1. Abort the script currently running in |serviceWorker|.
@@ -2727,66 +2725,66 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |reservedClient| be |request|'s reserved client. 1. Assert: |request|'s destination is not "serviceworker". 1. If |request| is a potential-navigation-or-subresource request, then: - 1. Return null. + 1. Return null. 1. Else if |request| is a non-subresource request, then: - Note: If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration. + Note: If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration. - 1. If |reservedClient| is not null and is an environment settings object, then: - 1. If |reservedClient| is not a secure context, return null. - 1. Else: - 1. If |request|'s url is not a potentially trustworthy URL, return null. - 1. If |request| is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null. - 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s url as the argument. - 1. If |registration| is null or |registration|'s active worker is null, return null. - 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. + 1. If |reservedClient| is not null and is an environment settings object, then: + 1. If |reservedClient| is not a secure context, return null. + 1. Else: + 1. If |request|'s url is not a potentially trustworthy URL, return null. + 1. If |request| is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null. + 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s url as the argument. + 1. If |registration| is null or |registration|'s active worker is null, return null. + 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. - Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. + Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. 1. Else if |request| is a subresource request, then: - 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. - 1. Else, return null. + 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. + 1. Else, return null. 1. Let |activeWorker| be |registration|'s active worker. 1. If |activeWorker|'s set of event types to handle does not contain fetch, then: - 1. Return null and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - 1. Abort these steps. + 1. Return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. - Note: To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. + Note: To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. - 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. - 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. - 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. - 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s target client id, and to the empty string otherwise. - 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s 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 environment settings object's global object. - 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. - 1. If |e|'s wait to respond flag is set, then: - 1. Wait until |e|'s wait to respond flag is unset. - 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. - 1. Else, set |response| to |e|'s potential response. - 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - - If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. - - The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. + 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. + 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. + 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. + 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. + 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s target client id, and to the empty string otherwise. + 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s 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 environment settings object's global object. + 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. + 1. If |e|'s wait to respond flag is set, then: + 1. Wait until |e|'s wait to respond flag is unset. + 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. + 1. Else, set |response| to |e|'s potential response. + 1. If |e|'s canceled flag is set, set |eventCanceled| to true. + + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + + The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. 1. Wait for |task| to have executed or been discarded. 1. If |respondWithEntered| is false, then: - 1. If |eventCanceled| is true, return a network error and continue running these steps in parallel. - 1. Else, return null and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - 1. Abort these steps. + 1. If |eventCanceled| is true, return a network error and continue running these steps in parallel. + 1. Else, return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. 1. If |handleFetchFailed| is true, then: - 1. Return a network error and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Return a network error and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. 1. Else: - 1. Return |response| and continue running these steps in parallel. - 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Return |response| and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|.
@@ -2808,59 +2806,59 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |eventCanceled| be false. 1. If |request| is not a subresource request, return null and abort these steps. - Note: Foreign fetch only allows intercepting of subresource requests. Navigation requests can be intercepted by the regular fetch event anyway, so there is no benefit to supporting those requests here as well. + Note: Foreign fetch only allows intercepting of subresource requests. Navigation requests can be intercepted by the regular fetch event anyway, so there is no benefit to supporting those requests here as well. 1. If |request|'s client is not a secure context, return null and abort these steps. 1. Let |activeWorker| be the result of running the [[#foreign-fetch-scope-match-algorithm]] algorithm passing |request|'s url as the argument. 1. If |activeWorker| is null, return null. 1. If |activeWorker|'s state is *activating*, then: - 1. Wait for |activeWorker|'s state to become *activated*. + 1. Wait for |activeWorker|'s state to become *activated*. 1. If |activeWorker|'s origin is the same as |request|'s origin, return null. 1. Let |originMatches| be false. 1. If |activeWorker|'s list of foreign fetch origins is empty, set |originMatches| to true. 1. For each |origin| in |activeWorker|'s list of foreign fetch origins: - 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. + 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. 1. If |originMatches| is false, return null. 1. Let |r| be a new {{Request}} object associated with |request|. 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. - 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. - 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. - 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. - 1. If |e|'s 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 potential response. - 1. If |internalResponse| is a filtered response, set |internalResponse| to |internalResponse|'s internal response. - 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. - 1. Else if |e|'s origin is null: - 1. If |e|'s list of exposed headers is not empty, set |handleFetchFailed| to true. - 1. Else if |e|'s potential response is a opaque-redirect filtered response, set |response| to |e|'s potential response. - 1. Else set |response| to an opaque filtered response of |internalResponse|. - 1. Else if |e|'s origin is not equal to the Unicode serialization of |request|'s origin, set |handleFetchFailed| to true. - 1. Else if |e|'s potential response is an opaque filtered response or is an opaque-redirect filtered response, set |response| to |e|'s potential response. - 1. Else if |request|'s response tainting is "opaque", set |response| to an opaque filtered response of |internalResponse|. - 1. Else: - 1. Let |headers| be |e|'s list of exposed headers. - 1. If |response| is a CORS filtered response, remove from |internalResponse|'s CORS-exposed header-name list all values not in |headers|. - 1. Else set |internalResponse|'s CORS-exposed header-name list to |headers|. - 1. Set |response| to a CORS filtered response of |internalResponse|. - 1. If |e|'s canceled flag is set, set |eventCanceled| to true. + 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. + 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. + 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. + 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. If |e|'s 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 potential response. + 1. If |internalResponse| is a filtered response, set |internalResponse| to |internalResponse|'s internal response. + 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. + 1. Else if |e|'s origin is null: + 1. If |e|'s list of exposed headers is not empty, set |handleFetchFailed| to true. + 1. Else if |e|'s potential response is a opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else set |response| to an opaque filtered response of |internalResponse|. + 1. Else if |e|'s origin is not equal to the Unicode serialization of |request|'s origin, set |handleFetchFailed| to true. + 1. Else if |e|'s potential response is an opaque filtered response or is an opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else if |request|'s response tainting is "opaque", set |response| to an opaque filtered response of |internalResponse|. + 1. Else: + 1. Let |headers| be |e|'s list of exposed headers. + 1. If |response| is a CORS filtered response, remove from |internalResponse|'s CORS-exposed header-name list all values not in |headers|. + 1. Else set |internalResponse|'s CORS-exposed header-name list to |headers|. + 1. Set |response| to a CORS filtered response of |internalResponse|. + 1. If |e|'s canceled flag is set, set |eventCanceled| to true. - If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. - The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. + The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. 1. Wait for |task| to have executed or been discarded. 1. If |respondWithEntered| is false, then: - 1. If |eventCanceled| is true, then: - 1. Return a network error. - 1. Else: - 1. Return null. + 1. If |eventCanceled| is true, then: + 1. Return a network error. + 1. Else: + 1. Return null. 1. If |handleFetchFailed| is true, then: - 1. Return a network error. + 1. Return a network error. 1. Else: - 1. Return |response|. + 1. Return |response|.
@@ -2878,17 +2876,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 contain the event type for this functional event, then: - 1. Return and continue running these steps in parallel. - 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - 1. Abort these steps. + 1. Return and continue running these steps in parallel. + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. - Note: To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. + Note: To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to invoke |callbackSteps| with |activeWorker|'s environment settings object's global object as its argument. - The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. + The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. 1. Wait for |task| to have executed or been discarded. 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. @@ -2921,11 +2919,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: None 1. For each scope → |registration| of scope to registration map: - 1. If |registration|'s installing worker |installingWorker| is not null, then: - 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. - 1. Else, set |registration|'s installing worker to null. - 1. If |registration|'s waiting worker is not null, run the following substep in parallel: - 1. Invoke Activate with |registration|. + 1. If |registration|'s installing worker |installingWorker| is not null, then: + 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. + 1. Else, set |registration|'s installing worker to null. + 1. If |registration|'s waiting worker is not null, run the following substep in parallel: + 1. Invoke Activate with |registration|.
@@ -2937,17 +2935,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: none 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: - 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. - 1. Invoke Finish Job with |job| and abort these steps. + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s scope url as the argument. 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. 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. Invoke Resolve Job Promise with |job| and true. 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. - Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. + Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. 1. Invoke Finish Job with |job|.
@@ -2978,23 +2976,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Run the following steps atomically. 1. Let |redundantWorker| be null. 1. If |registration|'s installing worker is not null, then: - 1. Set |redundantWorker| to |registration|'s installing worker. - 1. Terminate service worker |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. Set |redundantWorker| to |registration|'s installing worker. + 1. Terminate service worker |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 service worker |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. Set |redundantWorker| to |registration|'s waiting worker. + 1. Terminate service worker |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 service worker |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. Set |redundantWorker| to |registration|'s active worker. + 1. Terminate service worker |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 scope url with the *exclude fragment flag* set. 1. Remove scope to registration map[|scopeString|]. @@ -3011,17 +3009,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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. 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. 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 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 active worker, or null if |registration|’s active worker is null. + 1. Set |registration|'s 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 active worker, or null if |registration|’s active worker is null. The task *must* use |registrationObject|'s relevant settings object's responsible event loop and the DOM manipulation task source. @@ -3038,34 +3036,34 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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" + 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. + 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" + : *installed* + :: "installed" - Note: The service worker in this state is considered a waiting worker. + Note: The service worker in this state is considered a waiting worker. - : *activating* - :: "activating" + : *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*. + 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" + : *activated* + :: "activated" - Note: The service worker in this state is considered an active worker ready to handle functional events. + Note: The service worker in this state is considered an active worker ready to handle functional events. - : *redundant* - :: "redundant" + : *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. + 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|. + 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. @@ -3098,7 +3096,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |allScopes| be the result of getting the keys from scope to registration map. 1. Set |matchingScope| to the longest value in |allScopes| which the value of |clientURLString| starts with, if it exists. - Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). + Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). 1. Let |parsedMatchingScope| be null. 1. If |matchingScope| is not the empty string, set |parsedMatchingScope| to the result of parsing |matchingScope|. @@ -3122,8 +3120,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |worker| is null, return null. 1. Let |requestURLString| be the serialized |requestURL|. 1. For each URL |scope| in |worker|'s list of foreign fetch scopes: - 1. Let |scopeString| be the serialized |scope|. - 1. If |requestURLString| starts with |scopeString| return |worker|. + 1. Let |scopeString| be the serialized |scope|. + 1. If |requestURLString| starts with |scopeString| return |worker|. 1. Return null. @@ -3140,7 +3138,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |scope| is not null, set |scopeString| to serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be null. 1. For each |key| → |value| of scope to registration map: - 1. If |scopeString| matches |key|, set |registration| to |value|. + 1. If |scopeString| matches |key|, set |registration| to |value|. 1. Return |registration|. @@ -3209,37 +3207,37 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.method is not `GET`, return |resultArray|. 1. Let |cachedURL| and |requestURL| be null. 1. If the optional argument |targetStorage| is omitted, then: - 1. For each fetching record |entry| of its request to response map, in key insertion order: - 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. - 1. If |options|.ignoreSearch is true, then: - 1. Set |cachedURL|'s query to the empty string. - 1. Set |requestURL|'s query to the empty string. - 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: - 1. Add a copy of |entry|.\[[key]] to |requestArray|. - 1. Add a copy of |entry|.\[[value]] to |responseArray|. + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. + 1. If |options|.ignoreSearch is true, then: + 1. Set |cachedURL|'s query to the empty string. + 1. Set |requestURL|'s query to the empty string. + 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Add a copy of |entry|.\[[key]] to |requestArray|. + 1. Add a copy of |entry|.\[[value]] to |responseArray|. 1. Else: - 1. For each |record| in |targetStorage|: - 1. Set |cachedURL| to |record|[0]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. - 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: - 1. Set |cachedURL|'s query to the empty string. - 1. Set |requestURL|'s query to the empty string. - 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: - 1. Add |record|[0] to |requestArray|. - 1. Add |record|[1] to |responseArray|. + 1. For each |record| in |targetStorage|: + 1. Set |cachedURL| to |record|[0]'s associated request's url. + 1. Set |requestURL| to |request|'s associated request's url. + 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: + 1. Set |cachedURL|'s query to the empty string. + 1. Set |requestURL|'s query to the empty string. + 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Add |record|[0] to |requestArray|. + 1. Add |record|[1] to |responseArray|. 1. For each |cachedResponse| in |responseArray| with the index |index|: - 1. Let |cachedRequest| be the |index|th element in |requestArray|. - 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: - 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. - 1. Continue to the next iteration of the loop. - 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. - 1. Let |matchFailed| be false. - 1. For each |f| in |varyHeaders|: - 1. If |f| matches "*", or the result of running |cachedRequest|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument does not match the result of running |request|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument, then: - 1. Set |matchFailed| to true. - 1. Break the loop. - 1. If |matchFailed| is false, add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. + 1. Let |cachedRequest| be the |index|th element in |requestArray|. + 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: + 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. + 1. Continue to the next iteration of the loop. + 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. Let |matchFailed| be false. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", or the result of running |cachedRequest|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument does not match the result of running |request|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument, then: + 1. Set |matchFailed| to true. + 1. Break the loop. + 1. If |matchFailed| is false, add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. 1. Return |resultArray|. @@ -3253,40 +3251,40 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a promise resolved with no value. 1. Return the result of transforming |promise| with a fulfillment handler that performs the following substeps in parallel: - 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. - 1. Let |addedRecords| be an empty array. - 1. Try running the following substeps atomically: - 1. Let |resultArray| be an empty array. - 1. For each |operation| in |operations|: - 1. If |operation|.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError. - 1. If |operation|.{{CacheBatchOperation/type}} matches "delete" and |operation|.{{CacheBatchOperation/response}} is not null, throw a TypeError. - 1. If the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}, |operation|.{{CacheBatchOperation/options}}, and |addedRecords| as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception. - 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}} and |operation|.{{CacheBatchOperation/options}} as the arguments. - 1. For each |requestResponse| in |requestResponseArray|: - 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. - 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: - 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. - 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. - 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. - 1. If |r|'s method is not `GET`, throw a TypeError. - 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. - 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. - 1. If |requestResponseArray| is not an empty array, then: - 1. Let |requestResponse| be |requestResponseArray|[0]. - 1. Let |fetchingRecord| be the corresponding fetching record for |requestResponse|[0] and |requestResponse|[1] in request to response map. - 1. Set |fetchingRecord|.\[[key]] to |operation|.{{CacheBatchOperation/request}} and |fetchingRecord|.\[[value]] to |operation|.{{CacheBatchOperation/response}}. - 1. Else: - 1. Set a newly-created fetching record {\[[key]]: |operation|.{{CacheBatchOperation/request}}, \[[value]]: |operation|.{{CacheBatchOperation/response}}} to request to response map. - - Note: The cache commit is allowed as long as the response's headers are available. - - 1. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception. - 1. Add an array [|operation|.request, |operation|.response] to |addedRecords|. - 1. Add |operation|.response to |resultArray|. - 1. Return |resultArray|. - 1. And then, if an exception was thrown, then: - 1. Set the context object's request to response map to |itemsCopy|. - 1. Throw the exception + 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. + 1. Let |addedRecords| be an empty array. + 1. Try running the following substeps atomically: + 1. Let |resultArray| be an empty array. + 1. For each |operation| in |operations|: + 1. If |operation|.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete" and |operation|.{{CacheBatchOperation/response}} is not null, throw a TypeError. + 1. If the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}, |operation|.{{CacheBatchOperation/options}}, and |addedRecords| as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception. + 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}} and |operation|.{{CacheBatchOperation/options}} as the arguments. + 1. For each |requestResponse| in |requestResponseArray|: + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. + 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: + 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. + 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. + 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. + 1. If |r|'s method is not `GET`, throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. + 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. + 1. If |requestResponseArray| is not an empty array, then: + 1. Let |requestResponse| be |requestResponseArray|[0]. + 1. Let |fetchingRecord| be the corresponding fetching record for |requestResponse|[0] and |requestResponse|[1] in request to response map. + 1. Set |fetchingRecord|.\[[key]] to |operation|.{{CacheBatchOperation/request}} and |fetchingRecord|.\[[value]] to |operation|.{{CacheBatchOperation/response}}. + 1. Else: + 1. Set a newly-created fetching record {\[[key]]: |operation|.{{CacheBatchOperation/request}}, \[[value]]: |operation|.{{CacheBatchOperation/response}}} to request to response map. + + Note: The cache commit is allowed as long as the response's headers are available. + + 1. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception. + 1. Add an array [|operation|.request, |operation|.response] to |addedRecords|. + 1. Add |operation|.response to |resultArray|. + 1. Return |resultArray|. + 1. And then, if an exception was thrown, then: + 1. Set the context object's request to response map to |itemsCopy|. + 1. Throw the exception From 93b9caa512151bb133c480dafb7dd0efd483ef85 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 24 Nov 2016 18:35:17 +0000 Subject: [PATCH 08/17] Correcting links pointing at the wrong places --- docs/index.bs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 9e891fa9..a78b9bbe 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -64,6 +64,7 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/ text: origin; for: MessageEvent; url: dom-messageevent-origin text: source; for: MessageEvent; url: dom-messageevent-source text: ports; for: MessageEvent; url: dom-messageevent-ports + text: data; for: MessageEvent; url: dom-messageevent-data type: dfn urlPrefix: browsers.html text: ancestor origins array; for: Location; url: concept-location-ancestor-origins-array @@ -834,19 +835,19 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe oninstall - install + {{install!!event}} onactivate - activate + {{activate!!event}} onfetch - fetch + {{fetch!!event}} onforeignfetch - foreignfetch + {{foreignfetch!!event}} onmessage @@ -920,8 +921,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |clonedMessage| be |cloneRecord|.\[[Clone]]. 1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order. 1. Add a task that runs the following steps to |destination|'s client message queue: - 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type message, which does not bubble and is not cancelable. - 1. Let the data attribute of |e| be initialized to |clonedMessage|. + 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type {{Window/message!!event}}, which does not bubble and is not cancelable. + 1. Let the data attribute of |e| be initialized to |clonedMessage|. 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s origin. 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the service worker associated with |sourceSettings|'s global object. 1. Let the ports attribute of |e| be initialized to |newPorts|. @@ -995,7 +996,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. 1. Wait for |task| to have executed (including its asynchronous steps). 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. - 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: 1. Resolve |promise| with null. 1. Abort these steps. 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. @@ -1195,7 +1196,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe An {{ExtendableEvent}} object has an associated extensions allowed flag. It is initially set. - Service workers have two lifecycle events, install and activate. Service workers use the {{ExtendableEvent}} interface for activate event and install event. + Service workers have two lifecycle events, {{install!!event}} and {{activate!!event}}. Service workers use the {{ExtendableEvent}} interface for {{activate!!event}} event and {{install!!event}} event. Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. @@ -1218,8 +1219,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Service workers define the following behaviors for install event and activate event, respectively: - * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. - * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries. + * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. + * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries.
@@ -1292,7 +1293,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - Service workers have an essential functional event fetch. For fetch event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. + Service workers have an essential functional event {{fetch!!event}}. For {{fetch!!event}} event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. Each event using {{FetchEvent}} interface has an associated potential response (a response), initially set to null, and the following associated flags that are initially unset: @@ -1300,7 +1301,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe * respond-with entered flag * respond-with error flag -

{{FetchEvent/request|event.request}}

@@ -2552,7 +2552,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |installingWorker| be |registration|'s installing worker. 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type install, which does not bubble and is not cancelable. + 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type {{install!!event}}, which does not bubble and is not cancelable. 1. Dispatch |e| at |installingWorker|'s environment settings object's global object. 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: 1. Wait until |e|'s extensions allowed flag is unset. @@ -2619,7 +2619,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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: - 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type activate, which does not bubble and is not cancelable. + 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type {{activate!!event}}, which does not bubble and is not cancelable. 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. 1. Wait for |task| to have executed or been discarded, or the script to have been aborted by the termination of |activeWorker|. @@ -2755,7 +2755,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type fetch, which does not bubble. + 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type {{fetch!!event}}, which does not bubble. 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. @@ -2822,7 +2822,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be a new {{Request}} object associated with |request|. 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type foreignfetch, which does not bubble. + 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type {{foreignfetch!!event}}, which does not bubble. 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. From 6e9d4427cd44f6b6f79a16e0d2073053846a3591 Mon Sep 17 00:00:00 2001 From: Jungkee Song Date: Fri, 25 Nov 2016 15:52:30 +0900 Subject: [PATCH 09/17] Minor - fix typos --- docs/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index a78b9bbe..51937866 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -2434,9 +2434,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |httpsState| be "none". 1. Let |referrerPolicy| be the empty string. 1. Switching on |job|'s worker type, run these substeps with the following options: - : *"classic"* + : "classic" :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". - : *"module"* + : "module" :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. To perform the fetch given |request|, run the following steps if the is top-level flag is set: From 589e1dc4543953b77498ef69d3bc0c251c16aa4f Mon Sep 17 00:00:00 2001 From: Jungkee Song Date: Fri, 25 Nov 2016 17:16:47 +0900 Subject: [PATCH 10/17] Correct a dfn closing tag location --- docs/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.bs b/docs/index.bs index 51937866..e986180d 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -3106,7 +3106,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
-

Match Service Worker for Foreign Fetch

+

Match Service Worker for Foreign Fetch

: Input :: |requestURL|, a URL From e3b00d657d68a16585391bd16e65be39e0a8afb7 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 25 Nov 2016 09:54:37 +0000 Subject: [PATCH 11/17] Hints were breaking styling --- docs/index.bs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index e986180d..b9e3e7de 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1340,7 +1340,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe respondWith(|r|) method *must* run these steps: -
1. If the dispatch flag is unset, then: 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. @@ -1397,7 +1396,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Note: If the 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 wait to respond flag. -
@@ -2712,7 +2710,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: |response|, a response -
1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. 1. Let |eventCanceled| be false. @@ -2785,8 +2782,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Else: 1. Return |response| and continue running these steps in parallel. 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. - -
From e9ebc1fd33ad249d7d7ecd238d8ed39c4f107306 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Fri, 25 Nov 2016 11:18:56 +0000 Subject: [PATCH 12/17] Some link fixes --- docs/index.bs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index b9e3e7de..cd288871 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -649,11 +649,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe oncontrollerchange - controllerchange + {{ServiceWorkerContainer/controllerchange!!event}} onmessage - message + {{ServiceWorkerContainer/message!!event}} @@ -1590,12 +1590,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe fetch {{FetchEvent}} - [Functional event] The http fetch invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) + [Functional event] The http fetch invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) foreignfetch {{FetchEvent}} - [Functional event] The http fetch invokes [[#on-foreign-fetch-request-algorithm]] with |request|. As a result of performing [[#on-foreign-fetch-request-algorithm]], the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) + [Functional event] The http fetch invokes [[#on-foreign-fetch-request-algorithm]] with |request|. As a result of performing [[#on-foreign-fetch-request-algorithm]], the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) message @@ -2153,7 +2153,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The implementers are encouraged to note: - * Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching fetch event. + * Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching {{fetch!!event}} event. * Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with service workers.
From 87cc81762ebf60d88045c3d404514b88e2d03af0 Mon Sep 17 00:00:00 2001 From: Jungkee Song Date: Tue, 29 Nov 2016 15:54:17 +0900 Subject: [PATCH 13/17] Rebase and merge conflicts for the missed commits --- docs/index.bs | 143 +++++++++++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 55 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index cd288871..87c55645 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -144,7 +144,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A service worker has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration. - A service worker has an associated global object (a {{ServiceWorkerGlobalScope}} object or null). + A service worker has an associated global object (a {{ServiceWorkerGlobalScope}} object or null). A service worker is dispatched a set of lifecycle events, install and activate, and functional events including fetch. @@ -1200,7 +1200,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. - Note: To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run Extend Service Worker Lifetime algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event. + Note: To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run [[#extend-service-worker-lifetime-algorithm]] algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event.

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

@@ -1219,8 +1219,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Service workers define the following behaviors for install event and activate event, respectively: - * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. - * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries. + * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. + * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries.
@@ -1371,7 +1371,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |reader| be the result of getting a reader from |response|'s 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 a chunk from |response|'s body's stream with |reader|. + 1. Let |promise| be the result of reading a chunk from |response|'s 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, error |newStream| with a TypeError. @@ -1481,7 +1481,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/response}}'s 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 a chunk from |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. + 1. Let |promise| be the result of reading a chunk from |response|.{{ForeignFetchResponse/response}}'s 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, error |newStream| with a TypeError. @@ -1791,7 +1791,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the optional argument |request| is not omitted, then: 1. If |request| is a {{Request}} object, then: 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with an empty array. + 1. If |r|'s method is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with an empty array. 1. Else if |request| is a string, then: 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |promise| be a new promise. @@ -1832,11 +1832,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |requestArray| be an empty array. 1. For each |request| whose type is {{Request}} in |requests|: 1. Let |r| be |request|'s request. - 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. + 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not \`GET\`, return a promise rejected with a TypeError. 1. For each |request| in |requests|: 1. Let |r| be the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. If |r|'s url's scheme is not one of "http" and "https", then: - 1. Terminate service worker all the ongoing fetches initiated by |requests| with reason *fatal*. + 1. Terminate all the ongoing fetches initiated by |requests| with reason *fatal*. 1. Break the loop. 1. Set |r|'s initiator to "fetch" and destination to "subresource". 1. Add a {{Request}} object associated with |r| to |requestArray|. @@ -1845,7 +1845,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe * Fetch |r|. * To process response for |response|, run these substeps: 1. If |response|'s type is "error", or |response|'s status is not an ok status, reject |responsePromise| with a TypeError. - 1. Else if |response|'s header list contains a header named `Vary`, then: + 1. Else if |response|'s header list contains a header named \`Vary\`, then: 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. 1. Let |matchAsterisk| be false. 1. For each |f| in |varyHeaders|: @@ -1856,7 +1856,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Note: This step ensures that the promise for this fetch resolves as soon as the response's headers become available. - * To process response for |response|, do nothing. + * To process response end-of-body for |response|, do nothing. * To process response done for |response|, do nothing. 1. Add |responsePromise| to |responsePromiseArray|. 1. Let |p| be waiting for all of |responsePromiseArray|. @@ -1900,11 +1900,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: 1. Set |r| to |request|'s request. - 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not `GET`, return a promise rejected with a TypeError. + 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not \`GET\`, return a promise rejected with a TypeError. 1. Else if |request| is a string, then: 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. If |r|'s url's scheme is not one of "http" and "https", return a promise rejected with a TypeError. - 1. If |response|'s associated response's header list contains a header named `Vary`, then: + 1. If |response|'s associated response's header list contains a header named \`Vary\`, then: 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. 1. For each |f| in |varyHeaders|: 1. If |f| matches "*", return a promise rejected with a TypeError. @@ -1946,7 +1946,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, return a promise resolved with false. + 1. If |r|'s method is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with false. 1. Else if |request| is a string, then: 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |operations| be an empty array. @@ -1976,7 +1976,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: 1. Set |r| to |request|'s request. - 1. If |r|'s method is not `GET` and |options|.ignoreMethod is false, resolve |promise| with an empty array. + 1. If |r|'s method is not \`GET\` and |options|.ignoreMethod is false, resolve |promise| with an empty array. 1. Else if |request| is a string, then: 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing a {{Request}} object that represents |r| and |options| as the arguments. @@ -2242,7 +2242,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A job has a referrer (a URL or null). - A job has a promise (a promise). It is initially null. + A job has a job promise (a promise). It is initially null. A job has a list of equivalent jobs (a list of jobs). It is initially the empty list. @@ -2270,10 +2270,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: |job|, a job 1. Let |job| be a new job. - 1. Set |job|'s job type to |jobType|. - 1. Set |job|'s scope url to |scopeURL|. - 1. Set |job|'s script url to |scriptURL|. - 1. Set |job|'s job promise to |promise|. + 1. Set |job|'s job type to |jobType|. + 1. Set |job|'s scope url to |scopeURL|. + 1. Set |job|'s script url to |scriptURL|. + 1. Set |job|'s job promise to |promise|. 1. Set |job|'s client to |client|. 1. If |client| is not null, set |job|'s referrer to |client|'s creation URL. 1. Return |job|. @@ -2291,7 +2291,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Push |job| to the job queue and invoke Run Job. 1. Else: 1. Let |lastJob| be the element at the back of the job queue. - 1. If |job| is equivalent to |lastJob| and |lastJob|'s job promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. + 1. If |job| is equivalent to |lastJob| and |lastJob|'s job promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. 1. Else, push |job| to the job queue.
@@ -2336,9 +2336,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: none - 1. If |job|'s client is not null, queue a task to resolve |job|'s job promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |job|'s client is not null, queue a task to resolve |job|'s job promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s job promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
@@ -2350,9 +2350,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: none - 1. If |job|'s client is not null, queue a task to reject |job|'s job promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |job|'s client is not null, queue a task to reject |job|'s job promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s job promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source.
@@ -2432,14 +2432,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |httpsState| be "none". 1. Let |referrerPolicy| be the empty string. 1. Switching on |job|'s worker type, run these substeps with the following options: + : "classic" - :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, and "serviceworker". + :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, "serviceworker", and the to-be-created environment settings object for this service worker. : "module" - :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. + :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. To perform the fetch given |request|, run the following steps if the is top-level flag is set: - 1. Append `Service-Worker`/`script` to |request|'s header list. + 1. Append \`Service-Worker\`/\`script\` to |request|'s header list. Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. @@ -2453,7 +2454,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Asynchronously complete these steps with a network error. - 1. Let |serviceWorkerAllowed| be the result of parsing `Service-Worker-Allowed` in |response|'s header list. + 1. Let |serviceWorkerAllowed| be the result of parsing \`Service-Worker-Allowed\` in |response|'s header list. Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. @@ -2544,14 +2545,16 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |redundantWorker| be null. 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. Assert: |job|'s job promise is not null. + 1. Assert: |job|'s job promise is not null. 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 scope url and all the service workers whose containing service worker registration is |registration|. 1. Let |installingWorker| be |registration|'s installing worker. 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{InstallEvent}} interface, with the event type {{install!!event}}, which does not bubble and is not cancelable. - 1. Dispatch |e| at |installingWorker|'s environment settings object's global object. + 1. Let |e| be the result of creating an event with {{InstallEvent}}. + 1. Initialize |e|’s {{Event/type}} attribute to {{install!!event}}. + 1. Dispatch |e| at |installingWorker|'s global object. + 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: 1. Wait until |e|'s extensions allowed flag is unset. 1. If the result of waiting for all of |e|'s extend lifetime promises rejected, set |installFailed| to true. @@ -2569,7 +2572,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Set |registration|'s installing worker's imported scripts updated flag. 1. If |registration|'s waiting worker is not null, then: 1. Set |redundantWorker| to |registration|'s waiting worker. - 1. Terminate service worker |redundantWorker|. + 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. @@ -2597,7 +2600,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 service worker |redundantWorker|. + 1. Terminate |redundantWorker|. 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. @@ -2617,8 +2620,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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: - 1. Create a trusted event |e| that uses the {{ExtendableEvent}} interface, with the event type {{activate!!event}}, which does not bubble and is not cancelable. - 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. Let |e| be the result of creating an event with {{ExtendableEvent}}. + 1. Initialize |e|’s {{Event/type}} attribute to {{activate!!event}}. + 1. Dispatch |e| at |activeWorker|'s global object. + 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. 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. @@ -2640,6 +2645,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Call the JavaScript InitializeHostDefinedRealm abstract operation with the following customizations: * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. * Let |realmExecutionContext| be the created execution context. + 1. Set |serviceWorker|'s global object to |workerGlobalScope|. 1. Let |workerEventLoop| be a newly created event loop. 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: @@ -2691,7 +2697,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: None 1. If |serviceWorker| is not running, abort these steps. - 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s environment settings object's global object. + 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s global object. 1. Set |serviceWorkerGlobalScope|'s closing flag to true. 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's task queues, queue them to |serviceWorker|'s containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's task queues without processing them. @@ -2700,6 +2706,25 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Abort the script currently running in |serviceWorker|.
+
+

Extend Service Worker Lifetime

+ + : Input + :: |event|, an {{ExtendableEvent}} object + : Output + :: None + + 1. If |event|'s extend lifetime promises is empty, unset |event|'s extensions allowed flag and abort these steps. + 1. Let |extendLifetimePromises| be an empty array. + 1. Run the following substeps in parallel: + 1. *SetupPromiseArray*: Set |extendLifetimePromises| to a copy of |event|'s extend lifetime promises. + 1. Wait until all the promises in |extendLifetimePromises| settle. + 1. If the length of |extendLifetimePromises| does not equal the length of |event|'s extend lifetime promises, jump to the step labeled *SetupPromiseArray*. + 1. Unset |event|'s extensions allowed flag. + + The user agent *should not* terminate the service worker associated with |event|'s relevant settings object's global object until |event|'s extensions allowed flag is unset. However, the user agent *may* impose a time limit to this lifetime extension. +
+

Handle Fetch

@@ -2752,13 +2777,16 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{FetchEvent}} interface, with the event type {{fetch!!event}}, which does not bubble. - 1. Let the {{FetchEvent/request}} attribute of |e| be initialized to |r|. + 1. Let |e| be the result of creating an event with {{FetchEvent}}. + 1. Initialize |e|’s {{Event/type}} attribute to {{fetch!!event}}. + 1. Initialize |e|’s {{Event/cancelable}} attribute to true. + 1. Initialize |e|’s {{FetchEvent/request}} attribute to |r|. 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s target client id, and to the empty string otherwise. 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s 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 environment settings object's global object. + 1. Dispatch |e| at |activeWorker|'s global object. + 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. 1. If |e|'s wait to respond flag is set, then: 1. Wait until |e|'s wait to respond flag is unset. @@ -2795,7 +2823,6 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: |response|, a response
- 1. ok 1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. 1. Let |eventCanceled| be false. @@ -2817,10 +2844,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be a new {{Request}} object associated with |request|. 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: - 1. Create a trusted event |e| that uses the {{ForeignFetchEvent}} interface, with the event type {{foreignfetch!!event}}, which does not bubble. - 1. Let the {{ForeignFetchEvent/request}} attribute of |e| be initialized to |r|. - 1. Let the {{ForeignFetchEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |request|'s origin. - 1. Dispatch |e| at |activeWorker|'s environment settings object's global object. + 1. Let |e| be the result of creating an event with {{ForeignFetchEvent}}. + 1. Initialize |e|’s {{Event/type}} attribute to {{foreignfetch!!event}}. + 1. Initialize |e|’s {{Event/cancelable}} attribute to true. + 1. Initialize |e|’s {{ForeignFetchEvent/request}} attribute to |r|. + 1. Initialize |e|’s {{ForeignFetchEvent/origin}} attribute to the Unicode serialization of |request|'s origin. + 1. Dispatch |e| at |activeWorker|'s global object. + 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. 1. If |e|'s 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 potential response. @@ -2862,6 +2892,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Handle Functional Event

: Input + :: |event|, an {{ExtendableEvent}} object :: |registration|, a service worker registration :: |callbackSteps|, an algorithm : Output @@ -2870,7 +2901,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 contain the event type for this functional event, then: + 1. If |activeWorker|'s set of event types to handle does not contain |event|'s {{Event/type}}, then: 1. Return and continue running these steps in parallel. 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. 1. Abort these steps. @@ -2879,7 +2910,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. - 1. Queue a task |task| to invoke |callbackSteps| with |activeWorker|'s environment settings object's global object as its argument. + 1. Queue a task |task| to run these substeps: + 1. Invoke |callbackSteps| with |activeWorker|'s global object as its argument. + 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |event|. The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. @@ -2972,19 +3005,19 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |redundantWorker| be null. 1. If |registration|'s installing worker is not null, then: 1. Set |redundantWorker| to |registration|'s installing worker. - 1. Terminate service worker |redundantWorker|. + 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 service worker |redundantWorker|. + 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 service worker |redundantWorker|. + 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. @@ -3199,7 +3232,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |requestArray| be an empty array. 1. Let |responseArray| be an empty array. 1. Let |resultArray| be an empty array. - 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.method is not `GET`, return |resultArray|. + 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.method is not \`GET\`, return |resultArray|. 1. Let |cachedURL| and |requestURL| be null. 1. If the optional argument |targetStorage| is omitted, then: 1. For each fetching record |entry| of its request to response map, in key insertion order: @@ -3223,7 +3256,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Add |record|[1] to |responseArray|. 1. For each |cachedResponse| in |responseArray| with the index |index|: 1. Let |cachedRequest| be the |index|th element in |requestArray|. - 1. If |cachedResponse|'s response's header list contains no header named `Vary`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: + 1. If |cachedResponse|'s response's header list contains no header named \`Vary\`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. 1. Continue to the next iteration of the loop. 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. @@ -3261,7 +3294,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. - 1. If |r|'s method is not `GET`, throw a TypeError. + 1. If |r|'s method is not \`GET\`, throw a TypeError. 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. 1. If |requestResponseArray| is not an empty array, then: @@ -3291,7 +3324,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe An HTTP request to fetch a service worker's script resource will include the following header: - : `Service-Worker` + : \`Service-Worker\` :: Indicates this request is a service worker's script resource request. Note: This header helps administrators log the requests and detect threats. @@ -3302,7 +3335,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe An HTTP response to a service worker's script resource request can include the following header: - : `Service-Worker-Allowed` + : \`Service-Worker-Allowed\` :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. Note: The value is a URL. If a relative URL is given, it is parsed against the script's URL. From 5d841b6082670df45e1cd28834ff8cbf4854300a Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 29 Nov 2016 09:51:50 +0100 Subject: [PATCH 14/17] Pretty sure these ! are typos --- docs/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 87c55645..08c98403 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1372,7 +1372,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 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 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, error |newStream| with a TypeError. 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. @@ -1482,7 +1482,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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|.{{ForeignFetchResponse/response}}'s 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 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, error |newStream| with a TypeError. 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. From 4c0af6ebf6d2e14aa6425d4a44b1847142b52185 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 29 Nov 2016 10:18:09 +0100 Subject: [PATCH 15/17] Revert "Pretty sure these ! are typos" This reverts commit 5d841b6082670df45e1cd28834ff8cbf4854300a. --- docs/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 08c98403..87c55645 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1372,7 +1372,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 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 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, error |newStream| with a TypeError. 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. @@ -1482,7 +1482,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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|.{{ForeignFetchResponse/response}}'s 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 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, error |newStream| with a TypeError. 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. From 157f04877f275998f517d61dbb8182b02bbe7d8b Mon Sep 17 00:00:00 2001 From: Jungkee Song Date: Wed, 30 Nov 2016 14:40:24 +0900 Subject: [PATCH 16/17] Address @mkruisselbrink's comments: use bikeshed shorthands --- docs/index.bs | 966 +++++++++++++++++++++++++------------------------- 1 file changed, 483 insertions(+), 483 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index 87c55645..285a850a 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -115,15 +115,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Web Applications traditionally assume that the network is reachable. This assumption pervades the platform. HTML documents are loaded over HTTP and traditionally fetch all of their sub-resources via subsequent HTTP requests. This places web content at a disadvantage versus other technology stacks. - The service worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the service worker, conceptually, between the network and a document renderer, allowing the service worker to provide content for documents, even while offline. + The [=/service worker=] is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the [=/service worker=], conceptually, between the network and a document renderer, allowing the [=/service worker=] to provide content for documents, even while offline. - Web developers familiar with previous attempts to solve the offline problem have reported a deficit of flexibility in those solutions. As a result, the service worker is highly procedural, providing a maximum of flexibility at the price of additional complexity for developers. Part of this complexity arises from the need to keep service workers responsive in the face of a single-threaded execution model. As a result, APIs exposed by service workers are almost entirely asynchronous, a pattern familiar in other JavaScript contexts but accentuated here by the need to avoid blocking document and resource loading. + Web developers familiar with previous attempts to solve the offline problem have reported a deficit of flexibility in those solutions. As a result, the [=/service worker=] is highly procedural, providing a maximum of flexibility at the price of additional complexity for developers. Part of this complexity arises from the need to keep [=/service workers=] responsive in the face of a single-threaded execution model. As a result, APIs exposed by [=/service workers=] are almost entirely asynchronous, a pattern familiar in other JavaScript contexts but accentuated here by the need to avoid blocking document and resource loading. - Developers using the HTML5 Application Cache have also reported that several attributes of the design contribute to unrecoverable errors. A key design principle of the service worker is that errors should *always* be recoverable. Many details of the update process of service workers are designed to avoid these hazards. + Developers using the HTML5 Application Cache have also reported that several attributes of the design contribute to unrecoverable errors. A key design principle of the [=/service worker=] is that errors should *always* be recoverable. Many details of the update process of [=/service workers=] are designed to avoid these hazards. - Service workers are started and kept alive by their relationship to events, not documents. This design borrows heavily from developer and vendor experience with Shared Workers and Chrome Background Pages. A key lesson from these systems is the necessity to time-limit the execution of background processing contexts, both to conserve resources and to ensure that background context loss and restart is top-of-mind for developers. As a result, service workers bear more than a passing resemblance to Chrome Event Pages, the successor to Background Pages. Service workers may be started by user agents *without an attached document* and may be killed by the user agent at nearly any time. Conceptually, service workers can be thought of as Shared Workers that can start, process events, and die without ever handling messages from documents. Developers are advised to keep in mind that service workers may be started and killed many times a second. + [=/Service workers=] are started and kept alive by their relationship to events, not documents. This design borrows heavily from developer and vendor experience with Shared Workers and Chrome Background Pages. A key lesson from these systems is the necessity to time-limit the execution of background processing contexts, both to conserve resources and to ensure that background context loss and restart is top-of-mind for developers. As a result, [=/service workers=] bear more than a passing resemblance to Chrome Event Pages, the successor to Background Pages. [=/Service workers=] may be started by user agents *without an attached document* and may be killed by the user agent at nearly any time. Conceptually, [=/service workers=] can be thought of as Shared Workers that can start, process events, and die without ever handling messages from documents. Developers are advised to keep in mind that [=/service workers=] may be started and killed many times a second. - Service workers are generic, event-driven, time-limited script contexts that run at an origin. These properties make them natural endpoints for a range of runtime services that may outlive the context of a particular document, e.g. handling push notifications, background data synchronization, responding to resource requests from other origins, or receiving centralized updates to expensive-to-calculate data (e.g., geolocation or gyroscope). + [=/Service workers=] are generic, event-driven, time-limited script contexts that run at an origin. These properties make them natural endpoints for a range of runtime services that may outlive the context of a particular document, e.g. handling push notifications, background data synchronization, responding to resource requests from other origins, or receiving centralized updates to expensive-to-calculate data (e.g., geolocation or gyroscope).
@@ -132,48 +132,48 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Service Worker

- A service worker is a type of web worker. A service worker executes in the registering service worker client's origin. + A service worker is a type of web worker. A [=/service worker=] executes in the registering [=/service worker client=]'s [=/origin=]. - A service worker has an associated state, which is one of *parsed*, *installing*, *installed*, *activating*, *activated*, and *redundant*. It is initially *parsed*. + A [=/service worker=] has an associated state, which is one of *parsed*, *installing*, *installed*, *activating*, *activated*, and *redundant*. It is initially *parsed*. - A service worker has an associated script url (a URL). + A [=/service worker=] has an associated script url (a [=/URL=]). - A service worker has an associated type which is either "classic" or "module". Unless stated otherwise, it is "classic". + A [=/service worker=] has an associated type which is either "classic" or "module". Unless stated otherwise, it is "classic". - A service worker has an associated containing service worker registration (a service worker registration), which contains itself. + A [=/service worker=] has an associated containing service worker registration (a [=/service worker registration=]), which contains itself. - A service worker has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration. + A [=/service worker=] has an associated id (an opaque string), which uniquely identifies itself during the lifetime of its containing service worker registration. - A service worker has an associated global object (a {{ServiceWorkerGlobalScope}} object or null). + A [=/service worker=] has an associated global object (a {{ServiceWorkerGlobalScope}} object or null). - A service worker is dispatched a set of lifecycle events, install and activate, and functional events including fetch. + A [=/service worker=] is dispatched a set of lifecycle events, {{install!!event}} and {{activate!!event}}, and functional events including {{fetch!!event}}. - A service worker has an associated script resource (a script), which represents its own script resource. It is initially set to null. + A [=/service worker=] has an associated script resource (a script), which represents its own script resource. It is initially set to null. A script resource has an associated has ever been evaluated flag. It is initially unset. A script resource has an associated HTTPS state (an HTTPS state value). It is initially "none". - A script resource has an associated referrer policy (a referrer policy). It is initially the empty string. + A script resource has an associated referrer policy (a [=/referrer policy=]). It is initially the empty string. - A service worker has an associated script resource map which is an ordered map where the keys are URLs and the values are responses. + A [=/service worker=] has an associated script resource map which is an ordered map where the keys are [=/URLs=] and the values are [=/responses=]. - A service worker has an associated skip waiting flag. Unless stated otherwise it is unset. + A [=/service worker=] has an associated skip waiting flag. Unless stated otherwise it is unset. - A service worker has an associated imported scripts updated flag. It is initially unset. + A [=/service worker=] has an associated imported scripts updated flag. It is initially unset. - A service worker has an associated set of event types to handle whose element type is an event listener's event type. It is initially set to null. + A [=/service worker=] has an associated set of event types to handle whose element type is an event listener's event type. It is initially set to null. - 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 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. + A [=/service worker=] has an associated list of foreign fetch origins whose element type is a [=/URL=]. It is initially empty.

Lifetime

- The lifetime of a service worker is tied to the execution lifetime of events and not references held by service worker clients to the {{ServiceWorker}} object. + The lifetime of a [=/service worker=] is tied to the execution lifetime of events and not references held by [=/service worker clients=] to the {{ServiceWorker}} object. - A user agent *may* terminate service workers at any time it: + A user agent *may* terminate [=/service workers=] at any time it: * Has no event to handle. * Detects abnormal operation: such as infinite loops and tasks exceeding imposed time limits (if any) while handling the events. @@ -183,28 +183,28 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Service Worker Registration

- A service worker registration is a tuple of a scope url and a set of service workers, an installing worker, a waiting worker, and an active worker. A user agent *may* enable many service worker registrations at a single origin so long as the scope url of the service worker registration differs. A service worker registration of an identical scope url when one already exists in the user agent causes the existing service worker registration to be replaced. + A service worker registration is a tuple of a [=service worker registration/scope url=] and a set of [=/service workers=], an installing worker, a waiting worker, and an active worker. A user agent *may* enable many [=/service worker registrations=] at a single origin so long as the [=service worker registration/scope url=] of the [=/service worker registration=] differs. A [=/service worker registration=] of an identical [=service worker registration/scope url=] when one already exists in the user agent causes the existing [=/service worker registration=] to be replaced. - A service worker registration has an associated scope url (a URL). + A [=/service worker registration=] has an associated scope url (a [=/URL=]). - A service worker registration has an associated registering script url (a URL). + A [=/service worker registration=] has an associated registering script url (a [=/URL=]). - A service worker registration has an associated installing worker (a service worker or null) whose state is *installing*. It is initially set to null. + A [=/service worker registration=] has an associated installing worker (a [=/service worker=] or null) whose [=service worker/state=] is *installing*. It is initially set to null. - A service worker registration has an associated waiting worker (a service worker or null) whose state is *installed*. It is initially set to null. + A [=/service worker registration=] has an associated waiting worker (a [=/service worker=] or null) whose [=service worker/state=] is *installed*. It is initially set to null. - A service worker registration has an associated active worker (a service worker or null) whose state is either *activating* or *activated*. It is initially set to null. + A [=/service worker registration=] has an associated active worker (a [=/service worker=] or null) whose [=service worker/state=] is either *activating* or *activated*. It is initially set to null. - A service worker registration has an associated last update check time. It is initially set to null. + A [=/service worker registration=] has an associated last update check time. It is initially set to null. - A service worker registration has an associated uninstalling flag. It is initially unset. + 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 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 task queues are not processed by any event loops in and of itself. + 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.

Lifetime

- A user agent *must* persistently keep a list of registered service worker registrations unless otherwise they are explicitly unregistered. A user agent has a scope to registration map that stores the entries of the tuple of service worker registration's scope url and the corresponding service worker registration. The lifetime of service worker registrations is beyond that of the {{ServiceWorkerRegistration}} objects which represent them within the lifetime of their corresponding service worker clients. + A user agent *must* persistently keep a list of registered [=/service worker registrations=] unless otherwise they are explicitly unregistered. A user agent has a scope to registration map that stores the entries of the tuple of [=/service worker registration=]'s [=service worker registration/scope url=] and the corresponding [=/service worker registration=]. The lifetime of [=/service worker registrations=] is beyond that of the {{ServiceWorkerRegistration}} objects which represent them within the lifetime of their corresponding [=/service worker clients=].
@@ -213,13 +213,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A service worker client is a type of environment or environment settings object. - A service worker client has an algorithm defined as the origin that returns the service worker client's creation URL's origin if the service worker client is a type of environment, and the service worker client's origin otherwise. + A [=/service worker client=] has an algorithm defined as the origin that returns the [=/service worker client=]'s creation URL's [=url/origin=] if the [=/service worker client=] is a type of environment, and the [=/service worker client=]'s [=environment settings object/origin=] otherwise. - A window client is a service worker client whose global object is a {{Window}} object. + A window client is a [=/service worker client=] whose [=environment settings object/global object=] is a {{Window}} object. - A dedicated worker client is a service worker client whose global object is a {{DedicatedWorkerGlobalScope}} object. + A dedicated worker client is a [=/service worker client=] whose [=environment settings object/global object=] is a {{DedicatedWorkerGlobalScope}} object. - A shared worker client is a service worker client whose global object is a {{SharedWorkerGlobalScope}} object. + A shared worker client is a [=/service worker client=] whose [=environment settings object/global object=] is a {{SharedWorkerGlobalScope}} object. A worker client is either a dedicated worker client or a shared worker client.
@@ -227,24 +227,24 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Selection and Use

- A service worker client independently selects and uses a service worker registration for its own loading and its subresources. The selection of a service worker registration, upon a non-subresource request, is a process of either matching a service worker registration from scope to registration map or inheriting an existing service worker registration from its parent or owner context depending on the request's url. + A [=/service worker client=] independently selects and uses a [=/service worker registration=] for its own loading and its subresources. The selection of a [=/service worker registration=], upon a non-subresource request, is a process of either matching a [=/service worker registration=] from scope to registration map or inheriting an existing [=/service worker registration=] from its parent or owner context depending on the request's [=request/url=]. - When the request's url is not local, a service worker client matches a service worker registration from scope to registration map. That is, the service worker client attempts to consult a service worker registration whose scope url matches its creation URL. + When the request's [=request/url=] is not local, a [=/service worker client=] matches a [=/service worker registration=] from scope to registration map. That is, the [=/service worker client=] attempts to consult a [=/service worker registration=] whose [=service worker registration/scope url=] matches its creation URL. - When the request's url is local, if the service worker client's responsible browsing context is a nested browsing context or the service worker client is a worker client, the service worker client inherits the service worker registration from its parent browsing context's environment or one of the worker's Documents' environment, respectively, if it exists. + When the request's [=request/url=] is local, if the [=/service worker client=]'s responsible browsing context is a nested browsing context or the [=/service worker client=] is a worker client, the [=/service worker client=] inherits the [=/service worker registration=] from its parent browsing context's environment or one of the worker's Documents' environment, respectively, if it exists. - If the selection was successful, the selected service worker registration's active worker starts to control the service worker client. Otherwise, the flow returns to fetch where it falls back to the default behavior. When a service worker client is controlled by an active worker, it is considered that the service worker client is using the active worker's containing service worker registration. + If the selection was successful, the selected [=/service worker registration=]'s active worker starts to control the [=/service worker client=]. Otherwise, the flow returns to [=/fetch=] where it falls back to the default behavior. When a [=/service worker client=] is controlled by an active worker, it is considered that the [=/service worker client=] is using the active worker's containing service worker registration.

Task Sources

- The following additional task sources are used by service workers. + The following additional task sources are used by [=/service workers=]. : The handle fetch task source - :: This task source is used for dispatching fetch events to service workers. + :: This task source is used for dispatching {{fetch!!event}} events to [=/service workers=]. : The handle functional event task source - :: This task source is used for features that dispatch other functional events, e.g. push events, to service workers. + :: This task source is used for features that dispatch other functional events, e.g. {{push!!event}} events, to [=/service workers=]. Note: A user agent may use a separate task source for each functional event type in order to avoid a head-of-line blocking phenomenon for certain functional events.
@@ -252,9 +252,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

User Agent Shutdown

- A user agent *must* maintain the state of its stored service worker registrations across restarts with the following rules: + A user agent *must* maintain the state of its stored [=/service worker registrations=] across restarts with the following rules: - * An installing worker does not persist but discarded. If the installing worker was the only service worker for the service worker registration, the service worker registration is discarded. + * An installing worker does not persist but discarded. If the installing worker was the only [=/service worker=] for the [=/service worker registration=], the [=/service worker registration=] is discarded. * A waiting worker promotes to an active worker. To attain this, the user agent *must* invoke Handle User Agent Shutdown when it terminates. @@ -304,14 +304,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - A {{ServiceWorker}} object represents a service worker. Each {{ServiceWorker}} object is associated with a service worker. Multiple separate objects implementing the {{ServiceWorker}} interface across documents and workers can all be associated with the same service worker simultaneously. + A {{ServiceWorker}} object represents a [=/service worker=]. Each {{ServiceWorker}} object is associated with a [=/service worker=]. Multiple separate objects implementing the {{ServiceWorker}} interface across documents and workers can all be associated with the same [=/service worker=] simultaneously. - A {{ServiceWorker}} object has an associated {{ServiceWorkerState}} object which is itself associated with service worker's state. + A {{ServiceWorker}} object has an associated {{ServiceWorkerState}} object which is itself associated with [=/service worker=]'s state.

{{ServiceWorker/scriptURL}}

- The scriptURL attribute *must* return the service worker's serialized script url. + The scriptURL attribute *must* return the [=/service worker=]'s serialized [=service worker/script url=].
For example, consider a document created by a navigation to https://example.com/app.html which matches via the following registration call which has been previously executed: @@ -336,21 +336,21 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The postMessage(|message|, |transfer|) method *must* run these steps: - 1. If the {{ServiceWorker/state}} attribute value of the context object is "redundant", throw an "{{InvalidStateError}}" exception and abort these steps. - 1. Let |serviceWorker| be the service worker represented by the context object. + 1. If the {{ServiceWorker/state}} attribute value of the context object is {{"redundant"}}, throw an "{{InvalidStateError}}" exception and abort these steps. + 1. Let |serviceWorker| be the [=/service worker=] represented by the context object. 1. Invoke Run Service Worker algorithm with |serviceWorker| as the argument. 1. Let |destination| be the {{ServiceWorkerGlobalScope}} object associated with |serviceWorker|. - 1. Let |targetRealm| be |destination|'s Realm. - 1. Let |incumbentSettings| be the incumbent settings object, and |incumbentGlobal| its global object. + 1. Let |targetRealm| be |destination|'s [=global object/Realm=]. + 1. Let |incumbentSettings| be the incumbent settings object, and |incumbentGlobal| its [=environment settings object/global object=]. 1. Let |cloneRecord| be StructuredCloneWithTransfer(|message|, |transfer|, |targetRealm|). If this throws an exception, rethrow that exception and abort these steps. 1. Let |clonedMessage| be |cloneRecord|.\[[Clone]]. 1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order. 1. Queue a task that runs the following steps: 1. Create an event |e| that uses the {{ExtendableMessageEvent}} interface, with the event type {{message!!event}}, which does not bubble and is not cancelable. 1. Let the {{ExtendableMessageEvent/data}} attribute of |e| be initialized to |clonedMessage|. - 1. Let the {{ExtendableMessageEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |incumbentSettings|'s origin. - 1. If |incumbentGlobal| is a {{ServiceWorkerGlobalScope}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{ServiceWorker}} object that represents |incumbentGlobal|'s service worker. - 1. Else if |incumbentGlobal| is a {{Window}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{WindowClient}} object that represents |incumbentGlobal|'s browsing context. + 1. Let the {{ExtendableMessageEvent/origin}} attribute of |e| be initialized to the Unicode serialization of |incumbentSettings|'s [=environment settings object/origin=]. + 1. If |incumbentGlobal| is a {{ServiceWorkerGlobalScope}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{ServiceWorker}} object that represents |incumbentGlobal|'s [=ServiceWorkerGlobalScope/service worker=]. + 1. Else if |incumbentGlobal| is a {{Window}} object, let the {{ExtendableMessageEvent/source}} attribute of |e| be initialized to a new {{WindowClient}} object that represents |incumbentGlobal|'s [=/browsing context=]. 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|. @@ -400,14 +400,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - A {{ServiceWorkerRegistration}} object represents a service worker registration. Each {{ServiceWorkerRegistration}} object is associated with a service worker registration (a service worker registration). Multiple separate objects implementing the {{ServiceWorkerRegistration}} interface across documents and workers can all be associated with the same service worker registration simultaneously. + A {{ServiceWorkerRegistration}} object represents a [=/service worker registration=]. Each {{ServiceWorkerRegistration}} object is associated with a service worker registration (a [=/service worker registration=]). Multiple separate objects implementing the {{ServiceWorkerRegistration}} interface across documents and workers can all be associated with the same [=/service worker registration=] simultaneously.
installing attribute *must* return the value to which it was last set. - Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same [=/service worker=] are the same objects.
@@ -415,7 +415,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe waiting attribute *must* return the value to which it was last set. - Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same [=/service worker=] are the same objects.
@@ -423,16 +423,16 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe active attribute *must* return the value to which it was last set. - Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same [=/service worker=] are the same objects.

{{ServiceWorkerRegistration/scope}}

- The scope attribute *must* return service worker registration's serialized scope url. + The scope attribute *must* return [=ServiceWorkerRegistration/service worker registration=]'s serialized [=service worker registration/scope url=].
- In the example in section 3.1.1, the value of registration.scope, obtained from navigator.serviceWorker.ready.then(registration => console.log(registration.scope)) for example, will be "https://example.com/". + In the example in [[#service-worker-url]], the value of registration.scope, obtained from navigator.serviceWorker.ready.then(registration => console.log(registration.scope)) for example, will be "https://example.com/".
@@ -442,12 +442,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe update() method *must* run these steps: 1. Let |p| be a promise. - 1. Let |registration| be the service worker registration. + 1. Let |registration| be the [=ServiceWorkerRegistration/service worker registration=]. 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. 1. If |newestWorker| is null, reject |p| with an "{{InvalidStateError}}" exception and abort these steps. - 1. If the context object's relevant settings object's global object |globalObject| is a {{ServiceWorkerGlobalScope}} object, and |globalObject|'s associated service worker's state is *installing*, reject |p| with an "{{InvalidStateError}}" exception and abort these steps. - 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, |p|, and the context object's relevant settings object. - 1. Set |job|'s worker type to |newestWorker|'s type. + 1. If the context object's relevant settings object's [=environment settings object/global object=] |globalObject| is a {{ServiceWorkerGlobalScope}} object, and |globalObject|'s associated [=ServiceWorkerGlobalScope/service worker=]'s state is *installing*, reject |p| with an "{{InvalidStateError}}" exception and abort these steps. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s [=service worker registration/scope url=], |newestWorker|'s [=service worker/script url=], |p|, and the context object's relevant settings object. + 1. Set |job|'s worker type to |newestWorker|'s [=service worker/type=]. 1. Invoke Schedule Job with |job|. 1. Return |p|.
@@ -455,12 +455,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 navigations. unregister() method *must* run these steps: 1. Let |p| be a promise. - 1. Let |job| be the result of running Create Job with *unregister*, the scope url of the service worker registration, null, |p|, and the context object's relevant settings object. + 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, |p|, and the context object's relevant settings object. 1. Invoke Schedule Job with |job|. 1. Return |p|.
@@ -480,7 +480,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe onupdatefound - updatefound + {{updatefound!!event}} @@ -534,23 +534,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The user agent *must* create a {{ServiceWorkerContainer}} object when a {{Navigator}} object or a {{WorkerNavigator}} object is created and associate it with that object. - A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the service worker registrations, and provides access to the state of the service worker registrations and their associated service workers. + A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the [=/service worker registrations=], and provides access to the state of the [=/service worker registrations=] and their associated [=/service workers=]. - A {{ServiceWorkerContainer}} has an associated service worker client, which is a service worker client whose global object is associated with the {{Navigator}} object or the {{WorkerNavigator}} object that the {{ServiceWorkerContainer}} is retrieved from. + A {{ServiceWorkerContainer}} has an associated service worker client, which is a [=/service worker client=] whose [=environment settings object/global object=] is associated with the {{Navigator}} object or the {{WorkerNavigator}} object that the {{ServiceWorkerContainer}} is retrieved from. A {{ServiceWorkerContainer}} object has an associated ready promise (a promise). It is initially set to a new promise. - A {{ServiceWorkerContainer}} object has a task source called the client message queue, initially empty. A client message queue can be enabled or disabled, and is initially disabled. When a {{ServiceWorkerContainer}} object's client message queue is enabled, the event loop *must* use it as one of its task sources. When the {{ServiceWorkerContainer}} object's relevant global object is a {{Window}} object, all tasks queued on its client message queue *must* be associated with its relevant settings object's responsible document. + A {{ServiceWorkerContainer}} object has a task source called the client message queue, initially empty. A [=ServiceWorkerContainer/client message queue=] can be enabled or disabled, and is initially disabled. When a {{ServiceWorkerContainer}} object's [=ServiceWorkerContainer/client message queue=] is enabled, the event loop *must* use it as one of its task sources. When the {{ServiceWorkerContainer}} object's relevant global object is a {{Window}} object, all tasks queued on its [=ServiceWorkerContainer/client message queue=] *must* be associated with its relevant settings object's responsible document.
controller attribute *must* run these steps: - 1. Let |client| be the context object's service worker client. + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. 1. Return the {{ServiceWorker}} object that represents |client|'s active service worker. - Note: {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects. + Note: {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same [=/service worker=] are the same objects.
@@ -558,8 +558,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe ready attribute *must* run these steps: - 1. If the context object's ready promise is settled, return the context object's ready promise. - 1. Let |client| be the context object's service worker client. + 1. If the context object's [=ServiceWorkerContainer/ready promise=] is settled, return the context object's [=ServiceWorkerContainer/ready promise=]. + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. 1. Let |registration| be null. 1. Let |clientURL| be |client|'s creation URL. 1. Run the following substeps in parallel: @@ -572,25 +572,25 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Note: Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm. - 1. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents |registration|. - 1. Return context object's ready promise. + 1. Resolve context object's [=ServiceWorkerContainer/ready promise=] with the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Return context object's [=ServiceWorkerContainer/ready promise=]. - Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker. + Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a [=/service worker registration=] that has an active worker.
- Note: The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a service worker registration for the given scope url. If successful, a service worker registration ties the provided |scriptURL| to a scope url, which is subsequently used for navigation matching. + Note: The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a [=/service worker registration=] for the given [=service worker registration/scope url=]. If successful, a [=/service worker registration=] ties the provided |scriptURL| to a [=service worker registration/scope url=], which is subsequently used for navigation matching. register(|scriptURL|, |options|) method *must* run these steps: 1. Let |p| be a promise. - 1. Let |client| be the context object's service worker client. + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. 1. Let |scriptURL| be the result of parsing |scriptURL| with the context object's relevant settings object's API base URL. 1. Let |scopeURL| be null. 1. If |options|.{{RegistrationOptions/scope}} is present, set |scopeURL| to the result of parsing |options|.{{RegistrationOptions/scope}} with the context object's relevant settings object's API base URL. - 1. Invoke [[#start-register-algorithm]] with |scopeURL|, |scriptURL|, |p|, |client|, |client|'s creation URL and |options|.{{RegistrationOptions/type}}. + 1. Invoke [=Start Register=] with |scopeURL|, |scriptURL|, |p|, |client|, |client|'s creation URL and |options|.{{RegistrationOptions/type}}. 1. Return |p|.
@@ -599,10 +599,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe getRegistration(|clientURL|) method *must* run these steps: - 1. Let |client| be the context object's service worker client. + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. 1. Let |clientURL| be the result of parsing |clientURL| with the context object's relevant settings object's API base URL. 1. If |clientURL| is failure, return a promise rejected with a TypeError. - 1. If the origin of |clientURL| is not |client|'s origin, return a |promise| rejected with a "{{SecurityError}}" exception. + 1. If the [=environment settings object/origin=] of |clientURL| is not |client|'s [=environment settings object/origin=], return a |promise| rejected with a "{{SecurityError}}" exception. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: 1. Let |registration| be the result of running Match Service Worker Registration algorithm with |clientURL| as its argument. @@ -618,12 +618,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe getRegistrations() method *must* run these steps: - 1. Let |client| be the context object's service worker client. + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: 1. Let |array| be an empty array. - 1. For each |key| → |value| of scope to registration map: - 1. If the origin of the result of parsing |key| is the same as |client|'s origin, and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. + 1. [=map/For each=] |key| → |value| of scope to registration map: + 1. If the [=url/origin=] of the result of parsing |key| is the same as |client|'s [=environment settings object/origin=], and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. 1. Resolve |promise| with |array|. 1. Return |promise|.
@@ -631,7 +631,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
- startMessages() method *must* enable the context object's client message queue if it is not enabled. + startMessages() method *must* enable the context object's [=ServiceWorkerContainer/client message queue=] if it is not enabled.
@@ -658,7 +658,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe - The first time the context object's {{ServiceWorkerContainer/onmessage}} IDL attribute is set, its client message queue *must* be enabled. + The first time the context object's {{ServiceWorkerContainer/onmessage}} IDL attribute is set, its [=ServiceWorkerContainer/client message queue=] *must* be enabled.
@@ -697,7 +697,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe updatefound {{Event}} - The service worker registration's installing worker changes. (See step 8 of the Install algorithm.) + The [=ServiceWorkerRegistration/service worker registration=]'s installing worker changes. (See step 8 of the Install algorithm.) @@ -716,7 +716,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe controllerchange {{Event}} - The service worker client's active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a service worker causes activation of the service worker registration to occur while service worker clients are using the service worker registration, {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the service worker that controls the service worker client.) + The [=ServiceWorkerContainer/service worker client=]'s active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a [=/service worker=] causes activation of the [=/service worker registration=] to occur while [=/service worker clients=] are using the [=/service worker registration=], {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the [=/service worker=] that controls the [=/service worker client=].) @@ -788,9 +788,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - A {{ServiceWorkerGlobalScope}} object represents the global execution context of a service worker. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a service worker). + A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). - Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a service worker is started, kept alive and killed by their relationship to events, not service worker clients. Any type of synchronous requests must not be initiated inside of a service worker. + Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a [=/service worker=] is started, kept alive and killed by their relationship to events, not [=/service worker clients=]. Any type of synchronous requests must not be initiated inside of a [=/service worker=].

{{ServiceWorkerGlobalScope/clients}}

@@ -801,21 +801,21 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{ServiceWorkerGlobalScope/registration}}

- The registration attribute *must* return the {{ServiceWorkerRegistration}} object that represents the service worker's containing service worker registration. + The registration attribute *must* return the {{ServiceWorkerRegistration}} object that represents the [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration.

{{ServiceWorkerGlobalScope/skipWaiting()}}

- Note: The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this service worker to progress from the registration's waiting position to active even while service worker clients are using the registration. + Note: The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this [=/service worker=] to progress from the [=service worker/registration=]'s waiting position to active even while [=/service worker clients=] are using the [=service worker/registration=]. skipWaiting() method *must* run these steps: 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. Set service worker's skip waiting flag. - 1. If service worker's state is *installed*, then: - 1. Run Activate algorithm passing service worker's registration as the argument. + 1. Set [=/service worker=]'s skip waiting flag. + 1. If [=/service worker=]'s state is *installed*, then: + 1. Run Activate algorithm passing [=/service worker=]'s [=service worker/registration=] as the argument. 1. Resolve |promise| with undefined. 1. Return |promise|.
@@ -880,7 +880,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - A {{Client}} object has an associated service worker client (a service worker client). + A {{Client}} object has an associated service worker client (a [=/service worker client=]). A {{Client}} object has an associated reserved state, which is either true or false. @@ -893,19 +893,19 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{Client/url}}

- The url attribute *must* return the context object's associated service worker client's serialized creation URL. + The url attribute *must* return the context object's associated [=Client/service worker client=]'s serialized creation URL.

{{Client/id}}

- The id attribute *must* return its associated service worker client's id. + The id attribute *must* return its associated [=Client/service worker client=]'s [=environment/id=].

{{Client/reserved}}

- The reserved attribute *must* return the context object's associated reserved state. + The reserved attribute *must* return the context object's associated [=Client/reserved state=].
@@ -914,17 +914,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The postMessage(|message|, |transfer|) method *must* run these steps: 1. Let |sourceSettings| be the context object's relevant settings object. - 1. Let |destination| be the {{ServiceWorkerContainer}} object whose service worker client is the context object's service worker client. + 1. Let |destination| be the {{ServiceWorkerContainer}} object whose [=ServiceWorkerContainer/service worker client=] is the context object's [=Client/service worker client=]. 1. If |destination| is null, throw an "{{InvalidStateError}}" exception. 1. Let |targetRealm| be |destination|'s relevant Realm. 1. Let |cloneRecord| be StructuredCloneWithTransfer(|message|, |transfer|, |targetRealm|). If this throws an exception, rethrow that exception and abort these steps. 1. Let |clonedMessage| be |cloneRecord|.\[[Clone]]. 1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order. - 1. Add a task that runs the following steps to |destination|'s client message queue: + 1. Add a task that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]: 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type {{Window/message!!event}}, which does not bubble and is not cancelable. 1. Let the data attribute of |e| be initialized to |clonedMessage|. - 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s origin. - 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the service worker associated with |sourceSettings|'s global object. + 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s [=environment settings object/origin=]. + 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=]. 1. Let the ports attribute of |e| be initialized to |newPorts|. 1. Dispatch |e| at |destination|.
@@ -944,7 +944,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{WindowClient/ancestorOrigins}}

- The ancestorOrigins attribute *must* return the context object's associated service worker client's ancestor origins array. + The ancestorOrigins attribute *must* return the context object's associated [=Client/service worker client=]'s [=WindowClient/ancestor origins array=].
@@ -955,17 +955,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. + 1. Let |browsingContext| be the context object's associated [=Client/service worker client=]'s [=environment settings object/global object=]'s [=/browsing context=]. 1. Let |visibilityState| be null. 1. Let |focusState| be false. 1. Let |ancestorOrigins| be the empty array. - 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: + 1. Queue a task |task| to run the following substeps on the context object's associated [=Client/service worker client=]'s responsible event loop using the user interaction task source: 1. Run the focusing steps with |browsingContext|. 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. 1. Wait for |task| to have executed. - 1. Let |windowClient| be the result of running Create Window Client algorithm with the context object's associated service worker client, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Let |windowClient| be the result of running Create Window Client algorithm with the context object's associated [=Client/service worker client=], |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. If |windowClient|'s focus state is true, resolve |promise| with |windowClient|. 1. Else, reject |promise| with a TypeError. 1. Return |promise|. @@ -979,24 +979,24 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |url| be the result of parsing |url| with the context object's relevant settings object's API base URL. 1. If |url| is failure, return a promise rejected with a TypeError. 1. If |url| is about:blank, return a promise rejected with a TypeError. - 1. If the context object's associated service worker client's active service worker is not the context object's relevant global object's service worker, return a promise rejected with a TypeError. + 1. If the context object's associated [=Client/service worker client=]'s active service worker is not the context object's relevant global object's [=ServiceWorkerGlobalScope/service worker=], return a promise rejected with a TypeError. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. Let |browsingContext| be the context object's associated service worker client's global object's browsing context. + 1. Let |browsingContext| be the context object's associated [=Client/service worker client=]'s [=environment settings object/global object=]'s [=/browsing context=]. 1. If |browsingContext| has discarded its {{Document}}, reject |promise| with a TypeError and abort these steps. 1. Let |navigateFailed| to false. 1. Let |visibilityState| be null. 1. Let |focusState| be false. 1. Let |ancestorOrigins| be the empty array. - 1. Queue a task |task| to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: + 1. Queue a task |task| to run the following substeps on the context object's associated [=Client/service worker client=]'s responsible event loop using the user interaction task source: 1. *HandleNavigate*: Navigate |browsingContext| to |url| with exceptions enabled. The source browsing context must be |browsingContext|. 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |navigateFailed| to true. 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. 1. Wait for |task| to have executed (including its asynchronous steps). 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. - 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's [=url/origin=] is not the same as the [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=], then: 1. Resolve |promise| with null. 1. Abort these steps. 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. @@ -1043,8 +1043,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Run these substeps in parallel: - 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: - 1. If |client|'s id is not |id|, continue to the next iteration of the loop. + 1. For each [=/service worker client=] |client| whose [=service worker client/origin=] is the same as the associated [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=]: + 1. If |client|'s [=environment/id=] is not |id|, continue to the next iteration of the loop. 1. If |client| is a type of environment, then: 1. If |client|’s creation URL is not a potentially trustworthy URL, reject |promise| with a "{{SecurityError}}" exception and abort these steps. 1. Else: @@ -1054,12 +1054,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |visibilityState| be null. 1. Let |focusState| be false. 1. Let |ancestorOrigins| be the empty array. - 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. - 1. Else, set |browsingContext| to |client|'s global object's browsing context. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s [=environment/target browsing context=]. + 1. Else, set |browsingContext| to |client|'s [=environment settings object/global object=]'s [=/browsing context=]. 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. 1. Wait for |task| to have executed. 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. Resolve |promise| with |windowClient| and abort these steps. @@ -1078,32 +1078,32 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |promise| be a new promise. 1. Run these substeps in parallel: 1. Let |targetClients| be an empty array. - 1. For each service worker client |client| whose origin is the same as the associated service worker's origin: + 1. For each [=/service worker client=] |client| whose [=service worker client/origin=] is the same as the associated [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=]: 1. If |client| is a type of environment, then: 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. 1. Else: 1. If |client| is not a secure context, continue to the next iteration of the loop. 1. If |options|.{{ClientQueryOptions/includeUncontrolled}} is false, then: - 1. If |client|'s active service worker is not the associated service worker, continue to the next iteration of the loop. + 1. If |client|'s active service worker is not the associated [=ServiceWorkerGlobalScope/service worker=], continue to the next iteration of the loop. 1. If |options|.{{ClientQueryOptions/includeReserved}} is false, then: - 1. If |client|'s execution ready flag is unset, continue to the next iteration of the loop. + 1. If |client|'s [=environment/execution ready flag=] is unset, continue to the next iteration of the loop. 1. Add |client| to |targetClients|. 1. Let |matchedClients| be an empty array. - 1. For each service worker client |client| in |targetClients|: - 1. If |options|.{{ClientQueryOptions/type}} is "window" or "all", and |client| is a type of environment or is a window client, then: + 1. For each [=/service worker client=] |client| in |targetClients|: + 1. If |options|.{{ClientQueryOptions/type}} is {{ClientType/"window"}} or {{ClientType/"all"}}, and |client| is a type of environment or is a window client, then: 1. Let |browsingContext| be null. 1. Let |isClientEnumerable| be true. 1. Let |visibilityState| be the empty string. 1. Let |focusState| be false. 1. Let |ancestorOrigins| be the empty array. - 1. If |client| is a type of environment, set |browsingContext| to |client|’s target browsing context. - 1. Else, set |browsingContext| to |client|'s global object's browsing context. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s [=environment/target browsing context=]. + 1. Else, set |browsingContext| to |client|'s [=environment settings object/global object=]'s [=/browsing context=]. 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: 1. If |browsingContext| has been discarded, set |isClientEnumerable| to false and abort these steps. 1. If |client| is a window client and |client|'s responsible document is not |browsingContext|'s active document, set |isClientEnumerable| to false and abort these steps. 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. - 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. 1. Wait for |task| to have executed. Note: Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken. @@ -1111,13 +1111,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |isClientEnumerable| is true, then: 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. 1. Add |windowClient| to |matchedClients|. - 1. Else if |options|.{{ClientQueryOptions/type}} is "worker" or "all" and |client| is a dedicated worker client, or |options|.{{ClientQueryOptions/type}} is "sharedworker" or "all" and |client| is a shared worker client, then: + 1. Else if |options|.{{ClientQueryOptions/type}} is {{ClientType/"worker"}} or {{ClientType/"all"}} and |client| is a dedicated worker client, or |options|.{{ClientQueryOptions/type}} is {{ClientType/"sharedworker"}} or {{ClientType/"all"}} and |client| is a shared worker client, then: 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. 1. Add |clientObject| to |matchedClients|. 1. Sort |matchedClients| such that: - * {{WindowClient}} objects are always placed before {{Client}} objects whose associated service worker clients are worker clients. - * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their service worker clients' creation order. - * {{Client}} objects whose associated service worker clients are worker clients are placed next sorted in their service worker clients' creation order. + * {{WindowClient}} objects are always placed before {{Client}} objects whose associated [=Client/service worker clients=] are worker clients. + * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their [=Client/service worker clients=]' creation order. + * {{Client}} objects whose associated [=Client/service worker clients=] are worker clients are placed next sorted in their [=Client/service worker clients=]' creation order. 1. Resolve |promise| with |matchedClients|. 1. Return |promise|.
@@ -1142,10 +1142,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |openWindowFailed| to true. 1. Set |visibilityState| to |newContext|'s active document's {{Document/visibilityState}} attribute value. 1. Set |focusState| to the result of running the has focus steps with |newContext|'s active document as the argument. - 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's ancestor origins array. + 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. 1. Wait for |task| to have executed (including its asynchronous steps). 1. If |openWindowFailed| is true, reject |promise| with a TypeError and abort these steps. - 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: + 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's [=environment settings object/origin=] is not the same as the [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=], then: 1. Resolve |promise| with null. 1. Abort these steps. 1. Let |client| be the result of running Create Window Client algorithm with |newContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. @@ -1158,19 +1158,19 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The claim() method *must* run these steps: - 1. If the service worker is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception. + 1. If the [=ServiceWorkerGlobalScope/service worker=] is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception. 1. Let |promise| be a new promise. 1. Run the following substeps in parallel: - 1. For each service worker client |client| whose origin is the same as the service worker's origin: + 1. For each [=/service worker client=] |client| whose [=service worker client/origin=] is the same as the [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=]: 1. If |client| is a type of environment, then: 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. 1. Else: 1. If |client| is not a secure context, continue to the next iteration of the loop. 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 service worker's containing service worker registration, continue to the next iteration of the loop. - 1. If |client|'s active service worker is not the service worker, then: + 1. If |registration| is not the [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration, continue to the next iteration of the loop. + 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 service worker. + 1. Set |client|'s active service worker to [=ServiceWorkerGlobalScope/service worker=]. 1. Invoke Notify Controller Change algorithm with |client| as the argument. 1. Resolve |promise| with undefined. 1. Return |promise|. @@ -1196,11 +1196,11 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe An {{ExtendableEvent}} object has an associated extensions allowed flag. It is initially set. - Service workers have two lifecycle events, {{install!!event}} and {{activate!!event}}. Service workers use the {{ExtendableEvent}} interface for {{activate!!event}} event and {{install!!event}} event. + [=/Service workers=] have two lifecycle events, {{install!!event}} and {{activate!!event}}. [=/Service workers=] use the {{ExtendableEvent}} interface for {{activate!!event}} event and {{install!!event}} event. Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. - Note: To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run [[#extend-service-worker-lifetime-algorithm]] algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event. + Note: To extend the lifetime of a [=/service worker=], algorithms that dispatch events using the {{ExtendableEvent}} interface run [=Extend Service Worker Lifetime=] algorithm after dispatching the event. See Handle Fetch, Handle Foreign Fetch, and Handle Functional Event.

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

@@ -1212,15 +1212,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the extensions allowed flag is unset, then: 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. - 1. Add |f| to the extend lifetime promises. + 1. Add |f| to the [=ExtendableEvent/extend lifetime promises=].
- Service workers and extensions that define event handlers *may* define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure. + [=/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. - Service workers define the following behaviors for install event and activate event, respectively: + [=/Service workers=] define the following behaviors for install event and activate event, respectively: - * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a service worker is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. - * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the service worker until it upgrades database schemas and deletes the outdated cache entries. + * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a [=/service worker=] is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. + * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the [=/service worker=] until it upgrades database schemas and deletes the outdated cache entries.
@@ -1249,22 +1249,22 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. 1. If |options|.{{ForeignFetchOptions/origins}} is empty throw a TypeError and abort these steps. - 1. Let |originURLs| be an empty list of URLs. + 1. Let |originURLs| be an empty list of [=/URLs=]. 1. If the value of |options|.{{ForeignFetchOptions/origins}} is not a single string equal to a single U+002A ASTERISK character (*): 1. For each |origin| in |options|.origins: 1. If the value of |origin| is not an absolute-URL string, throw a TypeError and abort these steps. 1. Add the result of parsing |origin| to |originURLs|. 1. If |options|.{{ForeignFetchOptions/scopes}} is empty throw a TypeError and abort these steps. - 1. Let |scopeString| be the context object's relevant global object's service worker's containing service worker registration's scope url, serialized. - 1. Let |subScopeURLs| be an empty list of URLs. + 1. Let |scopeString| be the context object's relevant global object's [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration's [=service worker registration/scope url=], serialized. + 1. Let |subScopeURLs| be an empty list of [=/URLs=]. 1. For each |subScope| in |options|.{{ForeignFetchOptions/scopes}}: 1. Let |subScopeURL| be the result of parsing |subScope| with context object's relevant settings object's API base URL. 1. If |subScopeURL| is failure, throw a TypeError and abort these steps. 1. Let |subScopeString| be the serialized |subScopeURL|. 1. If |subScopeString| does not start with |scopeString|, throw a TypeError and abort these steps. 1. Add |subScopeURL| to |subScopeURLs|. - 1. Set this service worker's list of foreign fetch scopes to |subScopeURLs|. - 1. Set this service worker's list of foreign fetch origins to |originURLs|. + 1. Set this [=/service worker=]'s list of foreign fetch scopes to |subScopeURLs|. + 1. Set this [=/service worker=]'s list of foreign fetch origins to |originURLs|.
@@ -1293,9 +1293,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - Service workers have an essential functional event {{fetch!!event}}. For {{fetch!!event}} event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. + [=/Service workers=] have an essential functional event {{fetch!!event}}. For {{fetch!!event}} event, [=/service workers=] use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. - Each event using {{FetchEvent}} interface has an associated potential response (a response), initially set to null, and the following associated flags that are initially unset: + Each event using {{FetchEvent}} interface has an associated potential response (a [=/response=]), initially set to null, and the following associated flags that are initially unset: * wait to respond flag * respond-with entered flag @@ -1336,14 +1336,14 @@ 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. If the dispatch flag is unset, then: 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. - 1. If the respond-with entered flag is set, then: + 1. If the [=FetchEvent/respond-with entered flag=] is set, then: 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. 1. Add |r| to the extend lifetime promises. @@ -1351,51 +1351,51 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 respond-with entered flag. - 1. Set the wait to respond 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 respond-with error flag. + 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 disturbed or locked, then: - 1. Set the respond-with error flag. + 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, except for its body. - 1. If |response|'s body is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|'s body's stream. + 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 body's stream with |reader|. + 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, error |newStream| with a TypeError. - 1. Let |cancel| be an action that cancels |response|'s body's stream with |reader|. - 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. - 1. Set |potentialResponse|'s body to a new body whose stream is |newStream|. + 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 close |newStream| and 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. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. + 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 body's stream into |potentialResponse|. + Note: These substeps are meant to produce the observable equivalent of "piping" |response|'s [=response/body=]'s stream into |potentialResponse|. - 1. Set the potential response to |potentialResponse|. + 1. Set the [=FetchEvent/potential response=] to |potentialResponse|. 1. Else: - 1. Set the respond-with error flag. + 1. Set the [=FetchEvent/respond-with error flag=]. - Note: If the 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 wait to respond flag. + 1. Unset the [=FetchEvent/wait to respond flag=].
@@ -1423,9 +1423,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - Service workers have a functional event foreignfetch. For foreignfetch events, service workers use the {{ForeignFetchEvent}} interface which extends the {{ExtendableEvent}} interface. + [=/Service workers=] have a functional event {{foreignfetch!!event}}. For {{foreignfetch!!event}} events, [=/service workers=] use the {{ForeignFetchEvent}} interface which extends the {{ExtendableEvent}} interface. - Each event using {{ForeignFetchEvent}} interface has an associated potential response (a response), initially set to null, an associated origin (a {{USVString}} or null), initially set to null, an associated list of exposed headers (whose element type is a byte string), initially set to an empty list, and the following associated flags that are initially unset: + Each event using {{ForeignFetchEvent}} interface has an associated potential response (a [=/response=]), initially set to null, an associated origin (a {{USVString}} or null), initially set to null, an associated list of exposed headers (whose element type is a byte string), initially set to an empty list, and the following associated flags that are initially unset: * wait to respond flag * respond-with entered flag @@ -1446,7 +1446,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{ForeignFetchEvent/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: @@ -1454,55 +1454,55 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the dispatch flag is unset, then: 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. - 1. If the respond-with entered flag is set, then: + 1. If the [=ForeignFetchEvent/respond-with entered flag=] is set, then: 1. Throw an "{{InvalidStateError}}" exception. 1. Abort these steps. 1. Add |r| to the extend lifetime promises. 1. Set the stop propagation flag and stop immediate propagation flag. - 1. Set the respond-with entered flag. - 1. Set the wait to respond flag. + 1. Set the [=ForeignFetchEvent/respond-with entered flag=]. + 1. Set the [=ForeignFetchEvent/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 respond-with error flag. + 1. Set the [=ForeignFetchEvent/respond-with error flag=]. 1. If |r| resolved with |response|, then: 1. If |response| is a {{ForeignFetchResponse}}, then: - 1. Set the origin to |response|.{{ForeignFetchResponse/origin}}. + 1. Set the [=ForeignFetchEvent/origin=] to |response|.{{ForeignFetchResponse/origin}}. 1. Set the list of exposed headers to |response|.{{ForeignFetchResponse/headers}}. 1. If |response|.{{ForeignFetchResponse/response}} is disturbed or locked, then: - 1. Set the respond-with error flag. + 1. Set the [=ForeignFetchEvent/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|.{{ForeignFetchResponse/response}}'s associated response, except for its body. + 1. Let |potentialResponse| be a copy of |response|.{{ForeignFetchResponse/response}}'s associated [=/response=], except for its [=response/body=]. 1. If |response|.{{ForeignFetchResponse/response}}'s body is non-null, run these substeps: - 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/response}}'s body's stream. + 1. Let |reader| be the result of getting a reader from |response|.{{ForeignFetchResponse/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|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. + 1. Let |promise| be the result of reading a chunk from |response|.{{ForeignFetchResponse/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, error |newStream| with a TypeError. - 1. Let |cancel| be an action that cancels |response|.{{ForeignFetchResponse/response}}'s body's stream with |reader|. - 1. Let |newStream| be the result of construct a ReadableStream object with |strategy|, |pull| and |cancel| in |targetRealm|. - 1. Set |potentialResponse|'s body to a new body whose stream is |newStream|. + 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|.{{ForeignFetchResponse/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 close |newStream| and 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. Enqueue a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. - 1. Set the potential response to |potentialResponse|. + 1. [=ReadableStream/Enqueue=] a Uint8Array object created in |targetRealm| and wrapping |buffer| to |newStream|. + 1. Set the [=ForeignFetchEvent/potential response=] to |potentialResponse|. 1. Else: - 1. Set the respond-with error flag. + 1. Set the [=ForeignFetchEvent/respond-with error flag=]. - Note: If the respond-with error flag is set, a network error is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 19.1.) Otherwise, a filtered version of |response| is returned to Fetch through [[#on-foreign-fetch-request-algorithm]] algorithm. (See the step 20.1.) + Note: If the [=ForeignFetchEvent/respond-with error flag=] is set, a network error is returned to [=/Fetch=] through [=Handle Foreign Fetch=] algorithm. (See the step 19.1.) Otherwise, a filtered version of |response| is returned to [=/Fetch=] through [=Handle Foreign Fetch=] algorithm. (See the step 20.1.) - 1. Unset the wait to respond flag. + 1. Unset the [=ForeignFetchEvent/wait to respond flag=].
@@ -1530,7 +1530,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe }; - Service workers define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, service workers use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface. + [=/Service workers=] define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, [=/service workers=] use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface.

{{ExtendableMessageEvent/data|event.data}}

@@ -1541,7 +1541,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

{{ExtendableMessageEvent/origin|event.origin}}

- The origin attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string. It represents the origin of the service worker client that sent the message. + The origin attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string. It represents the [=environment settings object/origin=] of the [=/service worker client=] that sent the message.
@@ -1580,22 +1580,22 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe install {{InstallEvent}} - [Lifecycle event] The service worker's containing service worker registration's installing worker changes. (See step 11.2 of the Install algorithm.) + [Lifecycle event] The [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration's installing worker changes. (See step 11.2 of the Install algorithm.) activate {{ExtendableEvent}} - [Lifecycle event] The service worker's containing service worker registration's active worker changes. (See step 12.2 of the Activate algorithm.) + [Lifecycle event] The [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration's active worker changes. (See step 12.2 of the Activate algorithm.) fetch {{FetchEvent}} - [Functional event] The http fetch invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) + [Functional event] The [=/http fetch=] invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the [=ServiceWorkerGlobalScope/service worker=] returns a [=/response=] to the [=/http fetch=]. The [=/response=], represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) foreignfetch {{FetchEvent}} - [Functional event] The http fetch invokes [[#on-foreign-fetch-request-algorithm]] with |request|. As a result of performing [[#on-foreign-fetch-request-algorithm]], the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) + [Functional event] The [=/http fetch=] invokes [=Handle Foreign Fetch=] with |request|. As a result of performing [=Handle Foreign Fetch=], the [=ServiceWorkerGlobalScope/service worker=] returns a [=/response=] to the [=/http fetch=]. The [=/response=], represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.) message @@ -1610,7 +1610,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
- The serviceworker keyword may be used with <{link}> elements. This keyword creates an external resource link (serviceworker link) that is used to declare a service worker registration and its scope url. + The serviceworker keyword may be used with <{link}> elements. This keyword creates an external resource link (serviceworker link) that is used to declare a [=/service worker registration=] and its [=service worker registration/scope url=].
@@ -1619,20 +1619,20 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the Link header has an "anchor" parameter, abort these steps. 1. Let |contextURL| be the result of parsing the context IRI of the Link header. - 1. If the result of running potentially trustworthy origin with the origin of |contextURL| is Not Trusted, abort these steps. - 1. Let |request| be the request for which this header was received in the response. - 1. If |request|'s client is not a secure context, abort these steps. + 1. If the result of running potentially trustworthy origin with the [=environment settings object/origin=] of |contextURL| is Not Trusted, abort these steps. + 1. Let |request| be the [=/request=] for which this header was received in the response. + 1. If |request|'s [=request/client=] is not a secure context, abort these steps. 1. Let |scriptURL| be the result of parsing the target IRI of the Link header. 1. Let |scopeURL| be null. 1. If the "scope" target attribute of the Link header is present, set |scopeURL| to the result of parsing the "scope" target attribute with |scriptURL|. 1. Let |workerType| be the "workertype" target attribute of the Link header, or "classic" if no such attribute is present. 1. If |workerType| is not a valid {{WorkerType}} value, abort these steps. - 1. Invoke [[#start-register-algorithm]] with |scopeURL|, |scriptURL|, a new promise, null, |contextURL| and |workerType|. + 1. Invoke [=Start Register=] with |scopeURL|, |scriptURL|, a new promise, null, |contextURL| and |workerType|. When a serviceworker link's <{link}> element is inserted into a document, a serviceworker link is created on a <{link}> element that is already in a document tree, or the <{link/href}> or <{link/scope}> attributes of the <{link}> element of a serviceworker link is changed, the user agent *should* run these steps: 1. If the <{link/href}> attribute is the empty string, abort these steps. - 1. Let |client| be the document's service worker client. + 1. Let |client| be the document's [=ServiceWorkerContainer/service worker client=]. 1. If |client| is not a secure context, queue a task to fire an event named error at the <{link}> element, and abort these steps. 1. Let |scriptURL| be the result of parsing the <{link/href}> attribute with the <{link}> element's node document's document base URL. 1. Let |scopeURL| be null. @@ -1640,13 +1640,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |workerType| be the <{link/workertype}> attribute, or "classic" if the <{link/workertype}> attribute is omitted. 1. If |workerType| is not a valid {{WorkerType}} value, queue a task to fire an event named error at the <{link}> element, and abort these steps. 1. Let |promise| be a new promise. - 1. Invoke [[#start-register-algorithm]] with |scopeURL|, |scriptURL|, |promise|, |client|, |client|'s creation URL and |workerType|. + 1. Invoke [=Start Register=] with |scopeURL|, |scriptURL|, |promise|, |client|, |client|'s creation URL and |workerType|. 1. Run the following substeps in parallel: 1. Wait until |promise| settles. 1. If |promise| rejected, queue a task to fire an event named error at the <{link}> element. 1. If |promise| resolved, queue a task to fire an event named load at the <{link}> element. - The serviceworker link element *must not* delay the load event of the element's node document. + The serviceworker link element *must not* [=document/delay the load event=] of the element's node document.
A resource being loaded with the following response header: @@ -1689,7 +1689,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Caches

- To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An origin can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across origins, and they are completely isolated from the browser's HTTP cache. + To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An [=environment settings object/origin=] can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across [=/origins=], and they are completely isolated from the browser's HTTP cache.

Constructs

@@ -1702,13 +1702,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe A name to cache map is an ordered map where the keys are strings that represents a name of the {{Cache}} object, and the values are {{Cache}} objects. - Each origin has an associated name to cache map. + Each [=/origin=] has an associated name to cache map.

Understanding Cache Lifetimes

- The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the service worker script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the service worker that can safely operate on. + The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the [=/service worker=] script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the [=/service worker=] that can safely operate on.
@@ -1790,10 +1790,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If the optional argument |request| is not omitted, then: 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with an empty array. + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/method=] is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with an empty array. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |promise| be a new promise. 1. Run these substeps in parallel: 1. Let |responseArray| be an empty array. @@ -1831,22 +1831,22 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |responsePromiseArray| be an empty array. 1. Let |requestArray| be an empty array. 1. For each |request| whose type is {{Request}} in |requests|: - 1. Let |r| be |request|'s request. - 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not \`GET\`, return a promise rejected with a TypeError. + 1. Let |r| be |request|'s [=Request/request=]. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", or |r|'s [=request/method=] is not \`GET\`, return a promise rejected with a TypeError. 1. For each |request| in |requests|: - 1. Let |r| be the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. - 1. If |r|'s url's scheme is not one of "http" and "https", then: - 1. Terminate all the ongoing fetches initiated by |requests| with reason *fatal*. + 1. Let |r| be the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", then: + 1. [=fetch/Terminate=] all the ongoing fetches initiated by |requests| with reason *fatal*. 1. Break the loop. - 1. Set |r|'s initiator to "fetch" and destination to "subresource". + 1. Set |r|'s [=request/initiator=] to "fetch" and [=request/destination=] to "subresource". 1. Add a {{Request}} object associated with |r| to |requestArray|. 1. Let |responsePromise| be a new promise. 1. Run the following substeps in parallel: - * Fetch |r|. + * [=/Fetch=] |r|. * To process response for |response|, run these substeps: - 1. If |response|'s type is "error", or |response|'s status is not an ok status, reject |responsePromise| with a TypeError. - 1. Else if |response|'s header list contains a header named \`Vary\`, then: - 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. If |response|'s [=response/type=] is "error", or |response|'s [=response/status=] is not an ok status, reject |responsePromise| with a TypeError. + 1. Else if |response|'s [=response/header list=] contains a header [=header/named=] \`Vary\`, then: + 1. Let |varyHeaders| be the array containing the elements corresponding to the [=http/field-values=] of the Vary header. 1. Let |matchAsterisk| be false. 1. For each |f| in |varyHeaders|: 1. If |f| matches "*", set |matchAsterisk| to true and break the loop. @@ -1874,8 +1874,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. For each |response| in |responses|: 1. Let |responseBodyPromise| be a new promise. 1. Run the following substeps in parallel: - 1. Wait for either end-of-file to have been pushed to |response|'s associated response |r|'s body or for |r| to have a termination reason. - 1. If |r| had a termination reason, then: + 1. Wait for either end-of-file to have been pushed to |response|'s associated [=Response/response=] |r|'s [=response/body=] or for |r| to have a [=response/termination reason=]. + 1. If |r| had a [=response/termination reason=], then: 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. 1. Else: @@ -1899,20 +1899,20 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s url's scheme is not one of "http" and "https", or |r|'s method is not \`GET\`, return a promise rejected with a TypeError. + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", or |r|'s [=request/method=] is not \`GET\`, return a promise rejected with a TypeError. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. - 1. If |r|'s url's scheme is not one of "http" and "https", return a promise rejected with a TypeError. - 1. If |response|'s associated response's header list contains a header named \`Vary\`, then: - 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", return a promise rejected with a TypeError. + 1. If |response|'s associated [=Response/response=]'s [=response/header list=] contains a header [=header/named=] \`Vary\`, then: + 1. Let |varyHeaders| be the array containing the elements corresponding to the [=http/field-values=] of the Vary header. 1. For each |f| in |varyHeaders|: 1. If |f| matches "*", return a promise rejected with a TypeError. 1. If |response| is disturbed or locked, return a promise rejected with a TypeError. - 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated response and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. + 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated [=/response=] and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. 1. If |response|'s body is non-null, run these substeps: 1. Let |dummyStream| be an empty {{ReadableStream}} object. - 1. Set |response|'s body to a new body whose stream is |dummyStream|. + 1. Set |response|'s [=response/body=] to a new [=/body=] whose stream is |dummyStream|. 1. Let |reader| be the result of getting a reader from |dummyStream|. 1. Read all bytes from |dummyStream| with |reader|. 1. Let |operations| be an empty array. @@ -1923,8 +1923,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Add |o| to |operations|. 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: - 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated response |r|'s body or for |r| to have a termination reason. - 1. If |r| had a termination reason, then: + 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated [=Response/response=] |r|'s [=response/body=] or for |r| to have a [=response/termination reason=]. + 1. If |r| had a [=response/termination reason=], then: 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. 1. Else: @@ -1945,10 +1945,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with false. + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/method=] is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with false. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |operations| be an empty array. 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "delete". @@ -1975,10 +1975,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Else: 1. Let |r| be null. 1. If |request| is a {{Request}} object, then: - 1. Set |r| to |request|'s request. - 1. If |r|'s method is not \`GET\` and |options|.ignoreMethod is false, resolve |promise| with an empty array. + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/method=] is not \`GET\` and |options|.ignoreMethod is false, resolve |promise| with an empty array. 1. Else if |request| is a string, then: - 1. Set |r| to the associated request of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing a {{Request}} object that represents |r| and |options| as the arguments. 1. For each |requestResponse| in |requestResponseArray|: 1. Add |requestResponse|[0] to |resultArray|. @@ -2006,7 +2006,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The user agent *must* create a {{CacheStorage}} object when a {{Window}} object or a {{WorkerGlobalScope}} object is created and associate it with that global object. - A {{CacheStorage}} object represents a name to cache map of its associated global object's environment settings object's origin. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously. + A {{CacheStorage}} object represents a name to cache map of its associated [=CacheStorage/global object=]'s environment settings object's [=environment settings object/origin=]. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously.

{{CacheStorage/match(request, options)}}

@@ -2015,14 +2015,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |options|.{{CacheQueryOptions/cacheName}} is present, then: 1. Return a new promise |p| and run the following substeps in parallel: - 1. For each |cacheName| → |cache| of name to cache map: + 1. [=map/For each=] |cacheName| → |cache| of name to cache map: 1. If |options|.{{CacheQueryOptions/cacheName}} matches |cacheName|, then: 1. Resolve |p| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache| as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) 1. Abort these steps. 1. Resolve |p| with undefined. 1. Else: 1. Let |p| be a promise resolved with undefined. - 1. For each cacheName → |cache| of name to cache map: + 1. [=map/For each=] cacheName → |cache| of name to cache map: 1. Set |p| to the result of transforming itself with a fulfillment handler that, when called with argument |v|, performs the following substeps in parallel: 1. If |v| is not undefined, return |v|. 1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache|] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) @@ -2035,7 +2035,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe has(|cacheName|) method *must* run these steps: 1. Return a promise resolved with the result of running the following substeps: - 1. For each |key| → value of name to cache map: + 1. [=map/For each=] |key| → value of name to cache map: 1. If |cacheName| matches |key|, then: 1. Return true. 1. Return false. @@ -2048,12 +2048,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |p| be a new promise. 1. Run the following substeps: - 1. For each |key| → |value| of name to cache map: + 1. [=map/For each=] |key| → |value| of name to cache map: 1. If |cacheName| matches |key|, then: 1. Resolve |p| with a new {{Cache}} object which is a copy of |value|. 1. Abort these steps. 1. Let |cache| be a new {{Cache}} object. - 1. Set name to cache map[|cacheName|] to |cache|. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. + 1. [=map/Set=] name to cache map[|cacheName|] to |cache|. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. 1. Resolve |p| with |cache|. 1. Return |p|.
@@ -2083,7 +2083,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Note: The promise returned from this method resolves with the sequence of keys, cache names in DOMString, in insertion order. - 1. Let |cacheKeys| be the result of getting the keys of name to cache map. + 1. Let |cacheKeys| be the result of [=map/get the keys|getting the keys=] of name to cache map. 1. Return |cacheKeys|.
@@ -2095,13 +2095,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Secure Context

- Service workers *must* execute in secure contexts. Service worker clients *must* also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts. + [=/Service workers=] *must* execute in secure contexts. [=/Service worker clients=] *must* also be secure contexts to register a [=/service worker registration=], to get access to the [=/service worker registrations=] and the [=/service workers=], to do messaging with the [=/service workers=], and to be manipulated by the [=/service workers=]. This effectively means that [=/service workers=] and their [=/service worker clients=] *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts.

Content Security Policy

- Whenever a user agent invokes Run Service Worker algorithm with a service worker |serviceWorker|: + Whenever a user agent invokes Run Service Worker algorithm with a [=/service worker=] |serviceWorker|: * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy HTTP header containing the value |policy|, the user agent *must* enforce |policy| for |serviceWorker|. * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy-Report-Only HTTP header containing the value |policy|, the user agent *must* monitor |policy| for |serviceWorker|. @@ -2117,22 +2117,22 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe *This section is non-normative.* - A Service worker executes in the registering service worker client's origin. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other origins. Therefore, service workers cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that service workers create the opportunity for a bad actor to turn a bad day into a bad eternity. + A [=/service worker=] executes in the registering [=/service worker client=]'s [=environment settings object/origin=]. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other [=/origins=]. Therefore, [=/service workers=] cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that [=/service workers=] create the opportunity for a bad actor to turn a bad day into a bad eternity.

{{WorkerGlobalScope/importScripts(urls)}}

- When the importScripts(|urls|) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent *must* import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and |urls|, and with the following steps to perform the fetch given the request |request|: + When the importScripts(|urls|) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent *must* import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and |urls|, and with the following steps to [=fetching scripts/perform the fetch=] given the [=/request=] |request|: - 1. Let |serviceWorker| be |request|'s client's global object's service worker. + 1. Let |serviceWorker| be |request|'s [=request/client=]'s [=environment settings object/global object=]'s [=ServiceWorkerGlobalScope/service worker=]. 1. If |serviceWorker|'s imported scripts updated flag is unset, then: 1. Let |response| be the result of fetching |request|. - 1. If |response|'s unsafe response's type is not "error", and |response|'s status is an ok status, then: - 1. Set script resource map[|request|'s url] to |response| + 1. If |response|'s unsafe response's [=response/type=] is not "error", and |response|'s [=response/status=] is an ok status, then: + 1. [=map/Set=] script resource map[|request|'s [=request/url=]] to |response| 1. Return |response|. 1. Else: - 1. If script resource map[|url|] exists, return script resource map[|url|]. + 1. If script resource map[|url|] [=map/exists=], return script resource map[|url|]. 1. Else, return a network error.
@@ -2142,8 +2142,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe *This section is non-normative.* - Applications tend to cache items that come from a CDN or other origin. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to fetch many sorts of off-origin resources when appropriate CORS headers are set. - Service workers enable this by allowing {{Cache|Caches}} to fetch and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding responses are basic filtered response, the objects stored are {{Response}} objects whose corresponding responses are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding responses are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases. + Applications tend to cache items that come from a CDN or other [=environment settings object/origin=]. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to [=/fetch=] many sorts of off-[=environment settings object/origin=] resources when appropriate CORS headers are set. + [=/Service workers=] enable this by allowing {{Cache|Caches}} to [=/fetch=] and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding [=Response/responses=] are basic filtered response, the objects stored are {{Response}} objects whose corresponding [=Response/responses=] are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding [=Response/responses=] are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases.
@@ -2153,26 +2153,26 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The implementers are encouraged to note: - * Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching {{fetch!!event}} event. - * Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with service workers. + * Plug-ins should not load via [=/service workers=]. As plug-ins may get their security origins from their own urls, the embedding [=/service worker=] cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching {{fetch!!event}} event. + * Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with [=/service workers=].

Privacy

- Service workers introduce new persistent storage features including scope to registration map (for service worker registrations and their service workers), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages *should* be cleared when users intend to clear them and *should* maintain and interoperate with existing user controls e.g. purging all existing persistent storages. + [=/Service workers=] introduce new persistent storage features including scope to registration map (for [=/service worker registrations=] and their [=/service workers=]), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages *should* be cleared when users intend to clear them and *should* maintain and interoperate with existing user controls e.g. purging all existing persistent storages.

Extensibility

- Service workers are extensible from other specifications. + [=/Service workers=] are extensible from other specifications.

Define API bound to Service Worker Registration

- Specifications *may* define an API tied to a service worker registration by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it *may* define the specification specific attributes and methods: + Specifications *may* define an API tied to a [=/service worker registration=] by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it *may* define the specification specific attributes and methods:
       partial interface ServiceWorkerRegistration {
@@ -2212,7 +2212,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
   

Request Functional Event Dispatch

- To request a functional event dispatch to a service worker, specifications *may* invoke Handle Functional Event algorithm with its service worker registration registration and the algorithm |callbackSteps| as the arguments. + To request a functional event dispatch to a [=/service worker=], specifications *may* invoke Handle Functional Event algorithm with its [=/service worker registration=] registration and the algorithm |callbackSteps| as the arguments. Specifications *may* define an algorithm |callbackSteps| where the corresponding functional event can be created and fired with specification specific objects. The algorithm is passed globalObject (a {{ServiceWorkerGlobalScope}} object) at which it *may* fire its functional events. This algorithm is called on a task queued by Handle Functional Event algorithm. @@ -2225,22 +2225,22 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The following definitions are the user agent's internal data structures used throughout the specification. - A scope to registration map is an ordered map where the keys are scope URLs and the values are service worker registrations. + A scope to registration map is an ordered map where the keys are [=service worker registration/scope urls=] and the values are [=/service worker registrations=]. - A job is an abstraction of one of register, update, and unregister request for a service worker registration. + A job is an abstraction of one of register, update, and unregister request for a [=/service worker registration=].
A job has a job type, which is one of *register*, *update*, and *unregister*. - A job has a scope url (a URL). + A job has a scope url (a [=/URL=]). - A job has a script url (a URL). + A job has a script url (a [=/URL=]). A job has a worker type ("classic" or "module"). - A job has a client (a service worker client). It is initially null. + A job has a client (a [=/service worker client=]). It is initially null. - A job has a referrer (a URL or null). + A job has a referrer (a [=/URL=] or null). A job has a job promise (a promise). It is initially null. @@ -2252,30 +2252,30 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Two jobs are equivalent when their job type is the same and: - * For *register* and *update* jobs, both their scope url and the script url are the same. - * For *unregister* jobs, their scope url is the same. + * For *register* and *update* jobs, both their [=service worker registration/scope url=] and the [=service worker/script url=] are the same. + * For *unregister* jobs, their [=service worker registration/scope url=] is the same. - A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue *should* satisfy the general properties of FIFO queue. A user agent *must* maintain a separate job queue for each service worker registration keyed by its scope url. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's scope url. + A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue *should* satisfy the general properties of FIFO queue. A user agent *must* maintain a separate job queue for each [=/service worker registration=] keyed by its [=service worker registration/scope url=]. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's [=service worker registration/scope url=].

Create Job

: Input :: |jobType|, a job type - :: |scopeURL|, a URL - :: |scriptURL|, a URL + :: |scopeURL|, a [=/URL=] + :: |scriptURL|, a [=/URL=] :: |promise|, a promise - :: |client|, a service worker client + :: |client|, a [=/service worker client=] : Output :: |job|, a job 1. Let |job| be a new job. - 1. Set |job|'s job type to |jobType|. - 1. Set |job|'s scope url to |scopeURL|. - 1. Set |job|'s script url to |scriptURL|. - 1. Set |job|'s job promise to |promise|. - 1. Set |job|'s client to |client|. - 1. If |client| is not null, set |job|'s referrer to |client|'s creation URL. + 1. Set |job|'s [=job/job type=] to |jobType|. + 1. Set |job|'s [=job/scope url=] to |scopeURL|. + 1. Set |job|'s [=job/script url=] to |scriptURL|. + 1. Set |job|'s [=job/job promise=] to |promise|. + 1. Set |job|'s [=job/client=] to |client|. + 1. If |client| is not null, set |job|'s [=job/referrer=] to |client|'s creation URL. 1. Return |job|.
@@ -2291,7 +2291,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Push |job| to the job queue and invoke Run Job. 1. Else: 1. Let |lastJob| be the element at the back of the job queue. - 1. If |job| is equivalent to |lastJob| and |lastJob|'s job promise has not settled, append |job| to |lastJob|'s list of equivalent jobs. + 1. If |job| is equivalent to |lastJob| and |lastJob|'s [=job/job promise=] has not settled, append |job| to |lastJob|'s list of equivalent jobs. 1. Else, push |job| to the job queue.
@@ -2336,9 +2336,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: none - 1. If |job|'s client is not null, queue a task to resolve |job|'s job promise with |value| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |job|'s [=job/client=] is not null, queue a task to resolve |job|'s [=job/job promise=] with |value| on |job|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to resolve |equivalentJob|'s job promise with |value| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |equivalentJob|'s [=job/client=] is not null, queue a task to resolve |equivalentJob|'s [=job/job promise=] with |value| on |equivalentJob|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source.
@@ -2350,38 +2350,38 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: none - 1. If |job|'s client is not null, queue a task to reject |job|'s job promise with |reason| on |job|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |job|'s [=job/client=] is not null, queue a task to reject |job|'s [=job/job promise=] with |reason| on |job|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source. 1. For each |equivalentJob| in |job|'s list of equivalent jobs: - 1. If |equivalentJob|'s client is not null, queue a task to reject |equivalentJob|'s job promise with |reason| on |equivalentJob|'s client's responsible event loop using the DOM manipulation task source as the task source. + 1. If |equivalentJob|'s [=job/client=] is not null, queue a task to reject |equivalentJob|'s [=job/job promise=] with |reason| on |equivalentJob|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source.

Start Register

: Input - :: |scopeURL|, a URL or failure or null - :: |scriptURL|, a URL or failure + :: |scopeURL|, a [=/URL=] or failure or null + :: |scriptURL|, a [=/URL=] or failure :: |promise|, a promise - :: |client|, a service worker client - :: |referrer|, a URL + :: |client|, a [=/service worker client=] + :: |referrer|, a [=/URL=] :: |workerType|, a worker type : Output :: none 1. If |scriptURL| is failure, reject |promise| with a TypeError and abort these steps. - 1. If |scriptURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. - 1. If any of the strings in |scriptURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. + 1. If |scriptURL|'s [=url/scheme=] is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. + 1. If any of the strings in |scriptURL|'s [=url/path=] contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. 1. If |scopeURL| is null, set |scopeURL| to the result of parsing the string "./" with |scriptURL|. Note: The scope url for the registration is set to the location of the service worker script by default. 1. If |scopeURL| is failure, reject |promise| with a TypeError and abort these steps. - 1. If |scopeURL|'s scheme is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. - 1. If any of the strings in |scopeURL|'s path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. - 1. Let |job| be the result of running [[#create-job-algorithm]] with *register*, |scopeURL|, |scriptURL|, |promise|, and |client|. + 1. If |scopeURL|'s [=url/scheme=] is not one of "http" and "https", reject |promise| with a TypeError and abort these steps. + 1. If any of the strings in |scopeURL|'s [=url/path=] contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |promise| with a TypeError and abort these steps. + 1. Let |job| be the result of running [=Create Job=] with *register*, |scopeURL|, |scriptURL|, |promise|, and |client|. 1. Set |job|'s worker type to |workerType|. - 1. Set |job|'s referrer to |referrer|. - 1. Invoke [[#schedule-job-algorithm]] with |job|. + 1. Set |job|'s [=job/referrer=] to |referrer|. + 1. Invoke [=Schedule Job=] with |job|.
@@ -2392,24 +2392,24 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: none - 1. If the result of running potentially trustworthy origin with the origin of |job|'s script url as the argument is Not Trusted, then: + 1. If the result of running potentially trustworthy origin with the [=environment settings object/origin=] of |job|'s [=service worker/script url=] as the argument is Not Trusted, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. - 1. If the origin of |job|'s script url is not |job|'s referrer's origin, then: + 1. If the [=environment settings object/origin=] of |job|'s [=service worker/script url=] is not |job|'s [=job/referrer=]'s [=environment settings object/origin=], then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. - 1. If the origin of |job|'s scope url is not |job|'s referrer's origin, then: + 1. If the [=environment settings object/origin=] of |job|'s [=service worker registration/scope url=] is not |job|'s [=job/referrer=]'s [=environment settings object/origin=], then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 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 scope url as the argument. + 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=service worker registration/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 and |job|'s script url equals |newestWorker|'s script url with the *exclude fragments flag* set, then: + 1. If |newestWorker| is not null and |job|'s [=service worker/script url=] [=url/equals=] |newestWorker|'s [=service worker/script url=] with the *exclude fragments flag* set, then: 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Invoke Finish Job with |job| and abort these steps. 1. Else: - 1. Invoke Set Registration algorithm passing |job|'s scope url as its argument. + 1. Invoke Set Registration algorithm passing |job|'s [=service worker registration/scope url=] as its argument. 1. Invoke Update algorithm passing |job| as the argument.
@@ -2421,12 +2421,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: none - 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s scope url as the argument. + 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=service worker registration/scope url=] as the argument. 1. If |registration| is null or |registration|'s uninstalling flag is set, then: 1. Invoke Reject Job Promise with |job| and a 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. - 1. If |job|'s job type is *update*, and |newestWorker|'s script url does not equal |job|'s script url with the *exclude fragments flag* set, then: + 1. If |job|'s job type is *update*, and |newestWorker|'s [=service worker/script url=] does not [=url/equal=] |job|'s [=service worker/script url=] with the *exclude fragments flag* set, then: 1. Invoke Reject Job Promise with |job| and a TypeError. 1. Invoke Finish Job with |job| and abort these steps. 1. Let |httpsState| be "none". @@ -2434,42 +2434,42 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Switching on |job|'s worker type, run these substeps with the following options: : "classic" - :: Fetch a classic worker script given |job|’s serialized script url, |job|’s client, "serviceworker", and the to-be-created environment settings object for this service worker. + :: Fetch a classic worker script given |job|’s serialized [=service worker/script url=], |job|’s [=job/client=], "serviceworker", and the to-be-created environment settings object for this service worker. : "module" - :: Fetch a module worker script graph given |job|’s serialized script url, |job|’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker. + :: Fetch a module worker script graph given |job|’s serialized [=service worker/script url=], |job|’s [=job/client=], "serviceworker", "omit", and the to-be-created environment settings object for this service worker. - To perform the fetch given |request|, run the following steps if the is top-level flag is set: + To [=fetching scripts/perform the fetch=] given |request|, run the following steps if the [=fetching scripts/is top-level=] flag is set: - 1. Append \`Service-Worker\`/\`script\` to |request|'s header list. + 1. Append \`Service-Worker\`/\`script\` to |request|'s [=request/header list=]. Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. - 1. Set |request|'s skip-service-worker flag and |request|'s redirect mode to "error". + 1. Set |request|'s skip-service-worker flag and |request|'s [=request/redirect mode=] to "error". 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: - 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s cache mode to "reload". + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s [=request/cache mode=] to "reload". Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. - 1. Fetch |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the response |response|. - 1. Extract a MIME type from the |response|'s header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: + 1. [=/Fetch=] |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the [=/response=] |response|. + 1. Extract a MIME type from the |response|'s [=response/header list=]. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Asynchronously complete these steps with a network error. - 1. Let |serviceWorkerAllowed| be the result of parsing \`Service-Worker-Allowed\` in |response|'s header list. + 1. Let |serviceWorkerAllowed| be the result of [=header/parse a header value|parsing=] \`Service-Worker-Allowed\` in |response|'s [=response/header list=]. Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. - 1. Set |httpsState| to |response|'s HTTPS state. + 1. Set |httpsState| to |response|'s [=response/HTTPS state=]. 1. Set |referrerPolicy| to the result of parse a referrer policy from a Referrer-Policy header of |response|. 1. If |serviceWorkerAllowed| is failure, then: 1. Asynchronously complete these steps with a network error. - 1. Let |scopeURL| be |registration|'s scope url. + 1. Let |scopeURL| be |registration|'s [=service worker registration/scope url=]. 1. Let |maxScopeString| be null. 1. If |serviceWorkerAllowed| is null, then: - 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s script url's path (including empty strings), separated from each other by "/". + 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s [=service worker/script url=]'s [=url/path=] (including empty strings), separated from each other by "/". 1. Else: - 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s script url. - 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s path (including empty strings), separated from each other by "/". - 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s path (including empty strings), separated from each other by "/". + 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s [=service worker/script url=]. + 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s [=url/path=] (including empty strings), separated from each other by "/". + 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s [=url/path=] (including empty strings), separated from each other by "/". 1. If |scopeString| starts with |maxScopeString|, do nothing. 1. Else: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. @@ -2491,15 +2491,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. - 1. If |newestWorker| is not null, |newestWorker|'s script url equals |job|'s script url with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: + 1. If |newestWorker| is not null, |newestWorker|'s [=service worker/script url=] [=url/equals=] |job|'s [=service worker/script url=] with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. 1. Invoke Finish Job with |job| and abort these steps. 1. Else: - 1. Let |worker| be a new service worker. + 1. Let |worker| be a new [=/service worker=]. 1. Generate a unique opaque string and set |worker|'s id to the value. - 1. Set |worker|'s script url to |job|'s script url, |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. + 1. Set |worker|'s [=service worker/script url=] to |job|'s [=service worker/script url=], |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. 1. Set |worker|'s script resource's HTTPS state to |httpsState|. - 1. Set |worker|'s script resource's referrer policy to |referrerPolicy|. + 1. Set |worker|'s script resource's [=script resource/referrer policy=] to |referrerPolicy|. 1. Invoke Run Service Worker algorithm with |worker| as the argument. 1. If an uncaught runtime script error occurs during the above step, then: 1. Invoke Reject Job Promise with |job| and a TypeError. @@ -2514,7 +2514,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The user agent *may* call this as often as it likes to check for updates. : Input - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] :: *force bypass cache flag*, an optional flag unset by default Note: Implementers may use the *force bypass cache flag* to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs. @@ -2524,8 +2524,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. 1. If |newestWorker| is null, abort these steps. - 1. Let |job| be the result of running Create Job with *update*, |registration|'s scope url, |newestWorker|'s script url, null, and null. - 1. Set |job|'s worker type to |newestWorker|'s type. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s [=service worker registration/scope url=], |newestWorker|'s [=service worker/script url=], null, and null. + 1. Set |job|'s worker type to |newestWorker|'s [=service worker/type=]. 1. Set |job|'s force bypass cache flag if its *force bypass cache flag* is set. 1. Invoke Schedule Job with |job|.
@@ -2535,8 +2535,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Input :: |job|, a job - :: |worker|, a service worker - :: |registration|, a service worker registration + :: |worker|, a [=/service worker=] + :: |registration|, a [=/service worker registration=] : Output :: none @@ -2545,16 +2545,16 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |redundantWorker| be null. 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. Assert: |job|'s job promise is not null. + 1. Assert: |job|'s [=job/job promise=] is not null. 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 scope url and all the service workers whose containing service worker registration is |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 |installingWorker| be |registration|'s installing worker. 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. 1. Queue a task |task| to run the following substeps: 1. Let |e| be the result of creating an event with {{InstallEvent}}. 1. Initialize |e|’s {{Event/type}} attribute to {{install!!event}}. - 1. Dispatch |e| at |installingWorker|'s global object. - 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. + 1. Dispatch |e| at |installingWorker|'s [=service worker/global object=]. + 1. Invoke [=Extend Service Worker Lifetime=] with |e|. 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: 1. Wait until |e|'s extensions allowed flag is unset. 1. If the result of waiting for all of |e|'s extend lifetime promises rejected, set |installFailed| to true. @@ -2583,7 +2583,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Invoke Finish Job with |job| and abort these steps. 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. 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 |waitingWorker| is not null and |waitingWorker|'s skip waiting flag is not set, invoke Activate algorithm with |registration| as its argument.
@@ -2591,7 +2591,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Activate

: Input - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] : Output :: None @@ -2608,13 +2608,13 @@ 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. - 1. For each service worker client |client| whose creation URL matches |registration|'s scope url: + 1. For each [=/service worker client=] |client| whose creation URL matches |registration|'s [=service worker registration/scope url=]: 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 global object from its application cache, if it has one. + 1. Else if |client| is a shared worker client, unassociate |client|'s [=environment settings object/global object=] from its application cache, if it has one. Note: Resources will now use the service worker registration instead of the existing application cache. - 1. For each service worker client |client| who is using |registration|: + 1. 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. @@ -2622,8 +2622,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 {{activate!!event}}. - 1. Dispatch |e| at |activeWorker|'s global object. - 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. + 1. Dispatch |e| at |activeWorker|'s [=service worker/global object=]. + 1. Invoke [=Extend Service Worker Lifetime=] with |e|. 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. 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. @@ -2634,52 +2634,52 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Run Service Worker

: Input - :: |serviceWorker|, a service worker + :: |serviceWorker|, a [=/service worker=] : Output :: None - 1. Let |script| be |serviceWorker|'s script resource. + 1. Let |script| be |serviceWorker|'s [=service worker/script resource=]. 1. Assert: |script| is not null. 1. If |serviceWorker| is already running, abort these steps. 1. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context. 1. Call the JavaScript InitializeHostDefinedRealm abstract operation with the following customizations: * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. * Let |realmExecutionContext| be the created execution context. - 1. Set |serviceWorker|'s global object to |workerGlobalScope|. + 1. Set |serviceWorker|'s [=service worker/global object=] to |workerGlobalScope|. 1. Let |workerEventLoop| be a newly created event loop. 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: - : The realm execution context + : The [=environment settings object/realm execution context=] :: Return |realmExecutionContext|. - : The global object + : The [=environment settings object/global object=] :: Return |workerGlobalScope|. : The responsible event loop :: Return |workerEventLoop|. - : The referrer policy - :: Return |workerGlobalScope|'s referrer policy. + : The [=environment settings object/referrer policy=] + :: Return |workerGlobalScope|'s [=WorkerGlobalScope/referrer policy=]. : The API URL character encoding :: Return UTF-8. : The API base URL - :: Return |serviceWorker|'s script url. - : The origin - :: Return its registering service worker client's origin. + :: Return |serviceWorker|'s [=service worker/script url=]. + : The [=environment settings object/origin=] + :: Return its registering [=/service worker client=]'s [=environment settings object/origin=]. : The creation URL - :: Return |workerGlobalScope|'s url. - : The HTTPS state - :: Return |workerGlobalScope|'s HTTPS state. - - 1. Set |workerGlobalScope|'s url to |serviceWorker|'s script url. - 1. Set |workerGlobalScope|'s HTTPS state to |serviceWorker|'s script resource's HTTPS state. - 1. Set |workerGlobalScope|'s referrer policy to |serviceWorker|'s script resource's referrer policy. - 1. Set |workerGlobalScope|'s type to |serviceWorker|'s type. + :: Return |workerGlobalScope|'s [=WorkerGlobalScope/url=]. + : The [=environment settings object/HTTPS state=] + :: Return |workerGlobalScope|'s [=WorkerGlobalScope/HTTPS state=]. + + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/url=] to |serviceWorker|'s [=service worker/script url=]. + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/HTTPS state=] to |serviceWorker|'s script resource's HTTPS state. + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/referrer policy=] to |serviceWorker|'s script resource's [=script resource/referrer policy=]. + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/type=] to |serviceWorker|'s type. 1. Create a new {{WorkerLocation}} object and associate it with |workerGlobalScope|. - 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's task queues, queue them to |serviceWorker|'s event loop's task queues in the same order using their original task sources. + 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's [=service worker registration/task queues=], queue them to |serviceWorker|'s event loop's [=/task queues=] in the same order using their original task sources. 1. If |script| is a classic script, then run the classic script |script|. Otherwise, it is a module script; run the module script |script|. Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. 1. If |script|'s has ever been evaluated flag is unset, then: - 1. Set |workerGlobalScope|'s associated service worker's set of event types to handle to the set of event types created from |settingsObject|'s global object's associated list of event listeners' event types. + 1. Set |workerGlobalScope|'s associated [=ServiceWorkerGlobalScope/service worker=]'s set of event types to handle to the set of event types created from |settingsObject|'s [=environment settings object/global object=]'s associated list of event listeners' event types. Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. @@ -2692,14 +2692,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Terminate Service Worker

: Input - :: |serviceWorker|, a service worker + :: |serviceWorker|, a [=/service worker=] : Output :: None 1. If |serviceWorker| is not running, abort these steps. - 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s global object. + 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s [=service worker/global object=]. 1. Set |serviceWorkerGlobalScope|'s closing flag to true. - 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's task queues, queue them to |serviceWorker|'s containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's task queues without processing them. + 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's [=/task queues=], queue them to |serviceWorker|'s containing service worker registration's corresponding [=service worker registration/task queues=] in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's [=/task queues=] without processing them. Note: This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded. @@ -2722,30 +2722,30 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If the length of |extendLifetimePromises| does not equal the length of |event|'s extend lifetime promises, jump to the step labeled *SetupPromiseArray*. 1. Unset |event|'s extensions allowed flag. - The user agent *should not* terminate the service worker associated with |event|'s relevant settings object's global object until |event|'s extensions allowed flag is unset. However, the user agent *may* impose a time limit to this lifetime extension. + The user agent *should not* terminate the [=/service worker=] associated with |event|'s relevant settings object's [=environment settings object/global object=] until |event|'s extensions allowed flag is unset. However, the user agent *may* impose a time limit to this lifetime extension.

Handle Fetch

- The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context. + The Handle Fetch algorithm is the entry point for the [=/fetch=] handling handed to the [=/service worker=] context. : Input - :: |request|, a request + :: |request|, a [=/request=] : Output - :: |response|, a response + :: |response|, a [=/response=] 1. Let |handleFetchFailed| be false. 1. Let |respondWithEntered| be false. 1. Let |eventCanceled| be false. 1. Let |r| be a new {{Request}} object associated with |request|. 1. Let |headersObject| be |r|'s {{Request/headers}} attribute value. - 1. Set |headersObject|'s guard to *immutable*. + 1. Set |headersObject|'s [=Headers/guard=] to *immutable*. 1. Let |response| be null. 1. Let |registration| be null. - 1. Let |client| be |request|'s client. - 1. Let |reservedClient| be |request|'s reserved client. - 1. Assert: |request|'s destination is not "serviceworker". + 1. Let |client| be |request|'s [=request/client=]. + 1. Let |reservedClient| be |request|'s [=request/reserved client=]. + 1. Assert: |request|'s [=request/destination=] is not "serviceworker". 1. If |request| is a potential-navigation-or-subresource request, then: 1. Return null. 1. Else if |request| is a non-subresource request, then: @@ -2755,13 +2755,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |reservedClient| is not null and is an environment settings object, then: 1. If |reservedClient| is not a secure context, return null. 1. Else: - 1. If |request|'s url is not a potentially trustworthy URL, return null. + 1. If |request|'s [=request/url=] is not a potentially trustworthy URL, return null. 1. If |request| is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null. - 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s url as the argument. + 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s [=request/url=] as the argument. 1. If |registration| is null or |registration|'s active worker is null, return null. - 1. If |request|'s destination is not "report", set |reservedClient|'s active service worker to |registration|'s active worker. + 1. If |request|'s [=request/destination=] is not {{RequestDestination/"report"}}, set |reservedClient|'s active service worker to |registration|'s active worker. - Note: From this point, the service worker client starts to use its active service worker's containing service worker registration. + Note: From this point, the [=/service worker client=] starts to use its active service worker's containing service worker registration. 1. Else if |request| is a subresource request, then: 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. @@ -2781,17 +2781,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Initialize |e|’s {{Event/type}} attribute to {{fetch!!event}}. 1. Initialize |e|’s {{Event/cancelable}} attribute to true. 1. Initialize |e|’s {{FetchEvent/request}} attribute to |r|. - 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s id. - 1. If |request| is a non-subresource request and |request|'s destination is not "report", initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s id, and to the empty string otherwise. - 1. If |request| is a navigation request, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s target client id, and to the empty string otherwise. - 1. Let the {{FetchEvent/isReload}} attribute of |e| be initialized to true if |request|'s 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 global object. - 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. - 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. - 1. If |e|'s wait to respond flag is set, then: - 1. Wait until |e|'s wait to respond flag is unset. - 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. - 1. Else, set |response| to |e|'s potential response. + 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s [=environment/id=]. + 1. If |request| is a non-subresource request and |request|'s [=request/destination=] is not {{RequestDestination/"report"}}, initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s [=environment/id=], and to the empty string otherwise. + 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 [=Extend Service Worker Lifetime=] with |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. + 1. If |e|'s [=FetchEvent/respond-with error flag=] is set, set |handleFetchFailed| to true. + 1. Else, set |response| to |e|'s [=FetchEvent/potential response=]. 1. If |e|'s canceled flag is set, set |eventCanceled| to true. If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. @@ -2815,12 +2815,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Handle Foreign Fetch

- The [[#on-foreign-fetch-request-algorithm]] algorithm is the entry point for the fetch handling handed to the service worker context to handle foreign fetch requests. + The [=Handle Foreign Fetch=] algorithm is the entry point for the [=/fetch=] handling handed to the [=/service worker=] context to handle foreign fetch requests. : Input - :: |request|, a request + :: |request|, a [=/request=] : Output - :: |response|, a response + :: |response|, a [=/response=]
1. Let |handleFetchFailed| be false. @@ -2830,38 +2830,38 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe Note: Foreign fetch only allows intercepting of subresource requests. Navigation requests can be intercepted by the regular fetch event anyway, so there is no benefit to supporting those requests here as well. - 1. If |request|'s client is not a secure context, return null and abort these steps. - 1. Let |activeWorker| be the result of running the [[#foreign-fetch-scope-match-algorithm]] algorithm passing |request|'s url as the argument. + 1. If |request|'s [=request/client=] is not a secure context, return null and abort these steps. + 1. Let |activeWorker| be the result of running the [=Match Service Worker for Foreign Fetch=] algorithm passing |request|'s [=request/url=] as the argument. 1. If |activeWorker| is null, return null. 1. If |activeWorker|'s state is *activating*, then: 1. Wait for |activeWorker|'s state to become *activated*. - 1. If |activeWorker|'s origin is the same as |request|'s origin, return null. + 1. If |activeWorker|'s [=environment settings object/origin=] is the same as |request|'s [=request/origin=], return null. 1. Let |originMatches| be false. 1. If |activeWorker|'s list of foreign fetch origins is empty, set |originMatches| to true. 1. For each |origin| in |activeWorker|'s list of foreign fetch origins: - 1. If |origin| is equal to |request|'s origin, set |originMatches| to true. + 1. If |origin| is equal to |request|'s [=request/origin=], set |originMatches| to true. 1. If |originMatches| is false, return null. 1. Let |r| be a new {{Request}} object associated with |request|. - 1. Invoke [[#run-service-worker-algorithm]] algorithm with |activeWorker| as the argument. + 1. Invoke [=Run Service Worker=] algorithm with |activeWorker| as the argument. 1. Queue a task |task| to run the following substeps: 1. Let |e| be the result of creating an event with {{ForeignFetchEvent}}. 1. Initialize |e|’s {{Event/type}} attribute to {{foreignfetch!!event}}. 1. Initialize |e|’s {{Event/cancelable}} attribute to true. 1. Initialize |e|’s {{ForeignFetchEvent/request}} attribute to |r|. - 1. Initialize |e|’s {{ForeignFetchEvent/origin}} attribute to the Unicode serialization of |request|'s origin. - 1. Dispatch |e| at |activeWorker|'s global object. - 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |e|. - 1. If |e|'s respond-with entered flag is set, set |respondWithEntered| to true. + 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 [=Extend Service Worker Lifetime=] with |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 potential response. + 1. Let |internalResponse| be |e|'s [=ForeignFetchEvent/potential response=]. 1. If |internalResponse| is a filtered response, set |internalResponse| to |internalResponse|'s internal response. 1. If |e|'s respond-with error flag is set, set |handleFetchFailed| to true. - 1. Else if |e|'s origin is null: + 1. Else if |e|'s [=ForeignFetchEvent/origin=] is null: 1. If |e|'s list of exposed headers is not empty, set |handleFetchFailed| to true. - 1. Else if |e|'s potential response is a opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else if |e|'s [=ForeignFetchEvent/potential response=] is a opaque-redirect filtered response, set |response| to |e|'s [=ForeignFetchEvent/potential response=]. 1. Else set |response| to an opaque filtered response of |internalResponse|. - 1. Else if |e|'s origin is not equal to the Unicode serialization of |request|'s origin, set |handleFetchFailed| to true. - 1. Else if |e|'s potential response is an opaque filtered response or is an opaque-redirect filtered response, set |response| to |e|'s potential response. + 1. Else if |e|'s [=ForeignFetchEvent/origin=] is not equal to the Unicode serialization of |request|'s [=request/origin=], set |handleFetchFailed| to true. + 1. Else if |e|'s [=ForeignFetchEvent/potential response=] is an opaque filtered response or is an opaque-redirect filtered response, set |response| to |e|'s [=ForeignFetchEvent/potential response=]. 1. Else if |request|'s response tainting is "opaque", set |response| to an opaque filtered response of |internalResponse|. 1. Else: 1. Let |headers| be |e|'s list of exposed headers. @@ -2893,7 +2893,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Input :: |event|, an {{ExtendableEvent}} object - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] :: |callbackSteps|, an algorithm : Output :: None @@ -2911,8 +2911,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. 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 global object as its argument. - 1. Invoke [[#extend-service-worker-lifetime-algorithm]] with |event|. + 1. Invoke |callbackSteps| with |activeWorker|'s [=service worker/global object=] as its argument. + 1. Invoke [=Extend Service Worker Lifetime=] with |event|. The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. @@ -2923,17 +2923,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Handle Service Worker Client Unload

- The user agent *must* run these steps when a service worker client unloads by unloading, being killed, or terminating. + The user agent *must* run these steps when a [=/service worker client=] unloads by unloading, being killed, or terminating. : Input - :: |client|, a service worker client + :: |client|, a [=/service worker client=] : Output :: None 1. Run the following steps atomically. - 1. Let |registration| be the service worker registration used by |client|. + 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 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.
@@ -2946,7 +2946,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: None - 1. For each scope → |registration| of scope to registration map: + 1. [=map/For each=] scope → |registration| of scope to registration map: 1. If |registration|'s installing worker |installingWorker| is not null, then: 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. 1. Else, set |registration|'s installing worker to null. @@ -2962,16 +2962,16 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe : Output :: none - 1. If the origin of |job|'s scope url is not |job|'s client's origin, then: + 1. If the [=environment settings object/origin=] of |job|'s [=service worker registration/scope url=] is not |job|'s [=job/client=]'s [=environment settings object/origin=], then: 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. 1. Invoke Finish Job with |job| and abort these steps. - 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s scope url as the argument. + 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s [=service worker registration/scope url=] as the argument. 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. Invoke Resolve Job Promise with |job| and true. - 1. If no service worker client is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. + 1. If no [=/service worker client=] is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. @@ -2982,14 +2982,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Set Registration

: Input - :: |scope|, a URL + :: |scope|, a [=/URL=] : Output - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] 1. Run the following steps atomically. 1. Let |scopeString| be serialized |scope| with the *exclude fragment flag* set. - 1. Let |registration| be a new service worker registration whose scope url is set to |scope|. - 1. Set scope to registration map[|scopeString|] to |registration|. + 1. Let |registration| be a new [=/service worker registration=] whose [=service worker registration/scope url=] is set to |scope|. + 1. [=map/Set=] scope to registration map[|scopeString|] to |registration|. 1. Return |registration|.
@@ -2997,7 +2997,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Clear Registration

: Input - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] : Output :: None @@ -3021,17 +3021,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 scope url with the *exclude fragment flag* set. - 1. Remove scope to registration map[|scopeString|]. + 1. Let |scopeString| be serialized |registration|'s [=service worker registration/scope url=] with the *exclude fragment flag* set. + 1. [=map/Remove=] scope to registration map[|scopeString|].

Update Registration State

: Input - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] :: |target|, a string (one of "installing", "waiting", and "active") - :: |source|, a service worker or null + :: |source|, a [=/service worker=] or null : Output :: None @@ -3045,9 +3045,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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 active worker to |source|. + 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 active worker, or null if |registration|’s active worker is null. + 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.
@@ -3056,8 +3056,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Update Worker State

: Input - :: |worker|, a service worker - :: |state|, a service worker's state + :: |worker|, a [=/service worker=] + :: |state|, a [=/service worker=]'s state : Output :: None @@ -3067,29 +3067,29 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 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" + :: {{"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. + 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" + :: {{"installed"}} - Note: The service worker in this state is considered a waiting worker. + Note: The [=/service worker=] in this state is considered a waiting worker. : *activating* - :: "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*. + 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" + :: {{"activated"}} - Note: The service worker in this state is considered an active worker ready to handle functional events. + Note: The [=/service worker=] in this state is considered an active worker ready to handle functional events. : *redundant* - :: "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. + 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|. @@ -3100,12 +3100,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Notify Controller Change

: Input - :: |client|, a service worker client + :: |client|, a [=/service worker client=] : Output :: None 1. Assert: |client| is not null. - 1. If |client| is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object |client| is associated with. + 1. If |client| is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object |client| is [=ServiceWorkerContainer/service worker client|associated=] with. The task *must* use |client|'s responsible event loop and the DOM manipulation task source. @@ -3114,14 +3114,14 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Match Service Worker Registration

: Input - :: |clientURL|, a URL + :: |clientURL|, a [=/URL=] : Output - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] 1. Run the following steps atomically. 1. Let |clientURLString| be serialized |clientURL|. 1. Let |matchingScope| be the empty string. - 1. Let |allScopes| be the result of getting the keys from scope to registration map. + 1. Let |allScopes| be the result of [=map/get the keys|getting the keys=] from scope to registration map. 1. Set |matchingScope| to the longest value in |allScopes| which the value of |clientURLString| starts with, if it exists. Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). @@ -3137,17 +3137,17 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Match Service Worker for Foreign Fetch

: Input - :: |requestURL|, a URL + :: |requestURL|, a [=/URL=] : Output - :: |worker|, a service worker + :: |worker|, a [=/service worker=] 1. Run the following steps atomically. - 1. Let |registration| be the result of running the [[#scope-match-algorithm]] algorithm passing |requestURL| as the argument. + 1. Let |registration| be the result of running the [=Match Service Worker Registration=] algorithm passing |requestURL| as the argument. 1. If |registration| is null, return null. - 1. Let |worker| be |registration|'s active worker. + 1. Let |worker| be |registration|'s [=service worker registration/active worker=]. 1. If |worker| is null, return null. 1. Let |requestURLString| be the serialized |requestURL|. - 1. For each URL |scope| in |worker|'s list of foreign fetch scopes: + 1. For each [=/URL=] |scope| in |worker|'s list of foreign fetch scopes: 1. Let |scopeString| be the serialized |scope|. 1. If |requestURLString| starts with |scopeString| return |worker|. 1. Return null. @@ -3157,15 +3157,15 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Get Registration

: Input - :: |scope|, a URL + :: |scope|, a [=/URL=] : Output - :: |registration|, a service worker registration + :: |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 serialized |scope| with the *exclude fragment flag* set. 1. Let |registration| be null. - 1. For each |key| → |value| of scope to registration map: + 1. [=map/For each=] |key| → |value| of scope to registration map: 1. If |scopeString| matches |key|, set |registration| to |value|. 1. Return |registration|. @@ -3174,9 +3174,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Get Newest Worker

: Input - :: |registration|, a service worker registration + :: |registration|, a [=/service worker registration=] : Output - :: |newestWorker|, a service worker + :: |newestWorker|, a [=/service worker=] 1. Run the following steps atomically. 1. Let |newestWorker| be null. @@ -3190,13 +3190,13 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Create Client

: Input - :: |client|, a service worker client + :: |client|, a [=/service worker client=] : Output :: |clientObject|, a {{Client}} object 1. Let |clientObject| be a new {{Client}} object. - 1. Set |clientObject|'s service worker client to |client|. - 1. Set |clientObject|'s reserved state to true if |client|'s execution ready flag is unset, and false otherwise. + 1. Set |clientObject|'s [=Client/service worker client=] to |client|. + 1. Set |clientObject|'s [=Client/reserved state=] to true if |client|'s [=environment/execution ready flag=] is unset, and false otherwise. 1. Return |clientObject|. @@ -3204,7 +3204,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Create Window Client

: Input - :: |client|, a service worker client + :: |client|, a [=/service worker client=] :: |visibilityState|, a string :: |focusState|, a boolean :: |ancestorOrigins|, an array @@ -3212,10 +3212,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe :: |windowClient|, a {{WindowClient}} object 1. Let |windowClient| be a new {{WindowClient}} object. - 1. Set |windowClient|'s service worker client to |client|. + 1. Set |windowClient|'s [=Client/service worker client=] to |client|. 1. Set |windowClient|'s visibility state to |visibilityState|. 1. Set |windowClient|'s focus state to |focusState|. - 1. Set |windowClient|'s ancestor origins array to |ancestorOrigins|. + 1. Set |windowClient|'s [=WindowClient/ancestor origins array=] to |ancestorOrigins|. 1. Return |windowClient|. @@ -3236,30 +3236,30 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. Let |cachedURL| and |requestURL| be null. 1. If the optional argument |targetStorage| is omitted, then: 1. For each fetching record |entry| of its request to response map, in key insertion order: - 1. Set |cachedURL| to |entry|.\[[key]]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. + 1. Set |cachedURL| to |entry|.\[[key]]'s associated [=Request/request=]'s [=request/url=]. + 1. Set |requestURL| to |request|'s associated [=Request/request=]'s [=request/url=]. 1. If |options|.ignoreSearch is true, then: - 1. Set |cachedURL|'s query to the empty string. - 1. Set |requestURL|'s query to the empty string. - 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Set |cachedURL|'s [=url/query=] to the empty string. + 1. Set |requestURL|'s [=url/query=] to the empty string. + 1. If |cachedURL| [=url/equals=] |requestURL| with the *exclude fragments flag* set, then: 1. Add a copy of |entry|.\[[key]] to |requestArray|. 1. Add a copy of |entry|.\[[value]] to |responseArray|. 1. Else: 1. For each |record| in |targetStorage|: - 1. Set |cachedURL| to |record|[0]'s associated request's url. - 1. Set |requestURL| to |request|'s associated request's url. + 1. Set |cachedURL| to |record|[0]'s associated [=Request/request=]'s [=request/url=]. + 1. Set |requestURL| to |request|'s associated [=Request/request=]'s [=request/url=]. 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: - 1. Set |cachedURL|'s query to the empty string. - 1. Set |requestURL|'s query to the empty string. - 1. If |cachedURL| equals |requestURL| with the *exclude fragments flag* set, then: + 1. Set |cachedURL|'s [=url/query=] to the empty string. + 1. Set |requestURL|'s [=url/query=] to the empty string. + 1. If |cachedURL| [=url/equals=] |requestURL| with the *exclude fragments flag* set, then: 1. Add |record|[0] to |requestArray|. 1. Add |record|[1] to |responseArray|. 1. For each |cachedResponse| in |responseArray| with the index |index|: 1. Let |cachedRequest| be the |index|th element in |requestArray|. - 1. If |cachedResponse|'s response's header list contains no header named \`Vary\`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: + 1. If |cachedResponse|'s [=Response/response=]'s [=response/header list=] contains no header [=header/named=] \`Vary\`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. 1. Continue to the next iteration of the loop. - 1. Let |varyHeaders| be the array containing the elements corresponding to the field-values of the Vary header. + 1. Let |varyHeaders| be the array containing the elements corresponding to the [=http/field-values=] of the Vary header. 1. Let |matchFailed| be false. 1. For each |f| in |varyHeaders|: 1. If |f| matches "*", or the result of running |cachedRequest|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument does not match the result of running |request|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument, then: @@ -3292,9 +3292,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. - 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated request. - 1. If |r|'s url's scheme is not one of "http" and "https", throw a TypeError. - 1. If |r|'s method is not \`GET\`, throw a TypeError. + 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated [=Request/request=]. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", throw a TypeError. + 1. If |r|'s [=request/method=] is not \`GET\`, throw a TypeError. 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. 1. If |requestResponseArray| is not an empty array, then: @@ -3322,10 +3322,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Service Worker Script Request

- An HTTP request to fetch a service worker's script resource will include the following header: + An HTTP request to [=/fetch=] a [=/service worker=]'s script resource will include the following header: : \`Service-Worker\` - :: Indicates this request is a service worker's script resource request. + :: Indicates this request is a [=/service worker=]'s script resource request. Note: This header helps administrators log the requests and detect threats.
@@ -3333,10 +3333,10 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Service Worker Script Response

- An HTTP response to a service worker's script resource request can include the following header: + An HTTP response to a [=/service worker=]'s script resource request can include the following header: : \`Service-Worker-Allowed\` - :: Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. + :: Indicates the user agent will override the path restriction, which limits the maximum allowed [=service worker registration/scope url=] that the script can control, to the given value. Note: The value is a URL. If a relative URL is given, it is parsed against the script's URL. @@ -3392,7 +3392,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

Syntax

- ABNF for the values of the headers used by the service worker's script resource requests and responses: + ABNF for the values of the headers used by the [=/service worker=]'s script resource requests and responses:
       Service-Worker = %x73.63.72.69.70.74 ; "script", case-sensitive

From c7b584504690f634092b924191efb4d5b5f8ee50 Mon Sep 17 00:00:00 2001
From: Jungkee Song 
Date: Wed, 30 Nov 2016 17:03:58 +0900
Subject: [PATCH 17/17] Merge bikeshed cleanups to V1

---
 docs/index.bs    |    6 +-
 docs/v1/index.bs | 4621 +++++++++++++++++++---------------------------
 2 files changed, 1925 insertions(+), 2702 deletions(-)

diff --git a/docs/index.bs b/docs/index.bs
index 285a850a..516fd9d3 100644
--- a/docs/index.bs
+++ b/docs/index.bs
@@ -2642,9 +2642,9 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
       1. Assert: |script| is not null.
       1. If |serviceWorker| is already running, abort these steps.
       1. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context.
-      1. Call the JavaScript InitializeHostDefinedRealm abstract operation with the following customizations:
+      1. Call the JavaScript [=InitializeHostDefinedRealm|InitializeHostDefinedRealm()=] abstract operation with the following customizations:
           * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object.
-          * Let |realmExecutionContext| be the created execution context.
+          * Let |realmExecutionContext| be the created [=execution context|JavaScript execution context=].
       1. Set |serviceWorker|'s [=service worker/global object=] to |workerGlobalScope|.
       1. Let |workerEventLoop| be a newly created event loop.
       1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows:
@@ -3275,7 +3275,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
       : Input
       :: |operations|, an array of  {{CacheBatchOperation}} dictionary objects
       : Output
-      :: |promise|, a promise resolves with an array of {{Response}} objects.
+      :: |promise|, a promise resolves with an array of {{Response}} objects
 
       1. Let |promise| be a promise resolved with no value.
       1. Return the result of transforming |promise| with a fulfillment handler that performs the following substeps in parallel:
diff --git a/docs/v1/index.bs b/docs/v1/index.bs
index 696c065e..2f8e3dd7 100644
--- a/docs/v1/index.bs
+++ b/docs/v1/index.bs
@@ -16,110 +16,65 @@ Abstract:
 Abstract: The core of this system is an event-driven Web Worker, which responds to events dispatched from documents and other sources. A system for managing installation, versions, and upgrades is provided.
 Abstract:
 Abstract: The service worker is a generic entry point for event-driven background processing in the Web Platform that is extensible by other specifications.
-Ignored Terms: javascript global environment, worker environment, worker environments, document environment, document environments, referrer source, script execution environment, script execution environments, code entry-point, jump to a code entry point, used flag, process response body, http equivalent codes
-Markup Shorthands: css no
+Markup Shorthands: css no, markdown yes
 
-
-{
-  "unsanctioned-tracking": {
-    "href": "https://www.w3.org/2001/tag/doc/unsanctioned-tracking/",
-    "title": "Unsanctioned Web Tracking",
-    "date": "17 July 2015",
-    "status": "Finding of the W3C TAG",
-    "publisher": "W3C TAG"
-  }
-}
-
+ -

The serviceWorker attribute must return the {{ServiceWorkerContainer}} object that is associated with the context object.

+ The serviceWorker attribute *must* return the {{ServiceWorkerContainer}} object that is associated with the context object.
@@ -536,156 +521,123 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

The user agent must create a {{ServiceWorkerContainer}} object when a {{Navigator}} object or a {{WorkerNavigator}} object is created and associate it with that object.

+ The user agent *must* create a {{ServiceWorkerContainer}} object when a {{Navigator}} object or a {{WorkerNavigator}} object is created and associate it with that object. -

A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the service worker registrations, and provides access to the state of the service worker registrations and their associated service workers.

+ A {{ServiceWorkerContainer}} provides capabilities to register, unregister, and update the [=/service worker registrations=], and provides access to the state of the [=/service worker registrations=] and their associated [=/service workers=]. -

A {{ServiceWorkerContainer}} has an associated service worker client, which is a service worker client whose global object is associated with the {{Navigator}} object or the {{WorkerNavigator}} object that the {{ServiceWorkerContainer}} is retrieved from.

+ A {{ServiceWorkerContainer}} has an associated service worker client, which is a [=/service worker client=] whose [=environment settings object/global object=] is associated with the {{Navigator}} object or the {{WorkerNavigator}} object that the {{ServiceWorkerContainer}} is retrieved from. -

A {{ServiceWorkerContainer}} object has an associated ready promise (a promise). It is initially set to a new promise.

+ A {{ServiceWorkerContainer}} object has an associated ready promise (a promise). It is initially set to a new promise. -

A {{ServiceWorkerContainer}} object has a task source called the client message queue, initially empty. A client message queue can be enabled or disabled, and is initially disabled. When a {{ServiceWorkerContainer}} object's client message queue is enabled, the event loop must use it as one of its task sources. When the {{ServiceWorkerContainer}} object's relevant global object is a {{Window}} object, all tasks queued on its client message queue must be associated with its relevant settings object's responsible document.

+ A {{ServiceWorkerContainer}} object has a task source called the client message queue, initially empty. A [=ServiceWorkerContainer/client message queue=] can be enabled or disabled, and is initially disabled. When a {{ServiceWorkerContainer}} object's [=ServiceWorkerContainer/client message queue=] is enabled, the event loop *must* use it as one of its task sources. When the {{ServiceWorkerContainer}} object's relevant global object is a {{Window}} object, all tasks queued on its [=ServiceWorkerContainer/client message queue=] *must* be associated with its relevant settings object's responsible document.
-

controller attribute must run these steps:

- -
    -
  1. Let client be the context object's service worker client.
  2. -
  3. Return the {{ServiceWorker}} object that represents client's active service worker.
  4. -
- -

{{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same service worker are the same objects.

- -
- -
- - -

ready attribute must run these steps:

- -
    -
  1. If the context object's ready promise is settled, return the context object's ready promise.
  2. -
  3. Let client be the context object's service worker client.
  4. -
  5. Let registration be null.
  6. -
  7. Let clientURL be client's creation URL.
  8. -
  9. Run the following substeps in parallel: -
      -
    1. CheckRegistration: If the result of running Match Service Worker Registration algorithm with clientURL as its argument is not null, then: -
        -
      1. Set registration to the result value.
      2. -
      -
    2. -
    3. Else: -
        -
      1. Wait until scope to registration map has a new entry.
      2. -
      3. Jump to the step labeled CheckRegistration.
      4. -
      -
    4. -
    5. If registration's active worker is null, wait until registration's active worker changes. -

      Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm.

      -
    6. -
    7. Resolve context object's ready promise with the {{ServiceWorkerRegistration}} object which represents registration.
    8. -
    -
  10. -
  11. Return context object's ready promise.
  12. -
- -

When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a service worker registration that has an active worker.

+ controller attribute *must* run these steps: + + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. + 1. Return the {{ServiceWorker}} object that represents |client|'s active service worker. + + Note: {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} returns null if the request is a force refresh (shift+refresh). The {{ServiceWorker}} objects returned from this attribute getter that represent the same [=/service worker=] are the same objects. +
+ +
+ + + ready attribute *must* run these steps: + + 1. If the context object's [=ServiceWorkerContainer/ready promise=] is settled, return the context object's [=ServiceWorkerContainer/ready promise=]. + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. + 1. Let |registration| be null. + 1. Let |clientURL| be |client|'s creation URL. + 1. Run the following substeps in parallel: + 1. *CheckRegistration*: If the result of running Match Service Worker Registration algorithm with |clientURL| as its argument is not null, then: + 1. Set |registration| to the result value. + 1. Else: + 1. Wait until scope to registration map has a new entry. + 1. Jump to the step labeled *CheckRegistration*. + 1. If |registration|'s active worker is null, wait until |registration|'s active worker changes. + + Note: Implementers should consider this condition is met when the corresponding registration request gets to the step 6 of Activate algorithm. + + 1. Resolve context object's [=ServiceWorkerContainer/ready promise=] with the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Return context object's [=ServiceWorkerContainer/ready promise=]. + + Note: When the {{ServiceWorkerContainer/ready}} attribute is accessed, the returned promise will never reject. Instead, it waits until the promise resolves with a [=/service worker registration=] that has an active worker.
-

The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a service worker registration for the given scope url. If successful, a service worker registration ties the provided scriptURL to a scope url, which is subsequently used for navigation matching.

- -

register(scriptURL, options) method must run these steps:

- -
    -
  1. Let p be a promise.
  2. -
  3. Let client be the context object's service worker client.
  4. -
  5. Let scriptURL be the result of parsing scriptURL with the context object's relevant settings object's API base URL.
  6. -
  7. If scriptURL is failure, reject p with a TypeError and abort these steps.
  8. -
  9. If scriptURL's scheme is not one of "http" and "https", reject p with a TypeError and abort these steps.
  10. -
  11. If any of the strings in scriptURL's path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject p with a TypeError and abort these steps.
  12. -
  13. Let scopeURL be null.
  14. -
  15. If options.{{RegistrationOptions/scope}} is not present, set scopeURL to the result of parsing a string "./" with scriptURL. -

    The scope url for the registration is set to the location of the service worker script by default.

    -
  16. -
  17. Else, set scopeURL to the result of parsing options.{{RegistrationOptions/scope}} with the context object's relevant settings object's API base URL.
  18. -
  19. If scopeURL is failure, reject p with a TypeError and abort these steps.
  20. -
  21. If scopeURL's scheme is not one of "http" and "https", reject p with a TypeError and abort these steps.
  22. -
  23. If any of the strings in scopeURL's path contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject p with a TypeError and abort these steps.
  24. -
  25. Let job be the result of running Create Job with register, scopeURL, scriptURL, p, and client.
  26. -
  27. Invoke Schedule Job with job.
  28. -
  29. Return p.
  30. -
+ Note: The {{ServiceWorkerContainer/register(scriptURL, options)}} method creates or updates a [=/service worker registration=] for the given [=service worker registration/scope url=]. If successful, a [=/service worker registration=] ties the provided |scriptURL| to a [=service worker registration/scope url=], which is subsequently used for navigation matching. + + register(|scriptURL|, |options|) method *must* run these steps: + + 1. Let |p| be a promise. + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. + 1. Let |scriptURL| be the result of parsing |scriptURL| with the context object's relevant settings object's API base URL. + 1. If |scriptURL| is failure, reject |p| with a TypeError and abort these steps. + 1. If |scriptURL|'s [=url/scheme=] is not one of "http" and "https", reject |p| with a TypeError and abort these steps. + 1. If any of the strings in |scriptURL|'s [=url/path=] contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |p| with a TypeError and abort these steps. + 1. Let |scopeURL| be null. + 1. If |options|.{{RegistrationOptions/scope}} is not present, set |scopeURL| to the result of parsing a string "./" with |scriptURL|. + + Note: The scope url for the registration is set to the location of the service worker script by default. + + 1. Else, set |scopeURL| to the result of parsing |options|.{{RegistrationOptions/scope}} with the context object's relevant settings object's API base URL. + 1. If |scopeURL| is failure, reject |p| with a TypeError and abort these steps. + 1. If |scopeURL|'s [=url/scheme=] is not one of "http" and "https", reject |p| with a TypeError and abort these steps. + 1. If any of the strings in |scopeURL|'s [=url/path=] contains either ASCII case-insensitive "%2f" or ASCII case-insensitive "%5c", reject |p| with a TypeError and abort these steps. + 1. Let |job| be the result of running Create Job with *register*, |scopeURL|, |scriptURL|, |p|, and |client|. + 1. Invoke Schedule Job with |job|. + 1. Return |p|.
-

getRegistration(clientURL) method must run these steps:

- -
    -
  1. Let client be the context object's service worker client.
  2. -
  3. Let clientURL be the result of parsing clientURL with the context object's relevant settings object's API base URL.
  4. -
  5. If clientURL is failure, return a promise rejected with a TypeError.
  6. -
  7. If the origin of clientURL is not client's origin, return a promise rejected with a "{{SecurityError}}" exception.
  8. -
  9. Let promise be a new promise.
  10. -
  11. Run the following substeps in parallel: -
      -
    1. Let registration be the result of running Match Service Worker Registration algorithm with clientURL as its argument.
    2. -
    3. If registration is not null, then: -
        -
      1. Resolve promise with the {{ServiceWorkerRegistration}} object which represents registration.
      2. -
      -
    4. -
    5. Else: -
        -
      1. Resolve promise with undefined.
      2. -
      -
    6. -
    -
  12. -
  13. Return promise.
  14. -
+ getRegistration(|clientURL|) method *must* run these steps: + + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. + 1. Let |clientURL| be the result of parsing |clientURL| with the context object's relevant settings object's API base URL. + 1. If |clientURL| is failure, return a promise rejected with a TypeError. + 1. If the [=environment settings object/origin=] of |clientURL| is not |client|'s [=environment settings object/origin=], return a |promise| rejected with a "{{SecurityError}}" exception. + 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. Let |registration| be the result of running Match Service Worker Registration algorithm with |clientURL| as its argument. + 1. If |registration| is not null, then: + 1. Resolve |promise| with the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Else: + 1. Resolve |promise| with undefined. + 1. Return |promise|.
-

getRegistrations() method must run these steps:

- -
    -
  1. Let client be the context object's service worker client.
  2. -
  3. Let promise be a new promise.
  4. -
  5. Run the following substeps in parallel: -
      -
    1. Let array be an empty array.
    2. -
    3. For each Record {\[[key]], \[[value]]} entry of scope to registration map: -
        -
      1. If the origin of the result of parsing entry.\[[key]] is the same as client's origin, and entry.\[[value]]'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with entry.\[[value]] to the array.
      2. -
      -
    4. -
    5. Resolve promise with array.
    6. -
    -
  6. -
  7. Return promise.
  8. -
+ getRegistrations() method *must* run these steps: + + 1. Let |client| be the context object's [=ServiceWorkerContainer/service worker client=]. + 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. Let |array| be an empty array. + 1. [=map/For each=] |key| → |value| of scope to registration map: + 1. If the [=url/origin=] of the result of parsing |key| is the same as |client|'s [=environment settings object/origin=], and |value|'s uninstalling flag is unset, add the {{ServiceWorkerRegistration}} object associated with |value| to the |array|. + 1. Resolve |promise| with |array|. + 1. Return |promise|.
-

startMessages() method must enable the context object's client message queue if it is not enabled.

+ startMessages() method *must* enable the context object's [=ServiceWorkerContainer/client message queue=] if it is not enabled.

Event handlers

-

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerContainer}} interface:

+ The following are the event handlers (and their corresponding event handler event types) that *must* be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerContainer}} interface: @@ -697,23 +649,22 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - + - +
oncontrollerchangecontrollerchange{{ServiceWorkerContainer/controllerchange!!event}}
onmessagemessage{{ServiceWorkerContainer/message!!event}}
-

The first time the context object's {{ServiceWorkerContainer/onmessage}} IDL attribute is set, its client message queue must be enabled.

+ The first time the context object's {{ServiceWorkerContainer/onmessage}} IDL attribute is set, its [=ServiceWorkerContainer/client message queue=] *must* be enabled.
-

Events

-

The following event is dispatched on {{ServiceWorker}} object:

+ The following event is dispatched on {{ServiceWorker}} object: @@ -732,7 +683,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
-

The following event is dispatched on {{ServiceWorkerRegistration}} object:

+ The following event is dispatched on {{ServiceWorkerRegistration}} object: @@ -746,12 +697,12 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - +
updatefound {{Event}}The service worker registration's installing worker changes. (See step 8 of the Install algorithm.)The [=ServiceWorkerRegistration/service worker registration=]'s installing worker changes. (See step 8 of the Install algorithm.)
-

The following events are dispatched on {{ServiceWorkerContainer}} object:

+ The following events are dispatched on {{ServiceWorkerContainer}} object: @@ -765,7 +716,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - +
controllerchange {{Event}}The service worker client's active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a service worker causes activation of the service worker registration to occur while service worker clients are using the service worker registration, {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the service worker that controls the service worker client.)The [=ServiceWorkerContainer/service worker client=]'s active service worker changes. (See step 9.2 of the Activate algorithm. The skip waiting flag of a [=/service worker=] causes activation of the [=/service worker registration=] to occur while [=/service worker clients=] are using the [=/service worker registration=], {{ServiceWorkerContainer/controller|navigator.serviceWorker.controller}} immediately reflects the active worker as the [=/service worker=] that controls the [=/service worker client=].)
@@ -778,12 +729,12 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
Serving Cached Resources: -
+    
       // caching.js
-      this.addEventListener("install", function(e) {
-        e.waitUntil(
+      self.addEventListener("install", event => {
+        event.waitUntil(
           // Open a cache of resources.
-          caches.open("shell-v1").then(function(cache) {
+          caches.open("shell-v1").then(cache => {
             // Begins the process of fetching them.
             // The coast is only clear when all the resources are ready.
             return cache.addAll([
@@ -797,16 +748,16 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
         );
       });
 
-      this.addEventListener("fetch", function(e) {
+      self.addEventListener("fetch", event => {
         // No "fetch" events are dispatched to the service worker until it
         // successfully installs and activates.
 
         // All operations on caches are async, including matching URLs, so we use
         // promises heavily. e.respondWith() even takes promises to enable this:
-        e.respondWith(
-          caches.match(e.request).then(function(response) {
+        event.respondWith(
+          caches.match(e.request).then(response => {
             return response || fetch(e.request);
-          }).catch(function() {
+          }).catch(() => {
             return caches.match("/fallback.html");
           })
         );
@@ -836,50 +787,42 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
       };
     
-

A {{ServiceWorkerGlobalScope}} object represents the global execution context of a service worker. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a service worker).

+ A {{ServiceWorkerGlobalScope}} object represents the global execution context of a [=/service worker=]. A {{ServiceWorkerGlobalScope}} object has an associated service worker (a [=/service worker=]). -

{{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a service worker is started, kept alive and killed by their relationship to events, not service worker clients. Any type of synchronous requests must not be initiated inside of a service worker.

+ Note: {{ServiceWorkerGlobalScope}} object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully registered, a [=/service worker=] is started, kept alive and killed by their relationship to events, not [=/service worker clients=]. Any type of synchronous requests must not be initiated inside of a [=/service worker=].

{{ServiceWorkerGlobalScope/clients}}

-

clients attribute must return the {{Clients}} object that is associated with the context object.

+ clients attribute *must* return the {{Clients}} object that is associated with the context object.

{{ServiceWorkerGlobalScope/registration}}

-

The registration attribute must return the {{ServiceWorkerRegistration}} object that represents the service worker's containing service worker registration.

+ The registration attribute *must* return the {{ServiceWorkerRegistration}} object that represents the [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration.

{{ServiceWorkerGlobalScope/skipWaiting()}}

-

The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this service worker to progress from the registration's waiting position to active even while service worker clients are using the registration.

+ Note: The {{ServiceWorkerGlobalScope/skipWaiting()}} method allows this [=/service worker=] to progress from the [=service worker/registration=]'s waiting position to active even while [=/service worker clients=] are using the [=service worker/registration=]. -

skipWaiting() method must run these steps:

+ skipWaiting() method *must* run these steps: -
    -
  1. Let promise be a new promise.
  2. -
  3. Run the following substeps in parallel: -
      -
    1. Set service worker's skip waiting flag.
    2. -
    3. If service worker's state is installed, then: -
        -
      1. Run Activate algorithm passing service worker's registration as the argument.
      2. -
      -
    4. -
    5. Resolve promise with undefined.
    6. -
    -
  4. -
  5. Return promise.
  6. -
+ 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. Set [=/service worker=]'s skip waiting flag. + 1. If [=/service worker=]'s state is *installed*, then: + 1. Run Activate algorithm passing [=/service worker=]'s [=service worker/registration=] as the argument. + 1. Resolve |promise| with undefined. + 1. Return |promise|.

Event handlers

-

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerGlobalScope}} interface:

+ The following are the event handlers (and their corresponding event handler event types) that *must* be supported, as event handler IDL attributes, by all objects implementing the {{ServiceWorkerGlobalScope}} interface: @@ -891,15 +834,15 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - + - + - + @@ -919,7 +862,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 readonly attribute USVString url; readonly attribute DOMString id; readonly attribute boolean reserved; - void postMessage(any message, optional sequence<object> transfer); + void postMessage(any message, optional sequence<object> transfer = []); }; [Exposed=ServiceWorker] @@ -932,152 +875,128 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

A {{Client}} object has an associated service worker client (a service worker client).

+ A {{Client}} object has an associated service worker client (a [=/service worker client=]). -

A {{Client}} object has an associated reserved state, which is either true or false.

+ A {{Client}} object has an associated reserved state, which is either true or false. -

A WindowClient object has an associated visibility state, which is one of {{Document/visibilityState}} attribute value.

+ A {{WindowClient}} object has an associated visibility state, which is one of {{Document/visibilityState}} attribute value. -

A {{WindowClient}} object has an associated focus state, which is either true or false (initially false).

+ A {{WindowClient}} object has an associated focus state, which is either true or false (initially false). -

A {{WindowClient}} object has an associated ancestor origins array.

+ A {{WindowClient}} object has an associated ancestor origins array.

{{Client/url}}

-

The url attribute must return the context object's associated service worker client's serialized creation URL.

+ The url attribute *must* return the context object's associated [=Client/service worker client=]'s serialized creation URL.

{{Client/id}}

-

The id attribute must return its associated service worker client's id.

+ The id attribute *must* return its associated [=Client/service worker client=]'s [=environment/id=].

{{Client/reserved}}

-

The reserved attribute must return the context object's associated reserved state.

+ The reserved attribute *must* return the context object's associated [=Client/reserved state=].

{{Client/postMessage(message, transfer)}}

-

The postMessage(message, transfer) method must run these steps:

- -
    -
  1. Let sourceSettings be the context object's relevant settings object.
  2. -
  3. Let destination be the {{ServiceWorkerContainer}} object whose service worker client is the context object's service worker client.
  4. -
  5. If destination is null, throw an "{{InvalidStateError}}" exception.
  6. -
  7. Let targetRealm be destination's relevant Realm.
  8. -
  9. Let cloneRecord be StructuredCloneWithTransfer(message, transfer, targetRealm). If this throws an exception, rethrow that exception and abort these steps.
  10. -
  11. Let clonedMessage be cloneRecord.\[[Clone]].
  12. -
  13. Let newPorts be a new frozen array consisting of all {{MessagePort}} objects in cloneRecord.\[[TransferList]], if any, maintaining their relative order.
  14. -
  15. Add a task that runs the following steps to destination's client message queue: -
      -
    1. Create an event e that uses the {{MessageEvent}} interface, with the event type message, which does not bubble and is not cancelable.
    2. -
    3. Let the data attribute of e be initialized to clonedMessage.
    4. -
    5. Let the origin attribute of e be initialized to the Unicode serialization of sourceSettings's origin.
    6. -
    7. Let the source attribute of e be initialized to a {{ServiceWorker}} object, which represents the service worker associated with sourceSettings's global object.
    8. -
    9. Let the ports attribute of e be initialized to newPorts.
    10. -
    11. Dispatch e at destination.
    12. -
    -
  16. -
+ The postMessage(|message|, |transfer|) method *must* run these steps: + + 1. Let |sourceSettings| be the context object's relevant settings object. + 1. Let |destination| be the {{ServiceWorkerContainer}} object whose [=ServiceWorkerContainer/service worker client=] is the context object's [=Client/service worker client=]. + 1. If |destination| is null, throw an "{{InvalidStateError}}" exception. + 1. Let |targetRealm| be |destination|'s relevant Realm. + 1. Let |cloneRecord| be StructuredCloneWithTransfer(|message|, |transfer|, |targetRealm|). If this throws an exception, rethrow that exception and abort these steps. + 1. Let |clonedMessage| be |cloneRecord|.\[[Clone]]. + 1. Let |newPorts| be a new frozen array consisting of all {{MessagePort}} objects in |cloneRecord|.\[[TransferList]], if any, maintaining their relative order. + 1. Add a task that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]: + 1. Create an event |e| that uses the {{MessageEvent}} interface, with the event type {{Window/message!!event}}, which does not bubble and is not cancelable. + 1. Let the data attribute of |e| be initialized to |clonedMessage|. + 1. Let the origin attribute of |e| be initialized to the Unicode serialization of |sourceSettings|'s [=environment settings object/origin=]. + 1. Let the source attribute of |e| be initialized to a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=]. + 1. Let the ports attribute of |e| be initialized to |newPorts|. + 1. Dispatch |e| at |destination|.

{{WindowClient/visibilityState}}

-

The visibilityState attribute must return the context object's visibility state.

+ The visibilityState attribute *must* return the context object's visibility state.

{{WindowClient/focused}}

-

The focused attribute must return the context object's focus state.

+ The focused attribute *must* return the context object's focus state.

{{WindowClient/ancestorOrigins}}

-

The ancestorOrigins attribute must return the context object's associated service worker client's ancestor origins array.

+ The ancestorOrigins attribute *must* return the context object's associated [=Client/service worker client=]'s [=WindowClient/ancestor origins array=].

{{WindowClient/focus()}}

-

The focus() method must run these steps:

- -
    -
  1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception.
  2. -
  3. Let promise be a new promise.
  4. -
  5. Run these substeps in parallel: -
      -
    1. Let browsingContext be the context object's associated service worker client's global object's browsing context.
    2. -
    3. Let visibilityState be null.
    4. -
    5. Let focusState be false.
    6. -
    7. Let ancestorOrigins be the empty array.
    8. -
    9. Queue a task task to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: -
        -
      1. Run the focusing steps with browsingContext.
      2. -
      3. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
      4. -
      5. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
      6. -
      7. Set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
      8. -
      -
    10. -
    11. Wait for task to have executed.
    12. -
    13. Let windowClient be the result of running Create Window Client algorithm with the context object's associated service worker client, visibilityState, focusState, and ancestorOrigins as the arguments.
    14. -
    15. If windowClient's focus state is true, resolve promise with windowClient.
    16. -
    17. Else, reject promise with a TypeError.
    18. -
    -
  6. -
  7. Return promise.
  8. -
+ The focus() method *must* run these steps: + + 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |browsingContext| be the context object's associated [=Client/service worker client=]'s [=environment settings object/global object=]'s [=/browsing context=]. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on the context object's associated [=Client/service worker client=]'s responsible event loop using the user interaction task source: + 1. Run the focusing steps with |browsingContext|. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. + 1. Wait for |task| to have executed. + 1. Let |windowClient| be the result of running Create Window Client algorithm with the context object's associated [=Client/service worker client=], |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. If |windowClient|'s focus state is true, resolve |promise| with |windowClient|. + 1. Else, reject |promise| with a TypeError. + 1. Return |promise|.

{{WindowClient/navigate(url)}}

-

The navigate() method must run these steps:

- -
    -
  1. Let url be the result of parsing url with the context object's relevant settings object's API base URL.
  2. -
  3. If url is failure, return a promise rejected with a TypeError.
  4. -
  5. If url is about:blank, return a promise rejected with a TypeError.
  6. -
  7. If the context object's associated service worker client's active service worker is not the context object's relevant global object's service worker, return a promise rejected with a TypeError.
  8. -
  9. Let promise be a new promise.
  10. -
  11. Run these substeps in parallel: -
      -
    1. Let browsingContext be the context object's associated service worker client's global object's browsing context.
    2. -
    3. If browsingContext has discarded its {{Document}}, reject promise with a TypeError and abort these steps.
    4. -
    5. Let navigateFailed to false.
    6. -
    7. Let visibilityState be null.
    8. -
    9. Let focusState be false.
    10. -
    11. Let ancestorOrigins be the empty array.
    12. -
    13. Queue a task task to run the following substeps on the context object's associated service worker client's responsible event loop using the user interaction task source: -
        -
      1. HandleNavigate: Navigate browsingContext to url with exceptions enabled. The source browsing context must be browsingContext.
      2. -
      3. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set navigateFailed to true.
      4. -
      5. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
      6. -
      7. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
      8. -
      9. Set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
      10. -
      -
    14. -
    15. Wait for task to have executed (including its asynchronous steps).
    16. -
    17. If navigateFailed is true, reject promise with a TypeError and abort these steps.
    18. -
    19. If browsingContext's {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: -
        -
      1. Resolve promise with null.
      2. -
      3. Abort these steps.
      4. -
      -
    20. -
    21. Let windowClient be the result of running Create Window Client algorithm with browsingContext's {{Window}} object's environment settings object, visibilityState, focusState, and ancestorOrigins as the arguments.
    22. -
    23. Resolve promise with windowClient.
    24. -
    -
  12. -
  13. Return promise.
  14. -
+ The navigate() method *must* run these steps: + + 1. Let |url| be the result of parsing |url| with the context object's relevant settings object's API base URL. + 1. If |url| is failure, return a promise rejected with a TypeError. + 1. If |url| is about:blank, return a promise rejected with a TypeError. + 1. If the context object's associated [=Client/service worker client=]'s active service worker is not the context object's relevant global object's [=ServiceWorkerGlobalScope/service worker=], return a promise rejected with a TypeError. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |browsingContext| be the context object's associated [=Client/service worker client=]'s [=environment settings object/global object=]'s [=/browsing context=]. + 1. If |browsingContext| has discarded its {{Document}}, reject |promise| with a TypeError and abort these steps. + 1. Let |navigateFailed| to false. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on the context object's associated [=Client/service worker client=]'s responsible event loop using the user interaction task source: + 1. *HandleNavigate*: Navigate |browsingContext| to |url| with exceptions enabled. The source browsing context must be |browsingContext|. + 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |navigateFailed| to true. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. + 1. Wait for |task| to have executed (including its asynchronous steps). + 1. If |navigateFailed| is true, reject |promise| with a TypeError and abort these steps. + 1. If |browsingContext|'s {{Window}} object's environment settings object's creation URL's [=url/origin=] is not the same as the [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=], then: + 1. Resolve |promise| with null. + 1. Abort these steps. + 1. Let |windowClient| be the result of running Create Window Client algorithm with |browsingContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |windowClient|. + 1. Return |promise|.
@@ -1110,235 +1029,146 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

The user agent must create a {{Clients}} object when a {{ServiceWorkerGlobalScope}} object is created and associate it with that object.

+ The user agent *must* create a {{Clients}} object when a {{ServiceWorkerGlobalScope}} object is created and associate it with that object.

{{Clients/get(id)}}

-

The get(id) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. For each service worker client client whose origin is the same as the associated service worker's origin: -
        -
      1. If client's id is not id, continue to the next iteration of the loop.
      2. -
      3. If client is a type of environment, then: -
          -
        1. If client’s creation URL is not a potentially trustworthy URL, reject promise with a "{{SecurityError}}" exception and abort these steps.
        2. -
        -
      4. -
      5. Else: -
          -
        1. If client is not a secure context, reject promise with a "{{SecurityError}}" exception and abort these steps.
        2. -
        -
      6. -
      7. If client is a type of environment or is a window client, then: -
          -
        1. Let browsingContext be null.
        2. -
        3. Let visibilityState be null.
        4. -
        5. Let focusState be false.
        6. -
        7. Let ancestorOrigins be the empty array.
        8. -
        9. If client is a type of environment, set browsingContext to client’s target browsing context.
        10. -
        11. Else, set browsingContext to client's global object's browsing context.
        12. -
        13. Queue a task task to run the following substeps on browsingContext's event loop using the user interaction task source: -
            -
          1. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
          2. -
          3. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
          4. -
          5. If client is a window client, set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
          6. -
          -
        14. -
        15. Wait for task to have executed.
        16. -
        17. Let windowClient be the result of running Create Window Client algorithm with client, visibilityState, focusState, and ancestorOrigins as the arguments.
        18. -
        19. Resolve promise with windowClient and abort these steps.
        20. -
        -
      8. -
      9. Else: -
          -
        1. Let clientObject be the result of running Create Client algorithm with client as the argument.
        2. -
        3. Resolve promise with clientObject and abort these steps.
        4. -
        -
      10. -
      -
    2. -
    3. Resolve promise with undefined.
    4. -
    -
  4. -
  5. Return promise.
  6. -
+ The get(|id|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. For each [=/service worker client=] |client| whose [=service worker client/origin=] is the same as the associated [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=]: + 1. If |client|'s [=environment/id=] is not |id|, continue to the next iteration of the loop. + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, reject |promise| with a "{{SecurityError}}" exception and abort these steps. + 1. Else: + 1. If |client| is not a secure context, reject |promise| with a "{{SecurityError}}" exception and abort these steps. + 1. If |client| is a type of environment or is a window client, then: + 1. Let |browsingContext| be null. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s [=environment/target browsing context=]. + 1. Else, set |browsingContext| to |client|'s [=environment settings object/global object=]'s [=/browsing context=]. + 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. If |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. + 1. Wait for |task| to have executed. + 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |windowClient| and abort these steps. + 1. Else: + 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. + 1. Resolve |promise| with |clientObject| and abort these steps. + 1. Resolve |promise| with undefined. + 1. Return |promise|.

{{Clients/matchAll(options)}}

-

The matchAll(options) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. Let targetClients be an empty array.
    2. -
    3. For each service worker client client whose origin is the same as the associated service worker's origin: -
        -
      1. If client is a type of environment, then: -
          -
        1. If client’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop.
        2. -
        -
      2. -
      3. Else: -
          -
        1. If client is not a secure context, continue to the next iteration of the loop.
        2. -
        -
      4. -
      5. If options.{{ClientQueryOptions/includeUncontrolled}} is false, then: -
          -
        1. If client's active service worker is not the associated service worker, continue to the next iteration of the loop.
        2. -
        -
      6. -
      7. If options.{{ClientQueryOptions/includeReserved}} is false, then: -
          -
        1. If client's execution ready flag is unset, continue to the next iteration of the loop.
        2. -
        -
      8. -
      9. Add client to targetClients.
      10. -
      -
    4. -
    5. Let matchedClients be an empty array.
    6. -
    7. For each service worker client client in targetClients: -
        -
      1. If options.{{ClientQueryOptions/type}} is "window" or "all", and client is a type of environment or is a window client, then: -
          -
        1. Let browsingContext be null.
        2. -
        3. Let isClientEnumerable be true.
        4. -
        5. Let visibilityState be the empty string.
        6. -
        7. Let focusState be false.
        8. -
        9. Let ancestorOrigins be the empty array.
        10. -
        11. If client is a type of environment, set browsingContext to client’s target browsing context.
        12. -
        13. Else, set browsingContext to client's global object's browsing context.
        14. -
        15. Queue a task task to run the following substeps on browsingContext's event loop using the user interaction task source: -
            -
          1. If browsingContext has been discarded, set isClientEnumerable to false and abort these steps.
          2. -
          3. If client is a window client and client's responsible document is not browsingContext's active document, set isClientEnumerable to false and abort these steps.
          4. -
          5. Set visibilityState to browsingContext's active document's {{Document/visibilityState}} attribute value.
          6. -
          7. Set focusState to the result of running the has focus steps with browsingContext's active document as the argument.
          8. -
          9. It client is a window client, set ancestorOrigins to browsingContext's active document's relevant global object's {{Location}} object's ancestor origins array.
          10. -
          -
        16. -
        17. Wait for task to have executed. -

          Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken.

          -
        18. -
        19. If isClientEnumerable is true, then: -
            -
          1. Let windowClient be the result of running Create Window Client algorithm with client, visibilityState, focusState, and ancestorOrigins as the arguments.
          2. -
          3. Add windowClient to matchedClients.
          4. -
          -
        20. -
        -
      2. -
      3. Else if options.{{ClientQueryOptions/type}} is "worker" or "all" and client is a dedicated worker client, or options.{{ClientQueryOptions/type}} is "sharedworker" or "all" and client is a shared worker client, then: -
          -
        1. Let clientObject be the result of running Create Client algorithm with client as the argument.
        2. -
        3. Add clientObject to matchedClients.
        4. -
        -
      4. -
      -
    8. -
    9. Sort matchedClients such that: - -
    10. -
    11. Resolve promise with matchedClients.
    12. -
    -
  4. -
  5. Return promise.
  6. -
+ The matchAll(|options|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |targetClients| be an empty array. + 1. For each [=/service worker client=] |client| whose [=service worker client/origin=] is the same as the associated [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=]: + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. + 1. Else: + 1. If |client| is not a secure context, continue to the next iteration of the loop. + 1. If |options|.{{ClientQueryOptions/includeUncontrolled}} is false, then: + 1. If |client|'s active service worker is not the associated [=ServiceWorkerGlobalScope/service worker=], continue to the next iteration of the loop. + 1. If |options|.{{ClientQueryOptions/includeReserved}} is false, then: + 1. If |client|'s [=environment/execution ready flag=] is unset, continue to the next iteration of the loop. + 1. Add |client| to |targetClients|. + 1. Let |matchedClients| be an empty array. + 1. For each [=/service worker client=] |client| in |targetClients|: + 1. If |options|.{{ClientQueryOptions/type}} is {{ClientType/"window"}} or {{ClientType/"all"}}, and |client| is a type of environment or is a window client, then: + 1. Let |browsingContext| be null. + 1. Let |isClientEnumerable| be true. + 1. Let |visibilityState| be the empty string. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. If |client| is a type of environment, set |browsingContext| to |client|’s [=environment/target browsing context=]. + 1. Else, set |browsingContext| to |client|'s [=environment settings object/global object=]'s [=/browsing context=]. + 1. Queue a task |task| to run the following substeps on |browsingContext|'s event loop using the user interaction task source: + 1. If |browsingContext| has been discarded, set |isClientEnumerable| to false and abort these steps. + 1. If |client| is a window client and |client|'s responsible document is not |browsingContext|'s active document, set |isClientEnumerable| to false and abort these steps. + 1. Set |visibilityState| to |browsingContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |browsingContext|'s active document as the argument. + 1. It |client| is a window client, set |ancestorOrigins| to |browsingContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. + 1. Wait for |task| to have executed. + + Note: Wait is a blocking wait, but implementers may run the iterations in parallel as long as the state is not broken. + + 1. If |isClientEnumerable| is true, then: + 1. Let |windowClient| be the result of running Create Window Client algorithm with |client|, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Add |windowClient| to |matchedClients|. + 1. Else if |options|.{{ClientQueryOptions/type}} is {{ClientType/"worker"}} or {{ClientType/"all"}} and |client| is a dedicated worker client, or |options|.{{ClientQueryOptions/type}} is {{ClientType/"sharedworker"}} or {{ClientType/"all"}} and |client| is a shared worker client, then: + 1. Let |clientObject| be the result of running Create Client algorithm with |client| as the argument. + 1. Add |clientObject| to |matchedClients|. + 1. Sort |matchedClients| such that: + * {{WindowClient}} objects are always placed before {{Client}} objects whose associated [=Client/service worker clients=] are worker clients. + * {{WindowClient}} objects that have been focused are placed first sorted in the most recently focused order, and {{WindowClient}} objects that have never been focused are placed next sorted in their [=Client/service worker clients=]' creation order. + * {{Client}} objects whose associated [=Client/service worker clients=] are worker clients are placed next sorted in their [=Client/service worker clients=]' creation order. + 1. Resolve |promise| with |matchedClients|. + 1. Return |promise|.

{{Clients/openWindow(url)}}

-

The openWindow(url) method must run these steps:

- -
    -
  1. Let url be the result of parsing url with the context object's relevant settings object's API base URL.
  2. -
  3. If url is failure, return a promise rejected with a TypeError.
  4. -
  5. If url is about:blank, return a promise rejected with a TypeError.
  6. -
  7. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception.
  8. -
  9. Let promise be a new promise.
  10. -
  11. Run these substeps in parallel: -
      -
    1. Let newContext be a new top-level browsing context.
    2. -
    3. Let openWindowFailed to false.
    4. -
    5. Let visibilityState be null.
    6. -
    7. Let focusState be false.
    8. -
    9. Let ancestorOrigins be the empty array.
    10. -
    11. Queue a task task to run the following substeps on newContext's {{Window}} object's environment settings object's responsible event loop using the user interaction task source: -
        -
      1. HandleNavigate: Navigate newContext to url with exceptions enabled and replacement enabled.
      2. -
      3. If the algorithm steps invoked in the step labeled HandleNavigate throws an exception, set openWindowFailed to true.
      4. -
      5. Set visibilityState to newContext's active document's {{Document/visibilityState}} attribute value.
      6. -
      7. Set focusState to the result of running the has focus steps with newContext's active document as the argument.
      8. -
      9. Set ancestorOrigins to newContext's active document's relevant global object's {{Location}} object's ancestor origins array.
      10. -
      -
    12. -
    13. Wait for task to have executed (including its asynchronous steps).
    14. -
    15. If openWindowFailed is true, reject promise with a TypeError and abort these steps.
    16. -
    17. If newContext's {{Window}} object's environment settings object's creation URL's origin is not the same as the service worker's origin, then: -
        -
      1. Resolve promise with null.
      2. -
      3. Abort these steps.
      4. -
      -
    18. -
    19. Let client be the result of running Create Window Client algorithm with newContext's {{Window}} object's environment settings object, visibilityState, focusState, and ancestorOrigins as the arguments.
    20. -
    21. Resolve promise with client.
    22. -
    -
  12. -
  13. Return promise.
  14. -
+ The openWindow(|url|) method *must* run these steps: + 1. Let |url| be the result of parsing |url| with the context object's relevant settings object's API base URL. + 1. If |url| is failure, return a promise rejected with a TypeError. + 1. If |url| is about:blank, return a promise rejected with a TypeError. + 1. If this algorithm is not triggered by user activation, return a promise rejected with an "{{InvalidAccessError}}" exception. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |newContext| be a new top-level browsing context. + 1. Let |openWindowFailed| to false. + 1. Let |visibilityState| be null. + 1. Let |focusState| be false. + 1. Let |ancestorOrigins| be the empty array. + 1. Queue a task |task| to run the following substeps on |newContext|'s {{Window}} object's environment settings object's responsible event loop using the user interaction task source: + 1. *HandleNavigate*: Navigate |newContext| to |url| with exceptions enabled and replacement enabled. + 1. If the algorithm steps invoked in the step labeled *HandleNavigate* throws an exception, set |openWindowFailed| to true. + 1. Set |visibilityState| to |newContext|'s active document's {{Document/visibilityState}} attribute value. + 1. Set |focusState| to the result of running the has focus steps with |newContext|'s active document as the argument. + 1. Set |ancestorOrigins| to |newContext|'s active document's relevant global object's {{Location}} object's [=Location/ancestor origins array=]. + 1. Wait for |task| to have executed (including its asynchronous steps). + 1. If |openWindowFailed| is true, reject |promise| with a TypeError and abort these steps. + 1. If |newContext|'s {{Window}} object's environment settings object's creation URL's [=environment settings object/origin=] is not the same as the [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=], then: + 1. Resolve |promise| with null. + 1. Abort these steps. + 1. Let |client| be the result of running Create Window Client algorithm with |newContext|'s {{Window}} object's environment settings object, |visibilityState|, |focusState|, and |ancestorOrigins| as the arguments. + 1. Resolve |promise| with |client|. + 1. Return |promise|.

{{Clients/claim()}}

-

The claim() method must run these steps:

- -
    -
  1. If the service worker is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception.
  2. -
  3. Let promise be a new promise.
  4. -
  5. Run the following substeps in parallel: -
      -
    1. For each service worker client client whose origin is the same as the service worker's origin: -
        -
      1. If client is a type of environment, then: -
          -
        1. If client’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop.
        2. -
        -
      2. -
      3. Else: -
          -
        1. If client is not a secure context, continue to the next iteration of the loop.
        2. -
        -
      4. -
      5. Let registration be the result of running Match Service Worker Registration algorithm passing client's creation URL as the argument.
      6. -
      7. If registration is not the service worker's containing service worker registration, continue to the next iteration of the loop.
      8. -
      9. If client's active service worker is not the service worker, then: -
          -
        1. Invoke Handle Service Worker Client Unload with client as the argument.
        2. -
        3. Set client's active service worker to service worker.
        4. -
        5. Invoke Notify Controller Change algorithm with client as the argument.
        6. -
        -
      10. -
      -
    2. -
    3. Resolve promise with undefined.
    4. -
    -
  6. -
  7. Return promise.
  8. -
+ The claim() method *must* run these steps: + + 1. If the [=ServiceWorkerGlobalScope/service worker=] is not an active worker, return a promise rejected with an "{{InvalidStateError}}" exception. + 1. Let |promise| be a new promise. + 1. Run the following substeps in parallel: + 1. For each [=/service worker client=] |client| whose [=service worker client/origin=] is the same as the [=ServiceWorkerGlobalScope/service worker=]'s [=environment settings object/origin=]: + 1. If |client| is a type of environment, then: + 1. If |client|’s creation URL is not a potentially trustworthy URL, continue to the next iteration of the loop. + 1. Else: + 1. If |client| is not a secure context, continue to the next iteration of the loop. + 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 to the next iteration of the loop. + 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. Resolve |promise| with undefined. + 1. Return |promise|.
@@ -1357,42 +1187,35 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

An {{ExtendableEvent}} object has an associated extend lifetime promises (an array of promises). It is initially an empty array.

+ An {{ExtendableEvent}} object has an associated extend lifetime promises (an array of promises). It is initially an empty array. -

An {{ExtendableEvent}} object has an associated extensions allowed flag. It is initially set.

+ An {{ExtendableEvent}} object has an associated extensions allowed flag. It is initially set. -

Service workers have two lifecycle events, install and activate. Service workers use the {{ExtendableEvent}} interface for activate event and install event.

+ [=/Service workers=] have two lifecycle events, {{install!!event}} and {{activate!!event}}. [=/Service workers=] use the {{ExtendableEvent}} interface for {{activate!!event}} event and {{install!!event}} event. -

Service worker extensions that define event handlers may also use or extend the {{ExtendableEvent}} interface.

+ Service worker extensions that define event handlers *may* also use or extend the {{ExtendableEvent}} interface. -

To extend the lifetime of a service worker, algorithms that dispatch events using the {{ExtendableEvent}} interface run Extend Service Worker Lifetime algorithm after dispatching the event. See Handle Fetch and Handle Functional Event.

+ Note: To extend the lifetime of a [=/service worker=], algorithms that dispatch events using the {{ExtendableEvent}} interface run [=Extend Service Worker Lifetime=] algorithm after dispatching the event. See Handle Fetch and Handle Functional Event.
-

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

+

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

-

{{ExtendableEvent/waitUntil(f)}} method extends the lifetime of the event.

+ {{ExtendableEvent/waitUntil()}} method extends the lifetime of the event. -

waitUntil(f) method must run these steps:

+ waitUntil(|f|) method *must* run these steps: -
    -
  1. If the extensions allowed flag is unset, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  2. -
  3. Add f to the extend lifetime promises.
  4. -
+ 1. If the extensions allowed flag is unset, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. Add |f| to the [=ExtendableEvent/extend lifetime promises=].
-

Service workers and extensions that define event handlers may define their own behaviors, allowing the extend lifetime promises to suggest operation length, and the rejected state of any of the promise in extend lifetime promises to suggest operation failure.

+ [=/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. -

Service workers define the following behaviors for install event and activate event, respectively:

+ [=/Service workers=] define the following behaviors for install event and activate event, respectively: - + * Adding a promise |f| to the event's extend lifetime promises delays treating the installing worker as *installed* (i.e. a waiting worker) until all the promises in the extend lifetime promises resolve successfully. (See step 11.3.1 of Install algorithm.) If |f| rejects, the installation fails. This is primarily used to ensure that a [=/service worker=] is not considered *installed* (i.e. a waiting worker) until all of the core caches it depends on are populated. + * Adding a promise to the event's extend lifetime promises delays treating the active worker as *activated* until all the promises in the extend lifetime promises settle. (See step 12.3 of Activate algorithm.) This is primarily used to ensure that any functional events are not dispatched to the {{ServiceWorkerGlobalScope}} object that represents the [=/service worker=] until it upgrades database schemas and deletes the outdated cache entries.
@@ -1413,154 +1236,116 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
       dictionary FetchEventInit : ExtendableEventInit {
         required Request request;
-        DOMString clientId = null;
+        DOMString clientId = "";
         DOMString reservedClientId = "";
         DOMString targetClientId = "";
         boolean isReload = false;
       };
     
-

Service workers have an essential functional event fetch. For fetch event, service workers use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface.

+ [=/Service workers=] have an essential functional event {{fetch!!event}}. For {{fetch!!event}} event, [=/service workers=] use the {{FetchEvent}} interface which extends the {{ExtendableEvent}} interface. + + Each event using {{FetchEvent}} interface has an associated potential response (a [=/response=]), initially set to null, and the following associated flags that are initially unset: -

Each event using {{FetchEvent}} interface has an associated potential response (a response), initially set to null, and the following associated flags that are initially unset: -

    -
  • wait to respond flag
  • -
  • respond-with entered flag
  • -
  • respond-with error flag
  • -
-

+ * wait to respond flag + * respond-with entered flag + * respond-with error flag

{{FetchEvent/request|event.request}}

-

request attribute must return the value it was initialized to.

+ request attribute *must* return the value it was initialized to.

{{FetchEvent/clientId|event.clientId}}

-

clientId attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

+ clientId attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to the empty string.

{{FetchEvent/reservedClientId|event.reservedClientId}}

-

reservedClientId attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

+ reservedClientId attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to the empty string.

{{FetchEvent/targetClientId|event.targetClientId}}

-

targetClientId attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

+ targetClientId attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to the empty string.

{{FetchEvent/isReload|event.isReload}}

-

isReload attribute must return the value it was initialized to. When an event is created the attribute must be initialized to false.

+ isReload attribute *must* return the value it was initialized to. When an event is created the attribute *must* be initialized to false. -

Pressing the refresh button should be considered a reload while clicking a link and pressing the back button should not. The behavior of the Ctrl+l enter is left to the implementations of the user agents.

+ Note: Pressing the refresh button should be considered a reload while clicking a link and pressing the back button should not. The behavior of Ctrl+l enter is left to the implementations of the user agents.

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

-

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. If the dispatch flag is unset, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  2. -
  3. If the respond-with entered flag is set, then: -
      -
    1. Throw an "{{InvalidStateError}}" exception.
    2. -
    3. Abort these steps.
    4. -
    -
  4. -
  5. Add r to the extend lifetime promises. -

    {{FetchEvent/respondWith(r)|event.respondWith(r)}} extends the lifetime of the event by default as if {{ExtendableEvent/waitUntil(f)|event.waitUntil(r)}} is called.

    -
  6. -
  7. Set the stop propagation flag and stop immediate propagation flag.
  8. -
  9. Set the respond-with entered flag.
  10. -
  11. Set the wait to respond flag.
  12. -
  13. Let targetRealm be the relevant Realm of the context object. -
  14. Run the following substeps in parallel: -
      -
    1. Wait until r settles.
    2. -
    3. If r rejected, then: -
        -
      1. Set the respond-with error flag.
      2. -
      -
    4. -
    5. If r resolved with response, then: -
        -
      1. If response is a {{Response}} object, then: -
          -
        1. If response is disturbed or locked, then: -
            -
          1. Set the respond-with error flag.
          2. -
          -
        2. -
        3. Else: -
            -
          1. Let bytes be an empty byte sequence. -
          2. Let end-of-body be false. -
          3. Let done be false. -
          4. Let potentialResponse be a copy of response's associated response, except for its body.
          5. -
          6. If response's body is non-null, run these substeps: -
              -
            1. Let reader be the result of getting a reader from response's body's stream.
            2. -
            3. Let strategy be an object created in targetRealm. The user agent may choose any object.
            4. -
            5. Let pull be an action that runs these subsubsteps: -
                -
              1. Let promise be the result of reading a chunk from response's body's stream with reader.
              2. -
              3. 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.
              4. -
              5. When promise is fulfilled with an object whose done property is true, set end-of-body to true.
              6. -
              7. When promise is fulfilled with a value that matches with neither of the above patterns, or promise is rejected, error newStream with a TypeError.
              8. -
              -
            6. -
            7. Let cancel be an action that cancels response's body's stream with reader.
            8. -
            9. Let newStream be the result of constructing a ReadableStream object with strategy, pull and cancel in targetRealm.
            10. -
            11. Set potentialResponse's body to a new body whose stream is newStream.
            12. -
            13. Run these subsubsteps repeatedly in parallel while done is false:
            14. -
                -
              1. If newStream is errored, then set done to true.
              2. -
              3. Otherwise, if bytes is empty and end-of-body is true, then close newStream and set done to true.
              4. -
              5. Otherwise, if bytes is not empty, run these subsubsubsteps: -
                  -
                1. Let chunk be a subsequence of bytes starting from the beginning of bytes.
                2. -
                3. Remove chunk from bytes. -
                4. Let buffer be an ArrayBuffer object created in targetRealm and containing chunk. -
                5. Enqueue a Uint8Array object created in targetRealm and wrapping buffer to newStream. -
                -
              6. -
              - -
            -

            These substeps are meant to produce the observable equivalent of "piping" response's body's stream into potentialResponse.

            -
          7. -
          8. Set the potential response to potentialResponse.
          9. -
          -
        4. -
        -
      2. -
      3. Else: -
          -
        1. Set the respond-with error flag.
        2. -
        -

        If the 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.)

        -
      4. -
      -
    6. -
    7. Unset the wait to respond flag.
    8. -
    -
  15. -
+ 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. If the dispatch flag is unset, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. If the [=FetchEvent/respond-with entered flag=] is set, then: + 1. Throw an "{{InvalidStateError}}" exception. + 1. Abort these steps. + 1. Add |r| to the extend lifetime promises. + + 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 disturbed or 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=]. + + 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=].
@@ -1587,43 +1372,43 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

Service workers define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, service workers use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface.

+ [=/Service workers=] define the extendable {{message!!event}} event to allow extending the lifetime of the event. For the {{message!!event}} event, [=/service workers=] use the {{ExtendableMessageEvent}} interface which extends the {{ExtendableEvent}} interface.

{{ExtendableMessageEvent/data|event.data}}

-

The data attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to null. It represents the message being sent.

+ The data attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to null. It represents the message being sent.

{{ExtendableMessageEvent/origin|event.origin}}

-

The origin attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to the empty string. It represents the origin of the service worker client that sent the message.

+ The origin attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string. It represents the [=environment settings object/origin=] of the [=/service worker client=] that sent the message.

{{ExtendableMessageEvent/lastEventId|event.lastEventId}}

-

The lastEventId attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to the empty string.

+ The lastEventId attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty string.

{{ExtendableMessageEvent/source|event.source}}

-

The source attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to null. It represents the {{Client}} object from which the message is sent.

+ The source attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to null. It represents the {{Client}} object from which the message is sent.

{{ExtendableMessageEvent/ports|event.ports}}

-

The ports attribute must return the value it was initialized to. When the object is created, this attribute must be initialized to the empty array. It represents the {{MessagePort}} array being sent.

+ The ports attribute *must* return the value it was initialized to. When the object is created, this attribute *must* be initialized to the empty array. It represents the {{MessagePort}} array being sent.

Events

-

The following events are dispatched on {{ServiceWorkerGlobalScope}} object:

+ The following events are dispatched on {{ServiceWorkerGlobalScope}} object:
oninstallinstall{{install!!event}}
onactivateactivate{{activate!!event}}
onfetchfetch{{fetch!!event}}
onmessage
@@ -1637,17 +1422,17 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 - + - + - + @@ -1663,24 +1448,26 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231

Caches

-

To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An origin can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across origins, and they are completely isolated from the browser's HTTP cache.

+ To allow authors to fully manage their content caches for offline use, the {{Window}} and the {{WorkerGlobalScope}} provide the asynchronous caching methods that open and manipulate {{Cache}} objects. An [=environment settings object/origin=] can have multiple, named {{Cache}} objects, whose contents are entirely under the control of scripts. Caches are not shared across [=/origins=], and they are completely isolated from the browser's HTTP cache.

Constructs

-

A fetching record is a Record {\[[key]], \[[value]]} where \[[key]] is a {{Request}} and \[[value]] is a {{Response}}.

-

A fetching record has an associated incumbent record (a fetching record). It is initially set to null.

-

A request to response map is a List of fetching records.

+ A fetching record is a Record {\[[key]], \[[value]]} where \[[key]] is a {{Request}} and \[[value]] is a {{Response}}. + + A fetching record has an associated incumbent record (a fetching record). It is initially set to null. + + A request to response map is a List of fetching records. -

A name to cache map is a List of the Record {\[[key]], \[[value]]} where \[[key]] is a string that represents a name of the {{Cache}} object and \[[value]] is a {{Cache}} object.

+ A name to cache map is an ordered map where the keys are strings that represents a name of the {{Cache}} object, and the values are {{Cache}} objects. -

Each origin has an associated name to cache map.

+ Each [=/origin=] has an associated name to cache map.

Understanding Cache Lifetimes

-

The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the service worker script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the service worker that can safely operate on.

+ The {{Cache}} instances are not part of the browser's HTTP cache. The {{Cache}} objects are exactly what authors have to manage themselves. The {{Cache}} objects do not get updated unless authors explicitly request them to be. The {{Cache}} objects do not expire unless authors delete the entries. The {{Cache}} objects do not disappear just because the [=/service worker=] script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the [=/service worker=] that can safely operate on.
@@ -1695,7 +1482,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231

{{WindowOrWorkerGlobalScope/caches}}

-

caches attribute must return this object's associated {{CacheStorage}} object.

+ caches attribute *must* return this object's associated {{CacheStorage}} object.
@@ -1731,401 +1518,236 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231 }; -

A {{Cache}} object represents a request to response map. Multiple separate objects implementing the {{Cache}} interface across documents and workers can all be associated with the same request to response map simultaneously.

+ A {{Cache}} object represents a request to response map. Multiple separate objects implementing the {{Cache}} interface across documents and workers can all be associated with the same request to response map simultaneously. -

{{Cache}} objects are always enumerable via {{WindowOrWorkerGlobalScope/caches|self.caches}} in insertion order (per ECMAScript 6 Map objects).

+ {{Cache}} objects are always enumerable via {{WindowOrWorkerGlobalScope/caches|self.caches}} in insertion order (per ECMAScript 6 Map objects).

{{Cache/match(request, options)}}

-

match(request, options) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. Let p be the result of running the algorithm specified in {{Cache/matchAll(request, options)}} method with request and options as the arguments.
    2. -
    3. Wait until p settles.
    4. -
    5. If p rejects with an exception, then: -
        -
      1. Reject promise with that exception.
      2. -
      -
    6. -
    7. Else if p resolves with an array, responseArray, then: -
        -
      1. If responseArray is an empty array, then: -
          -
        1. Resolve promise with undefined.
        2. -
        -
      2. -
      3. Else: -
          -
        1. Resolve promise with the first element of responseArray.
        2. -
        -
      4. -
      -
    8. -
    -
  4. -
  5. Return promise.
  6. -
+ match(|request|, |options|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |p| be the result of running the algorithm specified in {{Cache/matchAll(request, options)}} method with |request| and |options| as the arguments. + 1. Wait until |p| settles. + 1. If |p| rejects with an exception, then: + 1. Reject |promise| with that exception. + 1. Else if |p| resolves with an array, |responseArray|, then: + 1. If |responseArray| is an empty array, then: + 1. Resolve |promise| with undefined. + 1. Else: + 1. Resolve |promise| with the first element of |responseArray|. + 1. Return |promise|.

{{Cache/matchAll(request, options)}}

-

matchAll(request, options) method must run these steps:

- -
    -
  1. Let r be null.
  2. -
  3. If the optional argument request is not omitted, then: -
      -
    1. If request is a {{Request}} object, then: -
        -
      1. Set r to request's request.
      2. -
      3. If r's method is not `GET` and options.ignoreMethod is false, return a promise resolved with an empty array.
      4. -
      -
    2. -
    3. Else if request is a string, then: -
        -
      1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
      2. -
      -
    4. -
    -
  4. -
  5. Let promise be a new promise.
  6. -
  7. Run these substeps in parallel: -
      -
    1. Let responseArray be an empty array.
    2. -
    3. If the optional argument request is omitted, then: -
        -
      1. For each fetching record entry of its request to response map, in key insertion order: -
          -
        1. Add a copy of entry.\[[value]] to responseArray.
        2. -
        -
      2. -
      3. Resolve promise with responseArray.
      4. -
      5. Abort these steps.
      6. -
      -
    4. -
    5. Else: -
        -
      1. Let entries be the result of running Query Cache algorithm passing a {{Request}} object associated with r and options as the arguments.
      2. -
      3. For each entry of entries: -
          -
        1. Let response be null.
        2. -
        3. If the incumbent record incumbentRecord of the corresponding fetching record fetchingRecord in request to response map is not null, set response to a copy of incumbentRecord.\[[value]].
        4. -
        5. Else, set response to a copy of entry[1].
        6. -
        7. Add response to responseArray.
        8. -
        -
      4. -
      5. Resolve promise with responseArray.
      6. -
      -
    6. -
    -
  8. -
  9. Return promise.
  10. -
+ matchAll(|request|, |options|) method *must* run these steps: + + 1. Let |r| be null. + 1. If the optional argument |request| is not omitted, then: + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/method=] is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with an empty array. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |responseArray| be an empty array. + 1. If the optional argument |request| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Add a copy of |entry|.\[[value]] to |responseArray|. + 1. Resolve |promise| with |responseArray|. + 1. Abort these steps. + 1. Else: + 1. Let |entries| be the result of running Query Cache algorithm passing a {{Request}} object associated with |r| and |options| as the arguments. + 1. For each |entry| of |entries|: + 1. Let |response| be null. + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record in request to response map is not null, set |response| to a copy of |incumbentRecord|.\[[value]]. + 1. Else, set |response| to a copy of |entry|[1]. + 1. Add |response| to |responseArray|. + 1. Resolve |promise| with |responseArray|. + 1. Return |promise|.

{{Cache/add(request)}}

-

add(request) method must run these steps:

+ add(|request|) method *must* run these steps: -
    -
  1. Let requests be an array containing only request.
  2. -
  3. Set responseArrayPromise to the result of running the algorithm specified in {{Cache/addAll(requests)}} passing requests as the argument.
  4. -
  5. Return the result of transforming responseArrayPromise with a fulfillment handler that returns undefined.
  6. -
+ 1. Let |requests| be an array containing only |request|. + 1. Set |responseArrayPromise| to the result of running the algorithm specified in {{Cache/addAll(requests)}} passing |requests| as the argument. + 1. Return the result of transforming |responseArrayPromise| with a fulfillment handler that returns undefined.

{{Cache/addAll(requests)}}

-

addAll(requests) method must run these steps:

- -
    -
  1. Let responsePromiseArray be an empty array.
  2. -
  3. Let requestArray be an empty array.
  4. -
  5. For each request whose type is {{Request}} in requests: -
      -
    1. Let r be request's request.
    2. -
    3. If r's url's scheme is not one of "http" and "https", or r's method is not `GET`, return a promise rejected with a TypeError.
    4. -
    -
  6. -
  7. For each request in requests: -
      -
    1. Let r be the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
    2. -
    3. If r's url's scheme is not one of "http" and "https", then: -
        -
      1. Terminate all the ongoing fetches initiated by requests with reason fatal.
      2. -
      3. Break the loop.
      4. -
      -
    4. -
    5. Set r's initiator to "fetch" and destination to "subresource".
    6. -
    7. Add a {{Request}} object associated with r to requestArray.
    8. -
    9. Let responsePromise be a new promise.
    10. -
    11. Run the following substeps in parallel: -
        -
      • Fetch r.
      • -
      • To process response for response, run these substeps: -
          -
        1. If response's type is "error", or response's status is not an ok status, reject responsePromise with a TypeError.
        2. -
        3. Else if response's header list contains a header named `Vary`, then: -
            -
          1. Let varyHeaders be the array containing the elements corresponding to the field-values of the Vary header.
          2. -
          3. Let matchAsterisk be false.
          4. -
          5. For each f in varyHeaders: -
              -
            1. If f matches "*", set matchAsterisk to true and break the loop.
            2. -
            -
          6. -
          7. If matchAsterisk is true, reject responsePromise with a TypeError.
          8. -
          9. Else, resolve responsePromise with a new {{Response}} object associated with response and a new {{Headers}} object whose guard is "immutable".
          10. -
          -
        4. -
        5. Else, resolve responsePromise with a new {{Response}} object associated with response and a new {{Headers}} object whose guard is "immutable".
        6. -
        -

        This step ensures that the promise for this fetch resolves as soon as the response's headers become available.

        -
      • -
      • To process response body for response, do nothing.
      • -
      • To process response end-of-file for response, do nothing.
      • -
      -
    12. -
    13. Add responsePromise to responsePromiseArray.
    14. -
    -
  8. -
  9. Let p be waiting for all of responsePromiseArray.
  10. -
  11. Return the result of transforming p with a fulfillment handler that, when called with argument responseArray, performs the following substeps in parallel: -
      -
    1. Let operations be an empty array.
    2. -
    3. For each response in responseArray with the index index: -
        -
      1. Let o be an empty object representing a {{CacheBatchOperation}} dictionary.
      2. -
      3. Set the {{CacheBatchOperation/type}} dictionary member of o to "put".
      4. -
      5. Set the {{CacheBatchOperation/request}} dictionary member of o to requestArray[index].
      6. -
      7. Set the {{CacheBatchOperation/response}} dictionary member of o to response.
      8. -
      9. Add o to operations.
      10. -
      -
    4. -
    5. Let resultPromise be the result of running Batch Cache Operations algorithm passing operations as the argument.
    6. -
    7. Return the result of transforming resultPromise with a fulfillment handler that, when called with argument responses, performs the following substeps in parallel: -
        -
      1. Let responseBodyPromiseArray be an empty array.
      2. -
      3. For each response in responses: -
          -
        1. Let responseBodyPromise be a new promise.
        2. -
        3. Run the following substeps in parallel: -
            -
          1. Wait for either end-of-file to have been pushed to response's associated response r's body or for r to have a termination reason.
          2. -
          3. If r had a termination reason, then: -
              -
            1. If the incumbent record incumbentRecord of the corresponding fetching record fetchingRecord in request to response map is not null, then: -
                -
              1. Set fetchingRecord in request to response map to the copy of incumbentRecord.
              2. -
              -
            2. -
            3. Else: -
                -
              1. Delete fetchingRecord from request to response map.
              2. -
              -
            4. -
            5. Reject responseBodyPromise with a TypeError.
            6. -
            -
          4. -
          5. Else: -
              -
            1. Set the incumbent record of the corresponding fetching record fetchingRecord in request to response map to the copy of fetchingRecord.
            2. -
            3. Let invalidRecords be the result of running Query Cache algorithm passing fetchingRecord.\[[key]] as the argument.
            4. -
            5. For each invalidRecord in invalidRecords: -
                -
              1. If invalidRecord is not fetchingRecord, delete it from request to response map.
              2. -
              -
            6. -
            7. Resolve responseBodyPromise with response.
            8. -
            -
          6. -
          -
        4. -
        5. Add responseBodyPromise to responseBodyPromiseArray.
        6. -
        -
      4. -
      5. Let q be waiting for all of responseBodyPromiseArray.
      6. -
      7. Return the result of transforming q with a fulfillment handler that returns undefined.
      8. -
      -
    8. -
    -
  12. -
+ addAll(|requests|) method *must* run these steps: + + 1. Let |responsePromiseArray| be an empty array. + 1. Let |requestArray| be an empty array. + 1. For each |request| whose type is {{Request}} in |requests|: + 1. Let |r| be |request|'s [=Request/request=]. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", or |r|'s [=request/method=] is not \`GET\`, return a promise rejected with a TypeError. + 1. For each |request| in |requests|: + 1. Let |r| be the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", then: + 1. [=fetch/Terminate=] all the ongoing fetches initiated by |requests| with reason *fatal*. + 1. Break the loop. + 1. Set |r|'s [=request/initiator=] to "fetch" and [=request/destination=] to "subresource". + 1. Add a {{Request}} object associated with |r| to |requestArray|. + 1. Let |responsePromise| be a new promise. + 1. Run the following substeps in parallel: + * [=/Fetch=] |r|. + * To process response for |response|, run these substeps: + 1. If |response|'s [=response/type=] is "error", or |response|'s [=response/status=] is not an ok status, reject |responsePromise| with a TypeError. + 1. Else if |response|'s [=response/header list=] contains a header [=header/named=] \`Vary\`, then: + 1. Let |varyHeaders| be the array containing the elements corresponding to the [=http/field-values=] of the Vary header. + 1. Let |matchAsterisk| be false. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", set |matchAsterisk| to true and break the loop. + 1. If |matchAsterisk| is true, reject |responsePromise| with a TypeError. + 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". + 1. Else, resolve |responsePromise| with a new {{Response}} object associated with |response| and a new {{Headers}} object whose guard is "immutable". + + Note: This step ensures that the promise for this fetch resolves as soon as the response's headers become available. + + * To process response end-of-body for |response|, do nothing. + * To process response done for |response|, do nothing. + 1. Add |responsePromise| to |responsePromiseArray|. + 1. Let |p| be waiting for all of |responsePromiseArray|. + 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |responseArray|, performs the following substeps in parallel: + 1. Let |operations| be an empty array. + 1. For each |response| in |responseArray| with the index |index|: + 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. + 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "put". + 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to |requestArray|[|index|]. + 1. Set the {{CacheBatchOperation/response}} dictionary member of |o| to |response|. + 1. Add |o| to |operations|. + 1. Let |resultPromise| be the result of running Batch Cache Operations algorithm passing |operations| as the argument. + 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: + 1. Let |responseBodyPromiseArray| be an empty array. + 1. For each |response| in |responses|: + 1. Let |responseBodyPromise| be a new promise. + 1. Run the following substeps in parallel: + 1. Wait for either end-of-file to have been pushed to |response|'s associated [=Response/response=] |r|'s [=response/body=] or for |r| to have a [=response/termination reason=]. + 1. If |r| had a [=response/termination reason=], then: + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: + 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. + 1. Else: + 1. Delete |fetchingRecord| from request to response map. + 1. Reject |responseBodyPromise| with a TypeError. + 1. Else: + 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. + 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. + 1. For each |invalidRecord| in |invalidRecords|: + 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. + 1. Resolve |responseBodyPromise| with |response|. + 1. Add |responseBodyPromise| to |responseBodyPromiseArray|. + 1. Let |q| be waiting for all of |responseBodyPromiseArray|. + 1. Return the result of transforming |q| with a fulfillment handler that returns undefined.

{{Cache/put(request, response)}}

-

put(request, response) method must run these steps:

- -
    -
  1. Let r be null.
  2. -
  3. If request is a {{Request}} object, then: -
      -
    1. Set r to request's request.
    2. -
    3. If r's url's scheme is not one of "http" and "https", or r's method is not `GET`, return a promise rejected with a TypeError.
    4. -
    -
  4. -
  5. Else if request is a string, then: -
      -
    1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
    2. -
    3. If r's url's scheme is not one of "http" and "https", return a promise rejected with a TypeError.
    4. -
    -
  6. -
  7. If response's associated response's header list contains a header named `Vary`, then: -
      -
    1. Let varyHeaders be the array containing the elements corresponding to the field-values of the Vary header.
    2. -
    3. For each f in varyHeaders: -
        -
      1. If f matches "*", return a promise rejected with a TypeError.
      2. -
      -
    4. -
    -
  8. -
  9. If response is disturbed or locked, return a promise rejected with a TypeError.
  10. -
  11. Let newResponse be a new {{Response}} object associated with response's associated response and a new {{Headers}} object whose guard is response's {{Headers}}' guard.
  12. -
  13. If response's body is non-null, run these substeps: -
      -
    1. Let dummyStream be an empty ReadableStream object.
    2. -
    3. Set response's body to a new body whose stream is dummyStream.
    4. -
    5. Let reader be the result of getting a reader from dummyStream.
    6. -
    7. Read all bytes from dummyStream with reader.
    8. -
    -
  14. -
  15. Let operations be an empty array.
  16. -
  17. Let o be an empty object representing a {{CacheBatchOperation}} dictionary.
  18. -
  19. Set the {{CacheBatchOperation/type}} dictionary member of o to "put".
  20. -
  21. Set the {{CacheBatchOperation/request}} dictionary member of o to a {{Request}} object associated with r.
  22. -
  23. Set the {{CacheBatchOperation/response}} dictionary member of o to newResponse.
  24. -
  25. Add o to operations.
  26. -
  27. Let resultPromise be the result of running Batch Cache Operations passing operations as the argument.
  28. -
  29. Return the result of transforming resultPromise with a fulfillment handler that, when called with argument responses, performs the following substeps in parallel: -
      -
    1. Wait for either end-of-file to have been pushed to responses[0]'s associated response r's body or for r to have a termination reason.
    2. -
    3. If r had a termination reason, then: -
        -
      1. If the incumbent record incumbentRecord of the corresponding fetching record fetchingRecord in request to response map is not null, then: -
          -
        1. Set fetchingRecord in request to response map to the copy of incumbentRecord.
        2. -
        -
      2. -
      3. Else: -
          -
        1. Delete fetchingRecord from request to response map.
        2. -
        -
      4. -
      5. Throw a TypeError.
      6. -
      -
    4. -
    5. Else: -
        -
      1. Set the incumbent record of the corresponding fetching record fetchingRecord in request to response map to the copy of fetchingRecord.
      2. -
      3. Let invalidRecords be the result of running Query Cache algorithm passing fetchingRecord.\[[key]] as the argument.
      4. -
      5. For each invalidRecord in invalidRecords: -
          -
        1. If invalidRecord is not fetchingRecord, delete it from request to response map.
        2. -
        -
      6. -
      7. Return undefined.
      8. -
      -
    6. -
    -
  30. -
+ put(|request|, |response|) method *must* run these steps: + + 1. Let |r| be null. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", or |r|'s [=request/method=] is not \`GET\`, return a promise rejected with a TypeError. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", return a promise rejected with a TypeError. + 1. If |response|'s associated [=Response/response=]'s [=response/header list=] contains a header [=header/named=] \`Vary\`, then: + 1. Let |varyHeaders| be the array containing the elements corresponding to the [=http/field-values=] of the Vary header. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", return a promise rejected with a TypeError. + 1. If |response| is disturbed or locked, return a promise rejected with a TypeError. + 1. Let |newResponse| be a new {{Response}} object associated with |response|'s associated [=/response=] and a new {{Headers}} object whose guard is |response|'s {{Headers}}' guard. + 1. If |response|'s body is non-null, run these substeps: + 1. Let |dummyStream| be an empty {{ReadableStream}} object. + 1. Set |response|'s [=response/body=] to a new [=/body=] whose stream is |dummyStream|. + 1. Let |reader| be the result of getting a reader from |dummyStream|. + 1. Read all bytes from |dummyStream| with |reader|. + 1. Let |operations| be an empty array. + 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. + 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "put". + 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to a {{Request}} object associated with |r|. + 1. Set the {{CacheBatchOperation/response}} dictionary member of |o| to |newResponse|. + 1. Add |o| to |operations|. + 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. + 1. Return the result of transforming |resultPromise| with a fulfillment handler that, when called with argument |responses|, performs the following substeps in parallel: + 1. Wait for either end-of-file to have been pushed to |responses|[0]'s associated [=Response/response=] |r|'s [=response/body=] or for |r| to have a [=response/termination reason=]. + 1. If |r| had a [=response/termination reason=], then: + 1. If the incumbent record |incumbentRecord| of the corresponding fetching record |fetchingRecord| in request to response map is not null, then: + 1. Set |fetchingRecord| in request to response map to the copy of |incumbentRecord|. + 1. Else: + 1. Delete |fetchingRecord| from request to response map. + 1. Throw a TypeError. + 1. Else: + 1. Set the incumbent record of the corresponding fetching record |fetchingRecord| in request to response map to the copy of |fetchingRecord|. + 1. Let |invalidRecords| be the result of running Query Cache algorithm passing |fetchingRecord|.\[[key]] as the argument. + 1. For each |invalidRecord| in |invalidRecords|: + 1. If |invalidRecord| is not |fetchingRecord|, delete it from request to response map. + 1. Return undefined.

{{Cache/delete(request, options)}}

-

delete(request, options) method must run these steps:

- -
    -
  1. Let r be null.
  2. -
  3. If request is a {{Request}} object, then: -
      -
    1. Set r to request's request.
    2. -
    3. If r's method is not `GET` and options.ignoreMethod is false, return a promise resolved with false.
    4. -
    -
  4. -
  5. Else if request is a string, then: -
      -
    1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
    2. -
    -
  6. -
  7. Let operations be an empty array.
  8. -
  9. Let o be an empty object representing a {{CacheBatchOperation}} dictionary.
  10. -
  11. Set the {{CacheBatchOperation/type}} dictionary member of o to "delete".
  12. -
  13. Set the {{CacheBatchOperation/request}} dictionary member of o to a {{Request}} object associated with r.
  14. -
  15. Set the {{CacheBatchOperation/options}} dictionary member of o to options.
  16. -
  17. Add o to operations.
  18. -
  19. Let resultPromise be the result of running Batch Cache Operations passing operations as the argument.
  20. -
  21. Return the result of transforming resultPromise with a fulfillment handler, when called with argument responseArray, performs the following substeps in parallel: -
      -
    1. If responseArray is not null, return true.
    2. -
    3. Else, return false.
    4. -
    -
  22. -
+ delete(|request|, |options|) method *must* run these steps: + + 1. Let |r| be null. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/method=] is not \`GET\` and |options|.ignoreMethod is false, return a promise resolved with false. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |operations| be an empty array. + 1. Let |o| be an empty object representing a {{CacheBatchOperation}} dictionary. + 1. Set the {{CacheBatchOperation/type}} dictionary member of |o| to "delete". + 1. Set the {{CacheBatchOperation/request}} dictionary member of |o| to a {{Request}} object associated with |r|. + 1. Set the {{CacheBatchOperation/options}} dictionary member of |o| to |options|. + 1. Add |o| to |operations|. + 1. Let |resultPromise| be the result of running Batch Cache Operations passing |operations| as the argument. + 1. Return the result of transforming |resultPromise| with a fulfillment handler, when called with argument |responseArray|, performs the following substeps in parallel: + 1. If |responseArray| is not null, return true. + 1. Else, return false.

{{Cache/keys(request, options)}}

-

keys(request, options) method must run these steps:

- -
    -
  1. Let promise be a new promise.
  2. -
  3. Run these substeps in parallel: -
      -
    1. Let resultArray be an empty array.
    2. -
    3. If the optional argument request is omitted, then: -
        -
      1. For each fetching record entry of its request to response map, in key insertion order: -
          -
        1. Add entry.\[[key]] to resultArray.
        2. -
        -
      2. -
      -
    4. -
    5. Else: -
        -
      1. Let r be null.
      2. -
      3. If request is a {{Request}} object, then: -
          -
        1. Set r to request's request.
        2. -
        3. If r's method is not `GET` and options.ignoreMethod is false, resolve promise with an empty array.
        4. -
        -
      4. -
      5. Else if request is a string, then: -
          -
        1. Set r to the associated request of the result of invoking the initial value of {{Request}} as constructor with request as its argument. If this throws an exception, return a promise rejected with that exception.
        2. -
        -
      6. -
      7. Let requestResponseArray be the result of running Query Cache algorithm passing a {{Request}} object that represents r and options as the arguments.
      8. -
      9. For each requestResponse in requestResponseArray: -
          -
        1. Add requestResponse[0] to resultArray.
        2. -
        -
      10. -
      -
    6. -
    7. Resolve promise with resultArray.
    8. -
    -
  4. -
  5. Return promise.
  6. -
+ keys(|request|, |options|) method *must* run these steps: + + 1. Let |promise| be a new promise. + 1. Run these substeps in parallel: + 1. Let |resultArray| be an empty array. + 1. If the optional argument |request| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Add |entry|.\[[key]] to |resultArray|. + 1. Else: + 1. Let |r| be null. + 1. If |request| is a {{Request}} object, then: + 1. Set |r| to |request|'s [=Request/request=]. + 1. If |r|'s [=request/method=] is not \`GET\` and |options|.ignoreMethod is false, resolve |promise| with an empty array. + 1. Else if |request| is a string, then: + 1. Set |r| to the associated [=Request/request=] of the result of invoking the initial value of {{Request}} as constructor with |request| as its argument. If this throws an exception, return a promise rejected with that exception. + 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing a {{Request}} object that represents |r| and |options| as the arguments. + 1. For each |requestResponse| in |requestResponseArray|: + 1. Add |requestResponse|[0] to |resultArray|. + 1. Resolve |promise| with |resultArray|. + 1. Return |promise|.
-

{{CacheStorage}}

+

{{CacheStorage}}

       [SecureContext, Exposed=(Window,Worker)]
@@ -2137,156 +1759,91 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
         [NewObject] Promise<sequence<DOMString>> keys();
       };
     
- + -

{{CacheStorage}} interface is designed to largely conform to ECMAScript 6 Map objects but entirely async, and with additional convenience methods. The methods, clear, forEach, entries and values, are intentionally excluded from the scope of the first version resorting to the ongoing discussion about the async iteration by TC39.

+ Note: {{CacheStorage}} interface is designed to largely conform to ECMAScript 6 Map objects but entirely async, and with additional convenience methods. The methods, clear, forEach, entries and values, are intentionally excluded from the scope of the first version resorting to the ongoing discussion about the async iteration by TC39. -

The user agent must create a {{CacheStorage}} object when a {{Window}} object or a {{WorkerGlobalScope}} object is created and associate it with that global object.

+ The user agent *must* create a {{CacheStorage}} object when a {{Window}} object or a {{WorkerGlobalScope}} object is created and associate it with that global object. -

A {{CacheStorage}} object represents a name to cache map of its associated global object's environment settings object's origin. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously.

+ A {{CacheStorage}} object represents a name to cache map of its associated [=CacheStorage/global object=]'s environment settings object's [=environment settings object/origin=]. Multiple separate objects implementing the {{CacheStorage}} interface across documents and workers can all be associated with the same name to cache map simultaneously.

{{CacheStorage/match(request, options)}}

-

match(request, options) method must run these steps:

- -
    -
  1. If options.{{CacheQueryOptions/cacheName}} is present, then: -
      -
    1. Return a new promise p and run the following substeps in parallel: -
        -
      1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
          -
        1. If options.{{CacheQueryOptions/cacheName}} matches entry.\[[key]], then: -
            -
          1. Resolve p with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with request and options as the arguments (providing entry.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.)
          2. -
          3. Abort these steps.
          4. -
          -
        2. -
        -
      2. -
      3. Resolve p with undefined.
      4. -
      -
    2. -
    -
  2. -
  3. Else: -
      -
    1. Let p be a promise resolved with undefined.
    2. -
    3. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. Set p to the result of transforming itself with a fulfillment handler that, when called with argument v, performs the following substeps in parallel: -
          -
        1. If v is not undefined, return v.
        2. -
        3. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with request and options as the arguments (providing entry.\[[value]] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.)
        4. -
        -
      2. -
      -
    4. -
    5. Return p.
    6. -
    -
  4. -
+ match(|request|, |options|) method *must* run these steps: + + 1. If |options|.{{CacheQueryOptions/cacheName}} is present, then: + 1. Return a new promise |p| and run the following substeps in parallel: + 1. [=map/For each=] |cacheName| → |cache| of name to cache map: + 1. If |options|.{{CacheQueryOptions/cacheName}} matches |cacheName|, then: + 1. Resolve |p| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache| as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. Abort these steps. + 1. Resolve |p| with undefined. + 1. Else: + 1. Let |p| be a promise resolved with undefined. + 1. [=map/For each=] cacheName → |cache| of name to cache map: + 1. Set |p| to the result of transforming itself with a fulfillment handler that, when called with argument |v|, performs the following substeps in parallel: + 1. If |v| is not undefined, return |v|. + 1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache|] as thisArgument to the \[[Call]] internal method of {{Cache/match(request, options)}}.) + 1. Return |p|.

{{CacheStorage/has(cacheName)}}

-

has(cacheName) method must run these steps:

- -
    -
  1. Return a promise p resolved with the result of running the following substeps: -
      -
    1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. If cacheName matches entry.\[[key]], then: -
          -
        1. Return true.
        2. -
        -
      2. -
      -
    2. -
    3. Return false.
    4. -
    -
  2. -
+ has(|cacheName|) method *must* run these steps: + + 1. Return a promise resolved with the result of running the following substeps: + 1. [=map/For each=] |key| → value of name to cache map: + 1. If |cacheName| matches |key|, then: + 1. Return true. + 1. Return false.

{{CacheStorage/open(cacheName)}}

-

open(cacheName) method must run these steps:

- -
    -
  1. Let p be a new promise.
  2. -
  3. Run the following substeps: -
      -
    1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. If cacheName matches entry.\[[key]], then: -
          -
        1. Resolve p with a new {{Cache}} object which is a copy of entry.\[[value]].
        2. -
        3. Abort these steps.
        4. -
        -
      2. -
      -
    2. -
    3. Let cache be a new {{Cache}} object.
    4. -
    5. Set a newly-created Record {\[[key]]: cacheName, \[[value]]: cache} to name to cache map. If this cache write operation failed due to exceeding the granted quota limit, reject p with a "{{QuotaExceededError}}" exception and abort these steps.
    6. -
    7. Resolve p with cache.
    8. -
    -
  4. -
  5. Return p.
  6. -
+ open(|cacheName|) method *must* run these steps: + + 1. Let |p| be a new promise. + 1. Run the following substeps: + 1. [=map/For each=] |key| → |value| of name to cache map: + 1. If |cacheName| matches |key|, then: + 1. Resolve |p| with a new {{Cache}} object which is a copy of |value|. + 1. Abort these steps. + 1. Let |cache| be a new {{Cache}} object. + 1. [=map/Set=] name to cache map[|cacheName|] to |cache|. If this cache write operation failed due to exceeding the granted quota limit, reject |p| with a "{{QuotaExceededError}}" exception and abort these steps. + 1. Resolve |p| with |cache|. + 1. Return |p|.

{{CacheStorage/delete(cacheName)}}

-

delete(cacheName) method must run these steps:

- -
    -
  1. Let p be the result of running the algorithm specified in {{CacheStorage/has(cacheName)}} method with cacheName as the argument.
  2. -
  3. Return the result of transforming p with a fulfillment handler that, when called with argument cacheExists, performs the following substeps in parallel: -
      -
    1. If cacheExists is true, then: -
        -
      1. Delete a Record {\[[key]], \[[value]]} entry from its name to cache map where cacheName matches entry.\[[key]].
      2. -
      3. Return true.
      4. -
      5. Abort these steps.
      6. -
      -

      After this step, the existing DOM objects (i.e. the currently referenced Cache, Request, and Response objects) should remain functional.

      -
    2. -
    3. Else: -
        -
      1. Return false.
      2. -
      -
    4. -
    -
  4. -
+ delete(|cacheName|) method *must* run these steps: + + 1. Let |p| be the result of running the algorithm specified in {{CacheStorage/has(cacheName)}} method with |cacheName| as the argument. + 1. Return the result of transforming |p| with a fulfillment handler that, when called with argument |cacheExists|, performs the following substeps in parallel: + 1. If |cacheExists| is true, then: + 1. Delete a Record {\[[key]], \[[value]]} entry from its name to cache map where |cacheName| matches entry.\[[key]]. + 1. Return true. + 1. Abort these steps. + + Note: After this step, the existing DOM objects (i.e. the currently referenced Cache, Request, and Response objects) should remain functional. + + 1. Else: + 1. Return false.

{{CacheStorage/keys()}}

-

keys() method must run these steps:

+ keys() method *must* run these steps: -

The promise returned from this method resolves with the sequence of keys, cache names in DOMString, in insertion order.

+ Note: The promise returned from this method resolves with the sequence of keys, cache names in DOMString, in insertion order. -
    -
  1. Let resultArray be an empty array.
  2. -
  3. Return a promise p resolved with the result of running the following substeps: -
      -
    1. For each Record {\[[key]], \[[value]]} entry of its name to cache map, in key insertion order: -
        -
      1. Add entry.\[[key]] to resultArray.
      2. -
      -
    2. -
    3. Return resultArray.
    4. -
    -
  4. -
+ 1. Let |cacheKeys| be the result of [=map/get the keys|getting the keys=] of name to cache map. + 1. Return |cacheKeys|.
@@ -2297,19 +1854,18 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231

Secure Context

-

Service workers must execute in secure contexts. Service worker clients must also be secure contexts to register a service worker registration, to get access to the service worker registrations and the service workers, to do messaging with the service workers, and to be manipulated by the service workers. This effectively means that service workers and their service worker clients should be hosted over HTTPS. A user agent may allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts.

+ [=/Service workers=] *must* execute in secure contexts. [=/Service worker clients=] *must* also be secure contexts to register a [=/service worker registration=], to get access to the [=/service worker registrations=] and the [=/service workers=], to do messaging with the [=/service workers=], and to be manipulated by the [=/service workers=]. This effectively means that [=/service workers=] and their [=/service worker clients=] *should* be hosted over HTTPS. A user agent *may* allow localhost, 127.0.0.0/8, and ::1/128 for development purpose. (Note that they may still be secure contexts.) The primary reason for this restriction is to protect users from the risks associated with insecure contexts.

Content Security Policy

-

Whenever a user agent invokes Run Service Worker algorithm with a service worker serviceWorker: -

    -
  • If serviceWorker's script resource was delivered with a Content-Security-Policy HTTP header containing the value policy, the user agent must enforce policy for serviceWorker.
  • -
  • If serviceWorker's script resource was delivered with a Content-Security-Policy-Report-Only HTTP header containing the value policy, the user agent must monitor policy for serviceWorker.
  • -
-

-

The primary reason for this restriction is to mitigate a broad class of content injection vulnerabilities, such as cross-site scripting (XSS).

+ Whenever a user agent invokes Run Service Worker algorithm with a [=/service worker=] |serviceWorker|: + + * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy HTTP header containing the value |policy|, the user agent *must* enforce |policy| for |serviceWorker|. + * If |serviceWorker|'s script resource was delivered with a Content-Security-Policy-Report-Only HTTP header containing the value |policy|, the user agent *must* monitor |policy| for |serviceWorker|. + + The primary reason for this restriction is to mitigate a broad class of content injection vulnerabilities, such as cross-site scripting (XSS).
@@ -2318,85 +1874,64 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231

Origin restriction

- This section is non-normative. + *This section is non-normative.* -

A Service worker executes in the registering service worker client's origin. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other origins. Therefore, service workers cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that service workers create the opportunity for a bad actor to turn a bad day into a bad eternity.

+ A [=/service worker=] executes in the registering [=/service worker client=]'s [=environment settings object/origin=]. One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other [=/origins=]. Therefore, [=/service workers=] cannot be hosted on CDNs. But they can include resources via importScripts(). The reason for this restriction is that [=/service workers=] create the opportunity for a bad actor to turn a bad day into a bad eternity.

{{WorkerGlobalScope/importScripts(urls)}}

-

When the importScripts(urls) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent must import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and urls, and with the following steps to perform the fetch given the request request:

- -
    -
  1. Let serviceWorker be request's client's global object's service worker.
  2. -
  3. If serviceWorker's imported scripts updated flag is unset, then: -
      -
    1. Let response be the result of fetching request.
    2. -
    3. If response's unsafe response's type is not "error", and response's status is an ok status, then: -
        -
      1. If there exists a corresponding Record record for request's url in serviceWorker's script resource map, set record.\[[value]] to response.
      2. -
      3. Else, set a newly-created Record {\[[key]]: url, \[[value]]: response} to serviceWorker's script resource map.
      4. -
      -
    4. -
    5. Return response. -
    -
  4. -
  5. Else: -
      -
    1. If there exists a corresponding Record record for url in serviceWorker's script resource map, return record.\[[value]].
    2. -
    3. Else, return a network error.
    4. -
    -
  6. -
+ When the importScripts(|urls|) method is called on a {{ServiceWorkerGlobalScope}} object, the user agent *must* import scripts into worker global scope, given this {{ServiceWorkerGlobalScope}} object and |urls|, and with the following steps to [=fetching scripts/perform the fetch=] given the [=/request=] |request|: + + 1. Let |serviceWorker| be |request|'s [=request/client=]'s [=environment settings object/global object=]'s [=ServiceWorkerGlobalScope/service worker=]. + 1. If |serviceWorker|'s imported scripts updated flag is unset, then: + 1. Let |response| be the result of fetching |request|. + 1. If |response|'s unsafe response's [=response/type=] is not "error", and |response|'s [=response/status=] is an ok status, then: + 1. [=map/Set=] script resource map[|request|'s [=request/url=]] to |response| + 1. Return |response|. + 1. Else: + 1. If script resource map[|url|] [=map/exists=], return script resource map[|url|]. + 1. Else, return a network error.

Cross-Origin Resources and CORS

- This section is non-normative. + *This section is non-normative.* -

Applications tend to cache items that come from a CDN or other origin. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to fetch many sorts of off-origin resources when appropriate CORS headers are set.

-

Service workers enable this by allowing {{Cache|Caches}} to fetch and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding responses are basic filtered response, the objects stored are {{Response}} objects whose corresponding responses are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding responses are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases.

+ Applications tend to cache items that come from a CDN or other [=environment settings object/origin=]. It is possible to request many of them directly using <script>, <img>, <video> and <link> elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to [=/fetch=] many sorts of off-[=environment settings object/origin=] resources when appropriate CORS headers are set. + [=/Service workers=] enable this by allowing {{Cache|Caches}} to [=/fetch=] and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the {{Cache}} as {{Response}} objects whose corresponding [=Response/responses=] are basic filtered response, the objects stored are {{Response}} objects whose corresponding [=Response/responses=] are either CORS filtered responses or opaque filtered responses. They can be passed to {{FetchEvent/respondWith(r)|event.respondWith(r)}} method in the same manner as the {{Response}} objects whose corresponding [=Response/responses=] are basic filtered responses, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing {{Cache|Caches}} to store them allows applications to avoid re-architecting in most cases.

Implementer Concerns

- This section is non-normative. + *This section is non-normative.* -

The implementers are encouraged to note: -

    -
  • Plug-ins should not load via service workers. As plug-ins may get their security origins from their own urls, the embedding service worker cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching fetch event.
  • -
  • Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with service workers.
  • -
-

+ The implementers are encouraged to note: + + * Plug-ins should not load via [=/service workers=]. As plug-ins may get their security origins from their own urls, the embedding [=/service worker=] cannot handle it. For this reason, the Handle Fetch algorithm makes the potential-navigation-or-subresource request (whose context is either <embed> or <object>) immediately fallback to the network without dispatching {{fetch!!event}} event. + * Some of the legacy networking stack code may need to be carefully audited to understand the ramifications of interactions with [=/service workers=].

Privacy

-

Service workers introduce new persistent storage features including scope to registration map (for service worker registrations and their service workers), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages should be cleared when users intend to clear them and should maintain and interoperate with existing user controls e.g. purging all existing persistent storages.

+ [=/Service workers=] introduce new persistent storage features including scope to registration map (for [=/service worker registrations=] and their [=/service workers=]), request to response map and name to cache map (for caches), and script resource map (for script resources). In order to protect users from any potential unsanctioned tracking threat, these persistent storages *should* be cleared when users intend to clear them and *should* maintain and interoperate with existing user controls e.g. purging all existing persistent storages.
-
-

Storage Considerations

- -

Service workers should take a dependency on Quota Management API that extends the ServiceWorkerGlobalScope with the event listeners {{ServiceWorkerGlobalScope/onbeforeevicted}} and {{ServiceWorkerGlobalScope/onevicted}} to detect a storage pressure and give pre-eviction information to the application.

-

The cache write operations in service workers when failed due to exceeding the granted quota limit should throw "{{QuotaExceededError}}" exception.

- -

Extensibility

-

Service workers are extensible from other specifications.

+ [=/Service workers=] are extensible from other specifications.

Define API bound to Service Worker Registration

-

Specifications may define an API tied to a service worker registration by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it may define the specification specific attributes and methods:

+ Specifications *may* define an API tied to a [=/service worker registration=] by using partial interface definition to the {{ServiceWorkerRegistration}} interface where it *may* define the specification specific attributes and methods:
       partial interface ServiceWorkerRegistration {
@@ -2411,7 +1946,7 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
   

Define Functional Event

-

Specifications may define a functional event by extending {{ExtendableEvent}} interface:

+ Specifications *may* define a functional event by extending {{ExtendableEvent}} interface:
       // e.g. define FunctionalEvent interface
@@ -2424,11 +1959,11 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231
   

Define Event Handler

-

Specifications may define an event handler attribute for the corresponding functional event using partial interface definition to the {{ServiceWorkerGlobalScope}} interface:

+ Specifications *may* define an event handler attribute for the corresponding functional event using partial interface definition to the {{ServiceWorkerGlobalScope}} interface:
       partial interface ServiceWorkerGlobalScope {
-        attribute EventHandler onfunctionalevent;
+        attribute EventHandler onfunctionalevent;
       };
     
@@ -2436,1288 +1971,979 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231

Request Functional Event Dispatch

-

To request a functional event dispatch to a service worker, specifications may invoke Handle Functional Event algorithm with its service worker registration registration and the algorithm callbackSteps as the arguments.

+ To request a functional event dispatch to a [=/service worker=], specifications *may* invoke Handle Functional Event algorithm with its [=/service worker registration=] registration and the algorithm |callbackSteps| as the arguments. -

Specifications may define an algorithm callbackSteps where the corresponding functional event can be created and fired with specification specific objects. The algorithm is passed globalObject (a {{ServiceWorkerGlobalScope}} object) at which it may fire its functional events. This algorithm is called on a task queued by Handle Functional Event algorithm.

+ Specifications *may* define an algorithm |callbackSteps| where the corresponding functional event can be created and fired with specification specific objects. The algorithm is passed globalObject (a {{ServiceWorkerGlobalScope}} object) at which it *may* fire its functional events. This algorithm is called on a task queued by Handle Functional Event algorithm. -

See an example hook defined in Notifications API.

+ Note: See an example hook defined in Notifications API.

Appendix A: Algorithms

-

The following definitions are the user agent's internal data structures used throughout the specification.

- -

A scope to registration map is a List of the Record {\[[key]], \[[value]]} where \[[key]] is a string that represents a scope url and \[[value]] is a service worker registration.

- -

A job is an abstraction of one of register, update, and unregister request for a service worker registration.

- -

A job has a job type, which is one of register, update, and unregister.

- -

A job has a scope url (a URL).

- -

A job has a script url (a URL).

- -

A job has a worker type ("classic" or "module").

- -

A job has a client (a service worker client). It is initially null.

- -

A job has a promise (a promise). It is initially null.

- -

A job has a list of equivalent jobs (a list of jobs). It is initially the empty list.

- -

A job has a force bypass cache flag It is initially unset.

- -

Two jobs are equivalent when their job type is the same and: -

-

- -

A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue should satisfy the general properties of FIFO queue. A user agent must maintain a separate job queue for each service worker registration keyed by its scope url. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's scope url.

- -
-

Create Job

- -
-
Input
-
jobType, a job type
-
scopeURL, a URL
-
scriptURL, a URL
-
promise, a promise
-
client, a service worker client
-
Output
-
job, a job
-
-
    -
  1. Let job be a new job.
  2. -
  3. Set job's job type to jobType.
  4. -
  5. Set job's scope url to scopeURL.
  6. -
  7. Set job's script url to scriptURL.
  8. -
  9. Set job's promise to promise.
  10. -
  11. Set job's client to client.
  12. -
  13. Return job.
  14. -
-
- -
-

Schedule Job

- -
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. If the job queue is empty, then: -
      -
    1. Push job to the job queue and invoke Run Job.
    2. -
    -
  2. -
  3. Else: -
      -
    1. Let lastJob be the element at the back of the job queue.
    2. -
    3. If job is equivalent to lastJob and lastJob's promise has not settled, append job to lastJob's list of equivalent jobs.
    4. -
    5. Else, push job to the job queue.
    6. -
    -
  4. -
-
- -
-

Run Job

- -
-
Input
-
none
-
Output
-
none
-
-
    -
  1. Assert: the job queue is not empty.
  2. -
  3. Queue a task to run these steps: -
      -
    1. Let job be the element in the front of the job queue.
    2. -
    3. If job's job type is register, run Register with job in parallel.
    4. -
    5. Else if job's job type is update, run Update with job in parallel. -

      For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event.

      -
    6. -
    7. Else if job's job type is unregister, run Unregister with job in parallel.
    8. -
    -
  4. -
-
- -
-

Finish Job

- -
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. Assert: the top element in the job queue is job.
  2. -
  3. Pop the top element from the job queue.
  4. -
  5. If the job queue is not empty, invoke Run Job with the top element of the job queue.
  6. -
-
- -
-

Resolve Job Promise

- -
-
Input
-
job, a job
-
value, any
-
Output
-
none
-
-
    -
  1. If job's client is not null, queue a task to resolve job's promise with value on job's client's responsible event loop using the DOM manipulation task source as the task source.
  2. -
  3. For each equivalentJob in job's list of equivalent jobs: -
      -
    1. If equivalentJob's client is not null, queue a task to resolve equivalentJob's promise with value on equivalentJob's client's responsible event loop using the DOM manipulation task source as the task source.
    2. -
    -
  4. -
-
- -
-

Reject Job Promise

- -
-
Input
-
job, a job
-
reason, an exception
-
Output
-
none
-
-
    -
  1. If job's client is not null, queue a task to reject job's promise with reason on job's client's responsible event loop using the DOM manipulation task source as the task source.
  2. -
  3. For each equivalentJob in job's list of equivalent jobs: -
      -
    1. If equivalentJob's client is not null, queue a task to reject equivalentJob's promise with reason on equivalentJob's client's responsible event loop using the DOM manipulation task source as the task source.
    2. -
    -
  4. -
-
- -
-

Register

- -
-
Input
-
job, a job
-
Output
-
promise, a promise
-
-
    -
  1. If the result of running Is origin potentially trustworthy with the origin of job's script url as the argument is Not Trusted, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  2. -
  3. If the origin of job's script url is not job's client's origin, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  4. -
  5. If the origin of job's scope url is not job's client's origin, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  6. -
  7. Let registration be the result of running the Get Registration algorithm passing job's scope url as the argument.
  8. -
  9. If registration is not null, then: -
      -
    1. If registration's uninstalling flag is set, unset it.
    2. -
    3. Let newestWorker be the result of running the Get Newest Worker algorithm passing registration as the argument.
    4. -
    5. If newestWorker is not null and job's script url equals newestWorker's script url with the exclude fragments flag set, then: -
        -
      1. Invoke Resolve Job Promise with job and the {{ServiceWorkerRegistration}} object which represents registration.
      2. -
      3. Invoke Finish Job with job and abort these steps.
      4. -
      -
    6. -
    -
  10. -
  11. Else: -
      -
    1. Invoke Set Registration algorithm passing job's scope url as its argument.
    2. -
    -
  12. -
  13. Invoke Update algorithm passing job as the argument.
  14. -
-
- -
-

Update

- -
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. Let registration be the result of running the Get Registration algorithm passing job's scope url as the argument.
  2. -
  3. If registration is null or registration's uninstalling flag is set, then: -
      -
    1. Invoke Reject Job Promise with job and a TypeError.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  4. -
  5. Let newestWorker be the result of running Get Newest Worker algorithm passing registration as the argument.
  6. -
  7. If job's job type is update, and newestWorker's script url does not equal job's script url with the exclude fragments flag set, then: -
      -
    1. Invoke Reject Job Promise with job and a TypeError.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  8. -
  9. Let httpsState be "none".
  10. -
  11. Let referrerPolicy be the empty string.
  12. -
  13. Switching on job's worker type, run these substeps with the following options: -
    -
    "classic"
    -

    Fetch a classic worker script given job’s serialized script url, job’s client, and "serviceworker".

    -
    "module"
    -

    Fetch a module worker script graph given job’s serialized script url, job’s client, "serviceworker", "omit", and the to-be-created environment settings object for this service worker.

    -
    -

    To perform the fetch given request, run the following steps if the is top-level flag is set:

    -
      -
    1. Append `Service-Worker`/`script` to request's header list. -

      See the definition of the Service-Worker header in Appendix B: Extended HTTP headers.

      -
    2. -
    3. Set request's skip service worker flag and request's redirect mode to "error".
    4. -
    5. If newestWorker is not null and registration's last update check time is not null, then: -
        -
      1. If the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, or force bypass cache flag is set, set request's cache mode to "reload".
      2. -
      -

      Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache.

      -
    6. -
    7. Fetch request, and asynchronously wait to run the remaining steps as part of fetch's process response for the response response.
    8. -
    9. Extract a MIME type from the response's header list. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: -
        -
      1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
      2. -
      3. Asynchronously complete these steps with a network error.
      4. -
      -
    10. -
    11. Let serviceWorkerAllowed be the result of parsing `Service-Worker-Allowed` in response's header list. -

      See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers.

      -
    12. -
    13. Set httpsState to response's HTTPS state.
    14. -
    15. Set referrerPolicy to the result of parsing the `Referrer-Policy` header of response.
    16. -
    17. If serviceWorkerAllowed is failure, then: -
        -
      1. Asynchronously complete these steps with a network error.
      2. -
      -
    18. -
    19. Let scopeURL be registration's scope url.
    20. -
    21. Let maxScopeString be null.
    22. -
    23. If serviceWorkerAllowed is null, then: -
        -
      1. Set maxScopeString to "/" concatenated with the strings, except the last string that denotes the script's file name, in job's script url's path (including empty strings), separated from each other by "/".
      2. -
      -
    24. -
    25. Else: -
        -
      1. Let maxScope be the result of parsing serviceWorkerAllowed with job's script url.
      2. -
      3. Set maxScopeString to "/" concatenated with the strings in maxScope's path (including empty strings), separated from each other by "/".
      4. -
      -
    26. -
    27. Let scopeString be "/" concatenated with the strings in scopeURL's path (including empty strings), separated from each other by "/".
    28. -
    29. If scopeString starts with maxScopeString, do nothing.
    30. -
    31. Else: -
        -
      1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
      2. -
      3. Asynchronously complete these steps with a network error.
      4. -
      -
    32. -
    33. If response's cache state is not "local", set registration's last update check time to the current time. -

      The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state.

      -
    34. -
    35. Return true.
    36. -
    -

    If the algorithm asynchronously completes with null, then: -

      -
    1. -

      Invoke Reject Job Promise with job and a TypeError.

      - -

      This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception.

      -
    2. -
    3. If newestWorker is null, invoke Clear Registration algorithm passing registration as its argument.
    4. -
    5. Invoke Finish Job with job and abort these steps.
    6. -
    -

    -

    Else, continue the rest of these steps after the algorithm's asynchronous completion, with script being the asynchronous completion value.

    -
  14. -
  15. If newestWorker is not null, newestWorker's script url equals job's script url with the exclude fragments flag set, and script is a byte-for-byte match with newestWorker's script resource, then: -
      -
    1. Invoke Resolve Job Promise with job and the {{ServiceWorkerRegistration}} object which represents registration.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  16. -
  17. Else: -
      -
    1. Let worker be a new service worker.
    2. -
    3. Generate a unique opaque string and set worker's id to the value.
    4. -
    5. Set worker's script url to job's script url, worker's script resource to script, and worker's type to job's worker type.
    6. -
    7. Set worker's script resource's HTTPS state to httpsState.
    8. -
    9. Set worker's script resource's referrer policy to referrerPolicy.
    10. -
    11. Invoke Run Service Worker algorithm with worker as the argument.
    12. -
    13. If an uncaught runtime script error occurs during the above step, then: -
        -
      1. Invoke Reject Job Promise with job and a TypeError.
      2. -
      3. If newestWorker is null, invoke Clear Registration algorithm passing registration as its argument.
      4. -
      5. Invoke Finish Job with job and abort these steps.
      6. -
      -
    14. -
    -
  18. -
  19. Invoke Install algorithm with job, worker, and registration as its arguments.
  20. -
-
- -
-

Soft Update

- -

The user agent may call this as often as it likes to check for updates.

- -
-
Input
-
registration, a service worker registration
-
force bypass cache flag, an optional flag unset by default
-

Implementers may use the force bypass cache flag to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs.

-
Output
-
None
-
-
    -
  1. Let newestWorker be the result of running Get Newest Worker algorithm passing registration as its argument.
  2. -
  3. If newestWorker is null, abort these steps.
  4. -
  5. Let job be the result of running Create Job with update, registration's scope url, newestWorker's script url, null, and null.
  6. -
  7. Set job's worker type to newestWorker's type.
  8. -
  9. Set job's force bypass cache flag if its force bypass cache flag is set.
  10. -
  11. Invoke Schedule Job with job.
  12. -
-
- -
-

Install

- -
-
Input
-
job, a job
-
worker, a service worker
-
registration, a service worker registration
-
Output
-
none
-
-
    -
  1. Let installFailed be false.
  2. -
  3. Let newestWorker be the result of running Get Newest Worker algorithm passing registration as its argument.
  4. -
  5. Let redundantWorker be null.
  6. -
  7. Run the Update Registration State algorithm passing registration, "installing" and worker as the arguments.
  8. -
  9. Run the Update Worker State algorithm passing registration's installing worker and installing as the arguments.
  10. -
  11. Assert: job's promise is not null.
  12. -
  13. Invoke Resolve Job Promise with job and the {{ServiceWorkerRegistration}} object which represents registration.
  14. -
  15. 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 scope url and all the service workers whose containing service worker registration is registration.
  16. -
  17. Let installingWorker be registration's installing worker.
  18. -
  19. Invoke Run Service Worker algorithm with installingWorker as the argument.
  20. -
  21. Queue a task task to run the following substeps: -
      -
    1. Let e be the result of creating an event with {{ExtendableEvent}}.
    2. -
    3. Initialize e’s {{Event/type}} attribute to "install".
    4. -
    5. Dispatch e at installingWorker's global object.
    6. -
    7. Invoke Extend Service Worker Lifetime with e.
    8. -
    9. WaitForAsynchronousExtensions: Run the following substeps in parallel: -
        -
      1. Wait until e's extensions allowed flag is unset.
      2. -
      3. If the result of waiting for all of e's extend lifetime promises rejected, set installFailed to true.
      4. -
      -
    10. -
    -
  22. -

    If task is discarded or the script has been aborted by the termination of installingWorker, set installFailed to true.

    -
  23. Wait for task to have executed or been discarded.
  24. -
  25. Wait for the step labeled WaitForAsynchronousExtensions to complete.
  26. -
  27. If installFailed is true, then: -
      -
    1. Set redundantWorker to registration's installing worker.
    2. -
    3. Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
    4. -
    5. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    6. -
    7. If newestWorker is null, invoke Clear Registration algorithm passing registration as its argument.
    8. -
    9. Invoke Finish Job with job and abort these steps.
    10. -
    -
  28. -
  29. Set registration's installing worker's imported scripts updated flag.
  30. -
  31. If registration's waiting worker is not null, then: -
      -
    1. Set redundantWorker to registration's waiting worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    -
  32. -
  33. Run the Update Registration State algorithm passing registration, "waiting" and registration's installing worker as the arguments.
  34. -
  35. Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
  36. -
  37. Run the Update Worker State algorithm passing registration's waiting worker and installed as the arguments.
  38. -
  39. If redundantWorker is not null, run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
  40. -
  41. If registration's waiting worker's skip waiting flag is set, then: -
      -
    1. Run Activate algorithm passing registration as the argument.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  42. -
  43. Invoke Finish Job with job.
  44. -
  45. Wait for all the tasks queued by Update Worker State invoked in this algorithm have executed.
  46. -
  47. Wait until no service worker client is using registration or registration's waiting worker's skip waiting flag is set.
  48. -
  49. If registration's waiting worker waitingWorker is not null and waitingWorker's skip waiting flag is not set, invoke Activate algorithm with registration as its argument.
  50. -
-
- -
-

Activate

- -
-
Input
-
registration, a service worker registration
-
Output
-
None
-
-
    -
  1. If registration's waiting worker is null, abort these steps.
  2. -
  3. Let redundantWorker be null.
  4. -
  5. If registration's active worker is not null, then: -
      -
    1. Set redundantWorker to registration's active worker.
    2. -
    3. Wait for redundantWorker to finish handling any in-progress requests. -
    4. -
    5. Terminate redundantWorker.
    6. -
    -
  6. -
  7. Run the Update Registration State algorithm passing registration, "active" and registration's waiting worker as the arguments.
  8. -
  9. Run the Update Registration State algorithm passing registration, "waiting" and null as the arguments.
  10. -
  11. Run the Update Worker State algorithm passing registration's active worker and activating as the arguments. -

    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.

    -
  12. -
  13. If redundantWorker is not null, run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
  14. -
  15. For each service worker client client whose creation URL matches registration's scope url: -
      -
    1. If client is a window client, unassociate client's responsible document from its application cache, if it has one.
    2. -
    3. Else if client is a shared worker client, unassociate client's global object from its application cache, if it has one.
    4. -
    -

    Resources will now use the service worker registration instead of the existing application cache.

    -
  16. -
  17. For each service worker client client who is using registration: -
      -
    1. Set client's active worker to registration's active worker.
    2. -
    3. Invoke Notify Controller Change algorithm with client as the argument.
    4. -
    -
  18. -
  19. Let activeWorker be registration's active worker.
  20. -
  21. Invoke Run Service Worker algorithm with activeWorker as the argument.
  22. -
  23. Queue a task task to run the following substeps: -
      -
    1. Let e be the result of creating an event with {{ExtendableEvent}}.
    2. -
    3. Initialize e’s {{Event/type}} attribute to "activate".
    4. -
    5. Dispatch e at activeWorker's global object.
    6. -
    7. Invoke Extend Service Worker Lifetime with e.
    8. -
    9. WaitForAsynchronousExtensions: Wait, in parallel, until e's extensions allowed flag is unset.
    10. -
    -
  24. -
  25. Wait for task to have executed or been discarded, or the script to have been aborted by the termination of activeWorker.
  26. -
  27. Wait for the step labeled WaitForAsynchronousExtensions to complete.
  28. -
  29. Run the Update Worker State algorithm passing registration's active worker and activated as the arguments.
  30. -
-
- -
-

Run Service Worker

- -
-
Input
-
serviceWorker, a service worker
-
Output
-
None
-
-
    -
  1. Let script be serviceWorker's script resource.
  2. -
  3. Assert: script is not null.
  4. -
  5. If serviceWorker is already running, abort these steps.
  6. -
  7. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context.
  8. -
  9. Call the JavaScript InitializeHostDefinedRealm() abstract operation with the following customizations: -
      -
    • For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let workerGlobalScope be the created object.
    • -
    • Let realmExecutionContext be the created JavaScript execution context.
    • -
    -
  10. -
  11. Set serviceWorker's global object to workerGlobalScope.
  12. -
  13. Let workerEventLoop be a newly created event loop.
  14. -
  15. Let settingsObject be a new environment settings object whose algorithms are defined as follows: -
    -
    The realm execution context
    -
    Return realmExecutionContext.
    -
    The global object
    -
    Return workerGlobalScope.
    -
    The responsible event loop
    -
    Return workerEventLoop.
    -
    The referrer policy
    -
    Return workerGlobalScope's referrer policy.
    -
    The API URL character encoding
    -
    Return UTF-8.
    -
    The API base URL
    -
    Return serviceWorker's script url.
    -
    The origin
    -
    Return its registering service worker client's origin.
    -
    The creation URL
    -
    Return workerGlobalScope's url.
    -
    The HTTPS state
    -
    Return workerGlobalScope's HTTPS state.
    -
    -
  16. -
  17. Set workerGlobalScope's url to serviceWorker's script url.
  18. -
  19. Set workerGlobalScope's HTTPS state to serviceWorker's script resource's HTTPS state.
  20. -
  21. Set workerGlobalScope's referrer policy to serviceWorker's script resource's referrer policy.
  22. -
  23. Set workerGlobalScope's type to serviceWorker's type.
  24. -
  25. Create a new {{WorkerLocation}} object and associate it with workerGlobalScope.
  26. -
  27. If serviceWorker is an active worker, and there are any tasks queued in serviceWorker's containing service worker registration's task queues, queue them to serviceWorker's event loop's task queues in the same order using their original task sources.
  28. -
  29. If script is a classic script, then run the classic script script. Otherwise, it is a module script; run the module script script. -

    In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms.

    -
  30. -
  31. If script's has ever been evaluated flag is unset, then: -
      -
    1. Set workerGlobalScope's associated service worker's set of event types to handle to the set of event types created from settingsObject's global object's associated list of event listeners' event types. -

      If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script.

      -
    2. -
    3. Set script's has ever been evaluated flag.
    4. -
    -
  32. -
  33. Run the responsible event loop specified by settingsObject until it is destroyed.
  34. -
  35. Empty workerGlobalScope's list of active timers.
  36. -
-
- -
-

Terminate Service Worker

- -
-
Input
-
serviceWorker, a service worker
-
Output
-
None
-
-
    -
  1. If serviceWorker is not running, abort these steps.
  2. -
  3. Let serviceWorkerGlobalScope be serviceWorker's global object.
  4. -
  5. Set serviceWorkerGlobalScope's closing flag to true.
  6. -
  7. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in serviceWorkerGlobalScope's event loop's task queues, queue them to serviceWorker's containing service worker registration's corresponding task queues in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from serviceWorkerGlobalScope's event loop's task queues without processing them. -

    This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded.

    -
  8. -
  9. Abort the script currently running in serviceWorker.
  10. -
  11. Set serviceWorker's global object to null.
  12. -
-
- -
-

Extend Service Worker Lifetime

- -
-
Input
-
event, an {{ExtendableEvent}} object
-
Output
-
None
-
-
    -
  1. If event's extend lifetime promises is empty, unset event's extensions allowed flag and abort these steps.
  2. -
  3. Let extendLifetimePromises be an empty array.
  4. -
  5. Run the following substeps in parallel: -
      -
    1. SetupPromiseArray: Set extendLifetimePromises to a copy of event's extend lifetime promises.
    2. -
    3. Wait until all the promises in extendLifetimePromises settle.
    4. -
    5. If the length of extendLifetimePromises does not equal the length of event's extend lifetime promises, jump to the step labeled SetupPromiseArray.
    6. -
    7. Unset event's extensions allowed flag.
    8. -
    -
  6. -
- -

The user agent should not terminate the service worker associated with event's relevant settings object's global object until event's extensions allowed flag is unset. However, the user agent may impose a time limit to this lifetime extension.

-
- -
-

Handle Fetch

- -

The Handle Fetch algorithm is the entry point for the fetch handling handed to the service worker context.

- -
-
Input
-
request, a request
-
Output
-
response, a response
-
-
    -
  1. Let handleFetchFailed be false.
  2. -
  3. Let respondWithEntered be false.
  4. -
  5. Let eventCanceled be false.
  6. -
  7. Let r be a new {{Request}} object associated with request.
  8. -
  9. Let headersObject be r's {{Request/headers}} attribute value.
  10. -
  11. Set headersObject's guard to immutable.
  12. -
  13. Let response be null.
  14. -
  15. Let registration be null.
  16. -
  17. Let client be request's client.
  18. -
  19. Let reservedClient be request's reserved client.
  20. -
  21. Assert: request's destination is not "serviceworker".
  22. -
  23. If request is a potential-navigation-or-subresource request, then: -
      -
    1. Return null.
    2. -
    -
  24. -
  25. Else if request is a non-subresource request, then: -

    If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration.

    -
      -
    1. If reservedClient is not null and is an environment settings object, then: -
        -
      1. If reservedClient is not a secure context, return null.
      2. -
      -
    2. -
    3. Else: -
        -
      1. If request's url is not a potentially trustworthy URL, return null.
      2. -
      -
    4. -
    5. If request is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null.
    6. -
    7. Set registration to the result of running Match Service Worker Registration algorithm passing request's url as the argument.
    8. -
    9. If registration is null or registration's active worker is null, return null.
    10. -
    11. If request's destination is not "report", set reservedClient's active service worker to registration's active worker.
    12. -
    -

    From this point, the service worker client starts to use its active service worker's containing service worker registration.

    -
  26. -
  27. Else if request is a subresource request, then: -
      -
    1. If client's active service worker is non-null, set registration to client's active service worker's containing service worker registration.
    2. -
    3. Else, return null.
    4. -
    -
  28. -
  29. Let activeWorker be registration's active worker.
  30. -
  31. If activeWorker's set of event types to handle does not contain fetch, then: -
      -
    1. Return null and continue running these steps in parallel.
    2. -
    3. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    5. Abort these steps.
    6. -
    -

    To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution.

    -
  32. -
  33. If activeWorker's state is activating, wait for activeWorker's state to become activated.
  34. -
  35. Invoke Run Service Worker algorithm with activeWorker as the argument.
  36. -
  37. Queue a task task to run the following substeps: -
      -
    1. Let e be the result of creating an event with {{FetchEvent}}.
    2. -
    3. Initialize e’s {{Event/type}} attribute to "fetch".
    4. -
    5. Initialize e’s {{Event/cancelable}} attribute to true.
    6. -
    7. Initialize e’s {{FetchEvent/request}} attribute to r.
    8. -
    9. Initialize e's {{FetchEvent/clientId}} attribute to client's id.
    10. -
    11. If request is a non-subresource request and request's destination is not "report", initialize e's {{FetchEvent/reservedClientId}} attribute to reservedClient's id, and to the empty string otherwise.
    12. -
    13. If request is a navigation request, initialize e's {{FetchEvent/targetClientId}} attribute to request's target client id, and to the empty string otherwise.
    14. -
    15. Let the {{FetchEvent/isReload}} attribute of e be initialized to true if request's client is a window client and the event was dispatched with the user's intention for the page reload, and false otherwise.
    16. -
    17. Dispatch e at activeWorker's global object.
    18. -
    19. Invoke Extend Service Worker Lifetime with e.
    20. -
    21. If e's respond-with entered flag is set, set respondWithEntered to true.
    22. -
    23. If e's wait to respond flag is set, then: -
        -
      1. Wait until e's wait to respond flag is unset.
      2. -
      3. If e's respond-with error flag is set, set handleFetchFailed to true.
      4. -
      5. Else, set response to e's potential response.
      6. -
      -
    24. -
    25. If e's canceled flag is set, set eventCanceled to true.
    26. -
    -

    If task is discarded or the script has been aborted by the termination of activeWorker, set handleFetchFailed to true.

    -

    The task must use activeWorker's event loop and the handle fetch task source.

    -
  38. -
  39. Wait for task to have executed or been discarded.
  40. -
  41. If respondWithEntered is false, then: -
      -
    1. If eventCanceled is true, return a network error and continue running these steps in parallel.
    2. -
    3. Else, return null and continue running these steps in parallel.
    4. -
    5. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    6. -
    7. Abort these steps.
    8. -
    -
  42. -
  43. If handleFetchFailed is true, then: -
      -
    1. Return a network error and continue running these steps in parallel.
    2. -
    3. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    -
  44. -
  45. Else: -
      -
    1. Return response and continue running these steps in parallel.
    2. -
    3. If request is a non-subresource request, or request is a subresource request and the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    -
  46. -
-
- -
-

Handle Functional Event

- -
-
Input
-
event, an {{ExtendableEvent}} object
-
registration, a service worker registration
-
callbackSteps, an algorithm
-
Output
-
None
-
-
    -
  1. Assert: a Record with the \[[value]] equals to registration is contained in scope to registration map.
  2. -
  3. Assert: registration's active worker is not null.
  4. -
  5. Let activeWorker be registration's active worker.
  6. -
  7. If activeWorker's set of event types to handle does not contain event's {{Event/type}}, then: -
      -
    1. Return and continue running these steps in parallel.
    2. -
    3. If the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
    4. -
    5. Abort these steps.
    6. -
    -

    To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution.

    -
  8. -
  9. If activeWorker's state is activating, wait for activeWorker's state to become activated.
  10. -
  11. Invoke Run Service Worker algorithm with activeWorker as the argument.
  12. -
  13. Queue a task task to run these substeps: -
      -
    1. Invoke callbackSteps with activeWorker's global object as its argument.
    2. -
    3. Invoke Extend Service Worker Lifetime with event.
    4. -
    -

    The task must use activeWorker's event loop and the handle functional event task source.

    -
  14. -
  15. Wait for task to have executed or been discarded.
  16. -
  17. If the time difference in seconds calculated by the current time minus registration's last update check time is greater than 86400, invoke Soft Update algorithm with registration.
  18. -
-
- -
-

Handle Service Worker Client Unload

- -

The user agent must run these steps when a service worker client unloads by unloading, being killed, or terminating.

- -
-
Input
-
client, a service worker client
-
Output
-
None
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let registration be the service worker registration used by client.
  4. -
  5. If registration is null, abort these steps.
  6. -
  7. If any other service worker client is using registration, abort these steps.
  8. -
  9. If registration's uninstalling flag is set, invoke Clear Registration algorithm passing registration as its argument and abort these steps.
  10. -
  11. If registration's waiting worker is not null, run Activate algorithm with registration as the argument.
  12. -
-
- -
-

Handle User Agent Shutdown

- -
-
Input
-
None
-
Output
-
None
-
-
    -
  1. For each Record {\[[key]], \[[value]]} entry of its scope to registration map: -
      -
    1. Let registration be entry.\[[value]].
    2. -
    3. If registration's installing worker installingWorker is not null, then: -
        -
      1. If the result of running Get Newest Worker with registration is installingWorker, invoke Clear Registration with registration and continue to the next iteration of the loop.
      2. -
      3. Else, set registration's installing worker to null.
      4. -
      -
    4. -
    5. If registration's waiting worker is not null, run the following substep in parallel: -
        -
      1. Invoke Activate with registration.
      2. -
      -
    6. -
    -
  2. -
-
- -
-

Unregister

- -
-
Input
-
job, a job
-
Output
-
none
-
-
    -
  1. If the origin of job's scope url is not job's client's origin, then: -
      -
    1. Invoke Reject Job Promise with job and a "{{SecurityError}}" exception.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  2. -
  3. Let registration be the result of running Get Registration algorithm passing job's scope url as the argument.
  4. -
  5. If registration is null, then: -
      -
    1. Invoke Resolve Job Promise with job and false.
    2. -
    3. Invoke Finish Job with job and abort these steps.
    4. -
    -
  6. -
  7. Set registration's uninstalling flag.
  8. -
  9. Invoke Resolve Job Promise with job and true.
  10. -
  11. If no service worker client is using registration, invoke Clear Registration algorithm passing registration as its argument. -

    When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm.

    -
  12. -
  13. Invoke Finish Job with job.
  14. -
-
- -
-

Set Registration

- -
-
Input
-
scope, a URL
-
Output
-
registration, a service worker registration
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let scopeString be serialized scope with the exclude fragment flag set.
  4. -
  5. Let registration be a new service worker registration whose scope url is set to scope.
  6. -
  7. Set a newly-created Record {\[[key]]: scopeString, \[[value]]: registration} to scope to registration map.
  8. -
  9. Return registration.
  10. -
-
- -
-

Clear Registration

- -
-
Input
-
registration, a service worker registration
-
Output
-
None
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let redundantWorker be null.
  4. -
  5. If registration's installing worker is not null, then: -
      -
    1. Set redundantWorker to registration's installing worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    7. Run the Update Registration State algorithm passing registration, "installing" and null as the arguments.
    8. -
    9. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    10. -
    -
  6. -
  7. If registration's waiting worker is not null, then: -
      -
    1. Set redundantWorker to registration's waiting worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    7. Run the Update Registration State algorithm passing registration, "waiting" and null as the arguments.
    8. -
    9. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    10. -
    -
  8. -
  9. If registration's active worker is not null, then: -
      -
    1. Set redundantWorker to registration's active worker.
    2. -
    3. Terminate redundantWorker.
    4. -
    5. The user agent may abort in-flight requests triggered by redundantWorker.
    6. -
    7. Run the Update Registration State algorithm passing registration, "active" and null as the arguments.
    8. -
    9. Run the Update Worker State algorithm passing redundantWorker and redundant as the arguments.
    10. -
    -
  10. -
  11. Delete a Record {\[[key]], \[[value]]} entry from scope to registration map where registration's scope url is the result of parsing entry.\[[key]].
  12. -
-
- -
-

Update Registration 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.
  2. -
  3. If target is "installing", then: -
      -
    1. Set registration's installing worker to source.
    2. -
    3. 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.
      2. -
      -
    4. -
    -
  4. -
  5. Else if target is "waiting", then: -
      -
    1. Set registration's waiting worker to source.
    2. -
    3. 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.
      2. -
      -
    4. -
    -
  6. -
  7. Else if target is "active", then: -
      -
    1. Set registration's active worker to source.
    2. -
    3. 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 active worker, or null if registration’s active worker is null.
      2. -
      -
    4. -
    -

    The task must use registrationObject's relevant settings object's responsible event loop and the DOM manipulation task source.

    -
  8. -
-
- -
-

Update Worker State

- -
-
Input
-
worker, a service worker
-
state, a service worker's state
-
Output
-
None
-
-
    -
  1. Set worker's state to state.
  2. -
  3. Let workerObjects be an array containing all the {{ServiceWorker}} objects associated with worker.
  4. -
  5. 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" -

        The service worker in this state is considered an installing worker. During this state, event.waitUntil(f) 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" -

        The service worker in this state is considered a waiting worker.

        - -
        activating
        -
        "activating" -

        The service worker in this state is considered an active worker. During this state, event.waitUntil(f) 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" -

        The service worker in this state is considered an active worker ready to handle functional events.

        - -
        redundant
        -
        "redundant" -

        A new service worker is replacing the current service worker, or the current service worker is being discarded due to an install failure.

        -
        -
      2. -
      3. Fire an event named statechange at workerObject.
      4. -
      -
    2. -
    -

    The task must use workerObject's relevant settings object's responsible event loop and the DOM manipulation task source.

    -
  6. -
-
- -
-

Notify Controller Change

- -
-
Input
-
client, a service worker client
-
Output
-
None
-
-
    -
  1. Assert: client is not null.
  2. -
  3. If client is a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object client is associated with.
  4. -
-

The task must use client's responsible event loop and the DOM manipulation task source.

-
- -
-

Match Service Worker Registration

- -
-
Input
-
clientURL, a URL
-
Output
-
registration, a service worker registration
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let clientURLString be serialized clientURL.
  4. -
  5. Let matchingScope be the empty string.
  6. -
  7. Set matchingScope to the longest \[[key]] in scope to registration map which the value of clientURLString starts with, if it exists. -

    The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix").

    -
  8. -
  9. Let parsedMatchingScope be null.
  10. -
  11. If matchingScope is not the empty string, set parsedMatchingScope to the result of parsing matchingScope.
  12. -
  13. Let registration be the result of running Get Registration algorithm passing parsedMatchingScope as the argument.
  14. -
  15. If registration is not null and registration's uninstalling flag is set, return null.
  16. -
  17. Return registration.
  18. -
-
- -
-

Get Registration

- -
-
Input
-
scope, a URL
-
Output
-
registration, a service worker registration
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let scopeString be the empty string.
  4. -
  5. If scope is not null, set scopeString to serialized scope with the exclude fragment flag set.
  6. -
  7. Let registration be null.
  8. -
  9. For each Record {\[[key]], \[[value]]} entry of its scope to registration map: -
      -
    1. If scopeString matches entry.\[[key]], set registration to entry.\[[value]].
    2. -
    -
  10. -
  11. Return registration.
  12. -
-
- -
-

Get Newest Worker

- -
-
Input
-
registration, a service worker registration
-
Output
-
worker, a service worker
-
-
    -
  1. Run the following steps atomically.
  2. -
  3. Let newestWorker be null.
  4. -
  5. If registration's installing worker is not null, set newestWorker to registration's installing worker.
  6. -
  7. Else if registration's waiting worker is not null, set newestWorker to registration's waiting worker.
  8. -
  9. Else if registration's active worker is not null, set newestWorker to registration's active worker.
  10. -
  11. Return newestWorker.
  12. -
-
- -
-

Create Client

- -
-
Input
-
client, a service worker client
-
Output
-
clientObject, a {{Client}} object
-
-
    -
  1. Let clientObject be a new {{Client}} object.
  2. -
  3. Set clientObject's service worker client to client.
  4. -
  5. Set clientObject's reserved state to true if client's execution ready flag is unset, and false otherwise.
  6. -
  7. Return clientObject.
  8. -
-
- -
-

Create Window Client

- -
-
Input
-
client, a service worker client
-
visibilityState, a string
-
focusState, a boolean
-
ancestorOrigins, an array
-
Output
-
windowClient, a {{WindowClient}} object
-
-
    -
  1. Let windowClient be a new {{WindowClient}} object.
  2. -
  3. Set windowClient's service worker client to client.
  4. -
  5. Set windowClient's visibility state to visibilityState.
  6. -
  7. Set windowClient's focus state to focusState.
  8. -
  9. Set windowClient's ancestor origins array to ancestorOrigins.
  10. -
  11. Return windowClient.
  12. -
-
- -
-

Query Cache

- -
-
Input
-
request, a {{Request}} object
-
options, a {{CacheQueryOptions}} object, optional
-
targetStorage, an array that has [{{Request}}, {{Response}}] pairs as its elements, optional
-
Output
-
resultArray, an array that has [{{Request}}, {{Response}}] pairs as its elements
-
-
    -
  1. Let requestArray be an empty array.
  2. -
  3. Let responseArray be an empty array.
  4. -
  5. Let resultArray be an empty array.
  6. -
  7. If options.{{CacheQueryOptions/ignoreMethod}} is false and request.method is not `GET`, return resultArray.
  8. -
  9. Let cachedURL and requestURL be null.
  10. -
  11. If the optional argument targetStorage is omitted, then: -
      -
    1. For each fetching record entry of its request to response map, in key insertion order: -
        -
      1. Set cachedURL to entry.\[[key]]'s associated request's url.
      2. -
      3. Set requestURL to request's associated request's url.
      4. -
      5. If options.ignoreSearch is true, then: -
          -
        1. Set cachedURL's query to the empty string.
        2. -
        3. Set requestURL's query to the empty string.
        4. -
        -
      6. -
      7. If cachedURL equals requestURL with the exclude fragments flag set, then: -
          -
        1. Add a copy of entry.\[[key]] to requestArray.
        2. -
        3. Add a copy of entry.\[[value]] to responseArray.
        4. -
        -
      8. -
      -
    2. -
    -
  12. -
  13. Else: -
      -
    1. For each record in targetStorage: -
        -
      1. Set cachedURL to record[0]'s associated request's url.
      2. -
      3. Set requestURL to request's associated request's url.
      4. -
      5. If options.{{CacheQueryOptions/ignoreSearch}} is true, then: -
          -
        1. Set cachedURL's query to the empty string.
        2. -
        3. Set requestURL's query to the empty string.
        4. -
        -
      6. -
      7. If cachedURL equals requestURL with the exclude fragments flag set, then: -
          -
        1. Add record[0] to requestArray.
        2. -
        3. Add record[1] to responseArray.
        4. -
        -
      8. -
      -
    2. -
    -
  14. -
  15. For each cachedResponse in responseArray with the index index: -
      -
    1. Let cachedRequest be the indexth element in requestArray.
    2. -
    3. If cachedResponse's response's header list contains no header named `Vary`, or options.{{CacheQueryOptions/ignoreVary}} is true, then: -
        -
      1. Add an array [cachedRequest, cachedResponse] to resultArray.
      2. -
      3. Continue to the next iteration of the loop.
      4. -
      -
    4. -
    5. Let varyHeaders be the array containing the elements corresponding to the field-values of the Vary header.
    6. -
    7. Let matchFailed be false.
    8. -
    9. For each f in varyHeaders: -
        -
      1. If f matches "*", or the result of running cachedRequest.{{Request/headers}} object's {{Headers/get(name)}} method with f as the argument does not match the result of running request.{{Request/headers}} object's {{Headers/get(name)}} method with f as the argument, then: -
          -
        1. Set matchFailed to true.
        2. -
        3. Break the loop.
        4. -
        -
      2. -
      -
    10. -
    11. If matchFailed is false, add an array [cachedRequest, cachedResponse] to resultArray.
    12. -
    -
  16. -
  17. Return resultArray.
  18. -
-
- -
-

Batch Cache Operations

- -
-
Input
-
operations, an array of {{CacheBatchOperation}} dictionary objects
-
Output
-
promise, a promise resolves with an array of {{Response}} objects.
-
-
    -
  1. Let p be a promise resolved with no value.
  2. -
  3. Return the result of transforming p with a fulfillment handler that performs the following substeps in parallel: -
      -
    1. Let itemsCopy be a new request to response map that is a copy of its context object's request to response map.
    2. -
    3. Let addedRecords be an empty array.
    4. -
    5. Try running the following substeps atomically: -
        -
      1. Let resultArray be an empty array.
      2. -
      3. For each operation in operations with the index index: -
          -
        1. If operation.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError.
        2. -
        3. If operation.{{CacheBatchOperation/type}} matches "delete" and operation.{{CacheBatchOperation/response}} is not null, throw a TypeError.
        4. -
        5. If the result of running Query Cache algorithm passing operation.{{CacheBatchOperation/request}}, operation.{{CacheBatchOperation/options}}, and addedRecords as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception.
        6. -
        7. Let requestResponseArray be the result of running Query Cache algorithm passing operation.{{CacheBatchOperation/request}} and operation.{{CacheBatchOperation/options}} as the arguments.
        8. -
        9. For each requestResponse in requestResponseArray: -
            -
          1. If operation.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map.
          2. -
          -
        10. -
        11. If operation.{{CacheBatchOperation/type}} matches "put", then: -
            -
          1. If operation.{{CacheBatchOperation/response}} is null, throw a TypeError.
          2. -
          3. Let r be operation.{{CacheBatchOperation/request}}'s associated request.
          4. -
          5. If r's url's scheme is not one of "http" and "https", throw a TypeError.
          6. -
          7. If r's method is not `GET`, throw a TypeError.
          8. -
          9. If operation.{{CacheBatchOperation/options}} is not null, throw a TypeError.
          10. -
          11. Set requestResponseArray to the result of running Query Cache algorithm passing operation.{{CacheBatchOperation/request}}.
          12. -
          13. If requestResponseArray is not an empty array, then: -
              -
            1. Let requestResponse be requestResponseArray[0].
            2. -
            3. Let fetchingRecord be the corresponding fetching record for requestResponse[0] and requestResponse[1] in request to response map.
            4. -
            5. Set fetchingRecord.\[[key]] to operation.{{CacheBatchOperation/request}} and fetchingRecord.\[[value]] to operation.{{CacheBatchOperation/response}}.
            6. -
            -
          14. -
          15. Else: -
              -
            1. Set a newly-created fetching record {\[[key]]: operation.{{CacheBatchOperation/request}}, \[[value]]: operation.{{CacheBatchOperation/response}}} to request to response map.
            2. -
            -

            The cache commit is allowed as long as the response's headers are available.

            -
          16. -
          17. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception.
          18. -
          19. Add an array [operation.request, operation.response] to addedRecords.
          20. -
          -
        12. -
        13. Add operation.response to resultArray.
        14. -
        -
      4. -
      5. Return resultArray.
      6. -
      -
    6. -
    7. And then, if an exception was thrown, then: -
        -
      1. Set the context object's request to response map to itemsCopy.
      2. -
      3. Throw the exception
      4. -
      -
    8. -
    -
  4. -
+ The following definitions are the user agent's internal data structures used throughout the specification. + + A scope to registration map is an ordered map where the keys are [=service worker registration/scope urls=] and the values are [=/service worker registrations=]. + + A job is an abstraction of one of register, update, and unregister request for a [=/service worker registration=]. + +
+ A job has a job type, which is one of *register*, *update*, and *unregister*. + + A job has a scope url (a [=/URL=]). + + A job has a script url (a [=/URL=]). + + A job has a worker type ("classic" or "module"). + + A job has a client (a [=/service worker client=]). It is initially null. + + A job has a job promise (a promise). It is initially null. + + A job has a list of equivalent jobs (a list of jobs). It is initially the empty list. + + A job has a force bypass cache flag It is initially unset. +
+ + + Two jobs are equivalent when their job type is the same and: + + * For *register* and *update* jobs, both their [=service worker registration/scope url=] and the [=service worker/script url=] are the same. + * For *unregister* jobs, their [=service worker registration/scope url=] is the same. + + A job queue is a thread safe queue used to synchronize the set of concurrent jobs. The job queue contains jobs as its elements. The job queue *should* satisfy the general properties of FIFO queue. A user agent *must* maintain a separate job queue for each [=/service worker registration=] keyed by its [=service worker registration/scope url=]. A job queue is initially empty. Unless stated otherwise, the job queue referenced from the algorithm steps is a job queue for the job's [=service worker registration/scope url=]. + +
+

Create Job

+ + : Input + :: |jobType|, a job type + :: |scopeURL|, a [=/URL=] + :: |scriptURL|, a [=/URL=] + :: |promise|, a promise + :: |client|, a [=/service worker client=] + : Output + :: |job|, a job + + 1. Let |job| be a new job. + 1. Set |job|'s [=job/job type=] to |jobType|. + 1. Set |job|'s [=job/scope url=] to |scopeURL|. + 1. Set |job|'s [=job/script url=] to |scriptURL|. + 1. Set |job|'s [=job/job promise=] to |promise|. + 1. Set |job|'s [=job/client=] to |client|. + 1. Return |job|. +
+ +
+

Schedule Job

+ + : Input + :: |job|, a job + : Output + :: none + + 1. If the job queue is empty, then: + 1. Push |job| to the job queue and invoke Run Job. + 1. Else: + 1. Let |lastJob| be the element at the back of the job queue. + 1. If |job| is equivalent to |lastJob| and |lastJob|'s [=job/job promise=] has not settled, append |job| to |lastJob|'s list of equivalent jobs. + 1. Else, push |job| to the job queue. +
+ +
+

Run Job

+ + : Input + :: none + : Output + :: none + + 1. Assert: the job queue is not empty. + 1. Queue a task to run these steps: + 1. Let |job| be the element in the front of the job queue. + 1. If |job|'s job type is *register*, run Register with |job| in parallel. + 1. Else if |job|'s job type is *update*, run Update with |job| in parallel. + + Note: For a register job and an update job, the user agent delays queuing a task for running the job until after the document initiated the job has been dispatched {{Document/DOMContentLoaded}} event. + + 1. Else if |job|'s job type is *unregister*, run Unregister with |job| in parallel. +
+ +
+

Finish Job

+ + : Input + :: |job|, a job + : Output + :: none + + 1. Assert: the top element in the job queue is |job|. + 1. Pop the top element from the job queue. + 1. If the job queue is not empty, invoke Run Job with the top element of the job queue. +
+ +
+

Resolve Job Promise

+ + : Input + :: |job|, a job + :: |value|, any + : Output + :: none + + 1. If |job|'s [=job/client=] is not null, queue a task to resolve |job|'s [=job/job promise=] with |value| on |job|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source. + 1. For each |equivalentJob| in |job|'s list of equivalent jobs: + 1. If |equivalentJob|'s [=job/client=] is not null, queue a task to resolve |equivalentJob|'s [=job/job promise=] with |value| on |equivalentJob|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source. +
+ +
+

Reject Job Promise

+ + : Input + :: |job|, a job + :: |reason|, an exception + : Output + :: none + + 1. If |job|'s [=job/client=] is not null, queue a task to reject |job|'s [=job/job promise=] with |reason| on |job|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source. + 1. For each |equivalentJob| in |job|'s list of equivalent jobs: + 1. If |equivalentJob|'s [=job/client=] is not null, queue a task to reject |equivalentJob|'s [=job/job promise=] with |reason| on |equivalentJob|'s [=job/client=]'s responsible event loop using the DOM manipulation task source as the task source. +
+ +
+

Register

+ + : Input + :: |job|, a job + : Output + :: none + + 1. If the result of running potentially trustworthy origin with the [=environment settings object/origin=] of |job|'s [=service worker/script url=] as the argument is Not Trusted, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. + 1. If the [=environment settings object/origin=] of |job|'s [=service worker/script url=] is not |job|'s [=job/client=]'s [=environment settings object/origin=], then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. + 1. If the [=environment settings object/origin=] of |job|'s [=service worker registration/scope url=] is not |job|'s [=job/client=]'s [=environment settings object/origin=], then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 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 [=service worker registration/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 and |job|'s [=service worker/script url=] [=url/equals=] |newestWorker|'s [=service worker/script url=] with the *exclude fragments flag* set, then: + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Invoke Finish Job with |job| and abort these steps. + 1. Else: + 1. Invoke Set Registration algorithm passing |job|'s [=service worker registration/scope url=] as its argument. + 1. Invoke Update algorithm passing |job| as the argument. +
+ +
+

Update

+ + : Input + :: |job|, a job + : Output + :: none + + 1. Let |registration| be the result of running the Get Registration algorithm passing |job|'s [=service worker registration/scope url=] as the argument. + 1. If |registration| is null or |registration|'s uninstalling flag is set, then: + 1. Invoke Reject Job Promise with |job| and a 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. + 1. If |job|'s job type is *update*, and |newestWorker|'s [=service worker/script url=] does not [=url/equal=] |job|'s [=service worker/script url=] with the *exclude fragments flag* set, then: + 1. Invoke Reject Job Promise with |job| and a TypeError. + 1. Invoke Finish Job with |job| and abort these steps. + 1. Let |httpsState| be "none". + 1. Let |referrerPolicy| be the empty string. + 1. Switching on |job|'s worker type, run these substeps with the following options: + + : "classic" + :: Fetch a classic worker script given |job|’s serialized [=service worker/script url=], |job|’s [=job/client=], "serviceworker", and the to-be-created environment settings object for this service worker. + : "module" + :: Fetch a module worker script graph given |job|’s serialized [=service worker/script url=], |job|’s [=job/client=], "serviceworker", "omit", and the to-be-created environment settings object for this service worker. + + To [=fetching scripts/perform the fetch=] given |request|, run the following steps if the [=fetching scripts/is top-level=] flag is set: + + 1. Append \`Service-Worker\`/\`script\` to |request|'s [=request/header list=]. + + Note: See the definition of the Service-Worker header in Appendix B: Extended HTTP headers. + + 1. Set |request|'s skip-service-worker flag and |request|'s [=request/redirect mode=] to "error". + 1. If |newestWorker| is not null and |registration|'s last update check time is not null, then: + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, or *force bypass cache flag* is set, set |request|'s [=request/cache mode=] to "reload". + + Note: Even if the cache mode is not set to "reload", the user agent obeys Cache-Control header's max-age value in the network layer to determine if it should bypass the browser cache. + + 1. [=/Fetch=] |request|, and asynchronously wait to run the remaining steps as part of fetch's process response for the [=/response=] |response|. + 1. Extract a MIME type from the |response|'s [=response/header list=]. If this MIME type (ignoring parameters) is not one of text/javascript, application/x-javascript, and application/javascript, then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + 1. Let |serviceWorkerAllowed| be the result of [=header/parse a header value|parsing=] \`Service-Worker-Allowed\` in |response|'s [=response/header list=]. + + Note: See the definition of the Service-Worker-Allowed header in Appendix B: Extended HTTP headers. + + 1. Set |httpsState| to |response|'s [=response/HTTPS state=]. + 1. Set |referrerPolicy| to the result of parse a referrer policy from a Referrer-Policy header of |response|. + 1. If |serviceWorkerAllowed| is failure, then: + 1. Asynchronously complete these steps with a network error. + 1. Let |scopeURL| be |registration|'s [=service worker registration/scope url=]. + 1. Let |maxScopeString| be null. + 1. If |serviceWorkerAllowed| is null, then: + 1. Set |maxScopeString| to "/" concatenated with the strings, except the last string that denotes the script's file name, in |job|'s [=service worker/script url=]'s [=url/path=] (including empty strings), separated from each other by "/". + 1. Else: + 1. Let |maxScope| be the result of parsing |serviceWorkerAllowed| with |job|'s [=service worker/script url=]. + 1. Set |maxScopeString| to "/" concatenated with the strings in |maxScope|'s [=url/path=] (including empty strings), separated from each other by "/". + 1. Let |scopeString| be "/" concatenated with the strings in |scopeURL|'s [=url/path=] (including empty strings), separated from each other by "/". + 1. If |scopeString| starts with |maxScopeString|, do nothing. + 1. Else: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Asynchronously complete these steps with a network error. + 1. If |response|'s cache state is not "local", set |registration|'s last update check time to the current time. + + Issue: The response's cache state concept had been removed from fetch. The fetch issue #376 tracks the request to restore the concept or add some similar way to check this state. + + 1. Return true. + + If the algorithm asynchronously completes with null, then: + + 1. Invoke Reject Job Promise with |job| and a TypeError. + + Note: This will do nothing if Reject Job Promise was previously invoked with a "{{SecurityError}}" exception. + + 1. If |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. + + Else, continue the rest of these steps after the algorithm's asynchronous completion, with |script| being the asynchronous completion value. + + 1. If |newestWorker| is not null, |newestWorker|'s [=service worker/script url=] [=url/equals=] |job|'s [=service worker/script url=] with the *exclude fragments flag* set, and |script| is a byte-for-byte match with |newestWorker|'s script resource, then: + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |registration|. + 1. Invoke Finish Job with |job| and abort these steps. + 1. Else: + 1. Let |worker| be a new [=/service worker=]. + 1. Generate a unique opaque string and set |worker|'s id to the value. + 1. Set |worker|'s [=service worker/script url=] to |job|'s [=service worker/script url=], |worker|'s script resource to |script|, and |worker|'s type to |job|'s worker type. + 1. Set |worker|'s script resource's HTTPS state to |httpsState|. + 1. Set |worker|'s script resource's [=script resource/referrer policy=] to |referrerPolicy|. + 1. Invoke Run Service Worker algorithm with |worker| as the argument. + 1. If an uncaught runtime script error occurs during the above step, then: + 1. Invoke Reject Job Promise with |job| and a TypeError. + 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. Invoke Install algorithm with |job|, |worker|, and |registration| as its arguments. +
+ +
+

Soft Update

+ + The user agent *may* call this as often as it likes to check for updates. + + : Input + :: |registration|, a [=/service worker registration=] + :: *force bypass cache flag*, an optional flag unset by default + + Note: Implementers may use the *force bypass cache flag* to aid debugging (e.g. invocations from developer tools), and other specifications that extend service workers may also use the flag on their own needs. + + : Output + :: None + + 1. Let |newestWorker| be the result of running Get Newest Worker algorithm passing |registration| as its argument. + 1. If |newestWorker| is null, abort these steps. + 1. Let |job| be the result of running Create Job with *update*, |registration|'s [=service worker registration/scope url=], |newestWorker|'s [=service worker/script url=], null, and null. + 1. Set |job|'s worker type to |newestWorker|'s [=service worker/type=]. + 1. Set |job|'s force bypass cache flag if its *force bypass cache flag* is set. + 1. Invoke Schedule Job with |job|. +
+ +
+

Install

+ + : Input + :: |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. Let |redundantWorker| be null. + 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. Assert: |job|'s [=job/job promise=] is not null. + 1. Invoke Resolve Job Promise with |job| and the {{ServiceWorkerRegistration}} object which represents |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 |installingWorker| be |registration|'s installing worker. + 1. Invoke Run Service Worker algorithm with |installingWorker| as the argument. + 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. Invoke [=Extend Service Worker Lifetime=] with |e|. + 1. *WaitForAsynchronousExtensions*: Run the following substeps in parallel: + 1. Wait until |e|'s extensions allowed flag is unset. + 1. If 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. + + 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. Set |redundantWorker| to |registration|'s installing worker. + 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 |newestWorker| is null, invoke Clear Registration algorithm passing |registration| as its argument. + 1. Invoke Finish Job with |job| and abort these steps. + 1. Set |registration|'s installing worker's imported scripts updated flag. + 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. If |registration|'s waiting worker's skip waiting flag is set, then: + 1. Run Activate algorithm passing |registration| as the argument. + 1. Invoke Finish Job with |job| and abort these steps. + 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 |waitingWorker| is not null and |waitingWorker|'s skip waiting flag is not set, invoke Activate algorithm with |registration| as its argument. +
+ +
+

Activate

+ + : Input + :: |registration|, a [=/service worker registration=] + : Output + :: None + + 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. 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. + + 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. If |redundantWorker| is not null, run the Update Worker State algorithm passing |redundantWorker| and *redundant* as the arguments. + 1. For each [=/service worker client=] |client| whose creation URL matches |registration|'s [=service worker registration/scope url=]: + 1. If |client| is a window client, unassociate |client|'s responsible document from its application cache, if it has one. + 1. Else if |client| is a shared worker client, unassociate |client|'s [=environment settings object/global object=] from its application cache, if it has one. + + Note: Resources will now use the service worker registration instead of the existing application cache. + + 1. For each [=/service worker client=] |client| who is using |registration|: + 1. Set |client|'s active worker to |registration|'s active worker. + 1. Invoke Notify Controller Change algorithm with |client| as the argument. + 1. Let |activeWorker| be |registration|'s active worker. + 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 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 {{activate!!event}}. + 1. Dispatch |e| at |activeWorker|'s [=service worker/global object=]. + 1. Invoke [=Extend Service Worker Lifetime=] with |e|. + 1. *WaitForAsynchronousExtensions*: Wait, in parallel, until |e|'s extensions allowed flag is unset. + 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. +
+ +
+

Run Service Worker

+ + : Input + :: |serviceWorker|, a [=/service worker=] + : Output + :: None + + 1. Let |script| be |serviceWorker|'s [=service worker/script resource=]. + 1. Assert: |script| is not null. + 1. If |serviceWorker| is already running, abort these steps. + 1. Create a separate parallel execution environment (i.e. a separate thread or process or equivalent construct), and run the rest of these steps in that context. + 1. Call the JavaScript [=InitializeHostDefinedRealm|InitializeHostDefinedRealm()=] abstract operation with the following customizations: + * For the global object, create a new {{ServiceWorkerGlobalScope}} object. Let |workerGlobalScope| be the created object. + * Let |realmExecutionContext| be the created [=execution context|JavaScript execution context=]. + 1. Set |serviceWorker|'s [=service worker/global object=] to |workerGlobalScope|. + 1. Let |workerEventLoop| be a newly created event loop. + 1. Let |settingsObject| be a new environment settings object whose algorithms are defined as follows: + + : The [=environment settings object/realm execution context=] + :: Return |realmExecutionContext|. + : The [=environment settings object/global object=] + :: Return |workerGlobalScope|. + : The responsible event loop + :: Return |workerEventLoop|. + : The [=environment settings object/referrer policy=] + :: Return |workerGlobalScope|'s [=WorkerGlobalScope/referrer policy=]. + : The API URL character encoding + :: Return UTF-8. + : The API base URL + :: Return |serviceWorker|'s [=service worker/script url=]. + : The [=environment settings object/origin=] + :: Return its registering [=/service worker client=]'s [=environment settings object/origin=]. + : The creation URL + :: Return |workerGlobalScope|'s [=WorkerGlobalScope/url=]. + : The [=environment settings object/HTTPS state=] + :: Return |workerGlobalScope|'s [=WorkerGlobalScope/HTTPS state=]. + + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/url=] to |serviceWorker|'s [=service worker/script url=]. + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/HTTPS state=] to |serviceWorker|'s script resource's HTTPS state. + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/referrer policy=] to |serviceWorker|'s script resource's [=script resource/referrer policy=]. + 1. Set |workerGlobalScope|'s [=WorkerGlobalScope/type=] to |serviceWorker|'s type. + 1. Create a new {{WorkerLocation}} object and associate it with |workerGlobalScope|. + 1. If |serviceWorker| is an active worker, and there are any tasks queued in |serviceWorker|'s containing service worker registration's [=service worker registration/task queues=], queue them to |serviceWorker|'s event loop's [=/task queues=] in the same order using their original task sources. + 1. If |script| is a classic script, then run the classic script |script|. Otherwise, it is a module script; run the module script |script|. + + Note: In addition to the usual possibilities of returning a value or failing due to an exception, this could be prematurely aborted by the kill a worker or terminate a worker algorithms. + + 1. If |script|'s has ever been evaluated flag is unset, then: + 1. Set |workerGlobalScope|'s associated [=ServiceWorkerGlobalScope/service worker=]'s set of event types to handle to the set of event types created from |settingsObject|'s [=environment settings object/global object=]'s associated list of event listeners' event types. + + Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle is set to an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script. + + 1. Set |script|'s has ever been evaluated flag. + 1. Run the responsible event loop specified by |settingsObject| until it is destroyed. + 1. Empty |workerGlobalScope|'s list of active timers. +
+ +
+

Terminate Service Worker

+ + : Input + :: |serviceWorker|, a [=/service worker=] + : Output + :: None + + 1. If |serviceWorker| is not running, abort these steps. + 1. Let |serviceWorkerGlobalScope| be |serviceWorker|'s [=service worker/global object=]. + 1. Set |serviceWorkerGlobalScope|'s closing flag to true. + 1. If there are any tasks, whose task source is either the handle fetch task source or the handle functional event task source, queued in |serviceWorkerGlobalScope|'s event loop's [=/task queues=], queue them to |serviceWorker|'s containing service worker registration's corresponding [=service worker registration/task queues=] in the same order using their original task sources, and discard all the tasks (including tasks whose task source is neither the handle fetch task source nor the handle functional event task source) from |serviceWorkerGlobalScope|'s event loop's [=/task queues=] without processing them. + + Note: This effectively means that the fetch events and the other functional events such as push events are backed up by the registration's task queues while the other tasks including message events are discarded. + + 1. Abort the script currently running in |serviceWorker|. +
+ +
+

Extend Service Worker Lifetime

+ + : Input + :: |event|, an {{ExtendableEvent}} object + : Output + :: None + + 1. If |event|'s extend lifetime promises is empty, unset |event|'s extensions allowed flag and abort these steps. + 1. Let |extendLifetimePromises| be an empty array. + 1. Run the following substeps in parallel: + 1. *SetupPromiseArray*: Set |extendLifetimePromises| to a copy of |event|'s extend lifetime promises. + 1. Wait until all the promises in |extendLifetimePromises| settle. + 1. If the length of |extendLifetimePromises| does not equal the length of |event|'s extend lifetime promises, jump to the step labeled *SetupPromiseArray*. + 1. Unset |event|'s extensions allowed flag. + + The user agent *should not* terminate the [=/service worker=] associated with |event|'s relevant settings object's [=environment settings object/global object=] until |event|'s extensions allowed flag is unset. However, the user agent *may* impose a time limit to this lifetime extension. +
+ +
+

Handle Fetch

+ + The Handle Fetch algorithm is the entry point for the [=/fetch=] handling handed to the [=/service worker=] context. + + : Input + :: |request|, a [=/request=] + : Output + :: |response|, a [=/response=] + + 1. Let |handleFetchFailed| be false. + 1. Let |respondWithEntered| be false. + 1. Let |eventCanceled| be false. + 1. Let |r| be a new {{Request}} object associated with |request|. + 1. Let |headersObject| be |r|'s {{Request/headers}} attribute value. + 1. Set |headersObject|'s [=Headers/guard=] to *immutable*. + 1. Let |response| be null. + 1. Let |registration| be null. + 1. Let |client| be |request|'s [=request/client=]. + 1. Let |reservedClient| be |request|'s [=request/reserved client=]. + 1. Assert: |request|'s [=request/destination=] is not "serviceworker". + 1. If |request| is a potential-navigation-or-subresource request, then: + 1. Return null. + 1. Else if |request| is a non-subresource request, then: + + Note: If the non-subresource request is under the scope of a service worker registration, application cache is completely bypassed regardless of whether the non-subresource request uses the service worker registration. + + 1. If |reservedClient| is not null and is an environment settings object, then: + 1. If |reservedClient| is not a secure context, return null. + 1. Else: + 1. If |request|'s [=request/url=] is not a potentially trustworthy URL, return null. + 1. If |request| is a navigation request and the navigation triggering it was initiated with a shift+reload or equivalent, return null. + 1. Set |registration| to the result of running Match Service Worker Registration algorithm passing |request|'s [=request/url=] as the argument. + 1. If |registration| is null or |registration|'s active worker is null, return null. + 1. If |request|'s [=request/destination=] is not {{RequestDestination/"report"}}, set |reservedClient|'s active service worker to |registration|'s active worker. + + Note: From this point, the [=/service worker client=] starts to use its active service worker's containing service worker registration. + + 1. Else if |request| is a subresource request, then: + 1. If |client|'s active service worker is non-null, set |registration| to |client|'s active service worker's containing service worker registration. + 1. Else, return null. + 1. Let |activeWorker| be |registration|'s active worker. + 1. If |activeWorker|'s set of event types to handle does not contain fetch, then: + 1. Return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + + Note: To avoid unnecessary delays, the Handle Fetch enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. + + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. + 1. Invoke Run Service Worker algorithm with |activeWorker| as the argument. + 1. Queue a task |task| to run the following substeps: + 1. Let |e| be the result of creating an event with {{FetchEvent}}. + 1. Initialize |e|’s {{Event/type}} attribute to {{fetch!!event}}. + 1. Initialize |e|’s {{Event/cancelable}} attribute to true. + 1. Initialize |e|’s {{FetchEvent/request}} attribute to |r|. + 1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s [=environment/id=]. + 1. If |request| is a non-subresource request and |request|'s [=request/destination=] is not {{RequestDestination/"report"}}, initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s [=environment/id=], and to the empty string otherwise. + 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 [=Extend Service Worker Lifetime=] with |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. + 1. If |e|'s [=FetchEvent/respond-with error flag=] is set, set |handleFetchFailed| to true. + 1. Else, set |response| to |e|'s [=FetchEvent/potential response=]. + 1. If |e|'s canceled flag is set, set |eventCanceled| to true. + + If |task| is discarded or the script has been aborted by the termination of |activeWorker|, set |handleFetchFailed| to true. + + The |task| *must* use |activeWorker|'s event loop and the handle fetch task source. + + 1. Wait for |task| to have executed or been discarded. + 1. If |respondWithEntered| is false, then: + 1. If |eventCanceled| is true, return a network error and continue running these steps in parallel. + 1. Else, return null and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + 1. If |handleFetchFailed| is true, then: + 1. Return a network error and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Else: + 1. Return |response| and continue running these steps in parallel. + 1. If |request| is a non-subresource request, or |request| is a subresource request and the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. +
+ +
+

Handle Functional Event

+ + : Input + :: |event|, an {{ExtendableEvent}} object + :: |registration|, a [=/service worker registration=] + :: |callbackSteps|, an algorithm + : 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 contain |event|'s {{Event/type}}, then: + 1. Return and continue running these steps in parallel. + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. + 1. Abort these steps. + + Note: To avoid unnecessary delays, the Handle Functional Event enforces early return when no event listeners have been deterministically added in the service worker's global during the very first script execution. + + 1. If |activeWorker|'s state is *activating*, wait for |activeWorker|'s state to become *activated*. + 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 [=Extend Service Worker Lifetime=] with |event|. + + The |task| *must* use |activeWorker|'s event loop and the handle functional event task source. + + 1. Wait for |task| to have executed or been discarded. + 1. If the time difference in seconds calculated by the current time minus |registration|'s last update check time is greater than 86400, invoke Soft Update algorithm with |registration|. +
+ +
+

Handle Service Worker Client Unload

+ + The user agent *must* run these steps when a [=/service worker client=] unloads by unloading, being killed, or terminating. + + : Input + :: |client|, a [=/service worker client=] + : Output + :: None + + 1. Run the following steps atomically. + 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 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. +
+ +
+

Handle User Agent Shutdown

+ + : Input + :: None + : Output + :: None + + 1. [=map/For each=] scope → |registration| of scope to registration map: + 1. If |registration|'s installing worker |installingWorker| is not null, then: + 1. If the result of running Get Newest Worker with |registration| is |installingWorker|, invoke Clear Registration with |registration| and continue to the next iteration of the loop. + 1. Else, set |registration|'s installing worker to null. + 1. If |registration|'s waiting worker is not null, run the following substep in parallel: + 1. Invoke Activate with |registration|. +
+ +
+

Unregister

+ + : Input + :: |job|, a job + : Output + :: none + + 1. If the [=environment settings object/origin=] of |job|'s [=service worker registration/scope url=] is not |job|'s [=job/client=]'s [=environment settings object/origin=], then: + 1. Invoke Reject Job Promise with |job| and a "{{SecurityError}}" exception. + 1. Invoke Finish Job with |job| and abort these steps. + 1. Let |registration| be the result of running Get Registration algorithm passing |job|'s [=service worker registration/scope url=] as the argument. + 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. Invoke Resolve Job Promise with |job| and true. + 1. If no [=/service worker client=] is using |registration|, invoke Clear Registration algorithm passing |registration| as its argument. + + Note: When the registration is being used for a client, the deletion of the registration is handled by the Handle Service Worker Client Unload algorithm. + + 1. Invoke Finish Job with |job|. +
+ +
+

Set Registration

+ + : Input + :: |scope|, a [=/URL=] + : Output + :: |registration|, a [=/service worker registration=] + + 1. Run the following steps atomically. + 1. Let |scopeString| be serialized |scope| with the *exclude fragment flag* set. + 1. Let |registration| be a new [=/service worker registration=] whose [=service worker registration/scope url=] is set to |scope|. + 1. [=map/Set=] scope to registration map[|scopeString|] to |registration|. + 1. Return |registration|. +
+ +
+

Clear Registration

+ + : Input + :: |registration|, a [=/service worker registration=] + : Output + :: None + + 1. Run the following steps atomically. + 1. Let |redundantWorker| be null. + 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. + 1. [=map/Remove=] scope to registration map[|scopeString|]. +
+ +
+

Update Registration 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

+ + : Input + :: |worker|, a [=/service worker=] + :: |state|, a [=/service worker=]'s state + : 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"}} + + 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 a type of environment settings object, queue a task to fire an event named controllerchange at the {{ServiceWorkerContainer}} object |client| is [=ServiceWorkerContainer/service worker client|associated=] with. + + The task *must* use |client|'s responsible event loop and the DOM manipulation task source. +
+ +
+

Match Service Worker Registration

+ + : Input + :: |clientURL|, a [=/URL=] + : Output + :: |registration|, a [=/service worker registration=] + + 1. Run the following steps atomically. + 1. Let |clientURLString| be serialized |clientURL|. + 1. Let |matchingScope| be the empty string. + 1. Let |allScopes| be the result of [=map/get the keys|getting the keys=] from scope to registration map. + 1. Set |matchingScope| to the longest value in |allScopes| which the value of |clientURLString| starts with, if it exists. + + Note: The URL string matching in this step is prefix-based rather than path-structural (e.g. a client URL string with "/prefix-of/resource.html" will match a registration for a scope with "/prefix"). + + 1. Let |parsedMatchingScope| be null. + 1. If |matchingScope| is not the empty string, set |parsedMatchingScope| to the result of parsing |matchingScope|. + 1. Let |registration| be the result of running Get Registration algorithm passing |parsedMatchingScope| as the argument. + 1. If |registration| is not null and |registration|'s uninstalling flag is set, return null. + 1. Return |registration|. +
+ +
+

Get Registration

+ + : Input + :: |scope|, a [=/URL=] + : Output + :: |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 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|. +
+ +
+

Get Newest Worker

+ + : Input + :: |registration|, a [=/service worker registration=] + : Output + :: |newestWorker|, a [=/service worker=] + + 1. Run the following steps atomically. + 1. Let |newestWorker| be null. + 1. If |registration|'s installing worker is not null, set |newestWorker| to |registration|'s installing worker. + 1. Else if |registration|'s waiting worker is not null, set |newestWorker| to |registration|'s waiting worker. + 1. Else if |registration|'s active worker is not null, set |newestWorker| to |registration|'s active worker. + 1. Return |newestWorker|. +
+ +
+

Create Client

+ + : Input + :: |client|, a [=/service worker client=] + : Output + :: |clientObject|, a {{Client}} object + + 1. Let |clientObject| be a new {{Client}} object. + 1. Set |clientObject|'s [=Client/service worker client=] to |client|. + 1. Set |clientObject|'s [=Client/reserved state=] to true if |client|'s [=environment/execution ready flag=] is unset, and false otherwise. + 1. Return |clientObject|. +
+ +
+

Create Window Client

+ + : Input + :: |client|, a [=/service worker client=] + :: |visibilityState|, a string + :: |focusState|, a boolean + :: |ancestorOrigins|, an array + : Output + :: |windowClient|, a {{WindowClient}} object + + 1. Let |windowClient| be a new {{WindowClient}} object. + 1. Set |windowClient|'s [=Client/service worker client=] to |client|. + 1. Set |windowClient|'s visibility state to |visibilityState|. + 1. Set |windowClient|'s focus state to |focusState|. + 1. Set |windowClient|'s [=WindowClient/ancestor origins array=] to |ancestorOrigins|. + 1. Return |windowClient|. +
+ +
+

Query Cache

+ + : Input + :: |request|, a {{Request}} object + :: |options|, a {{CacheQueryOptions}} object, optional + :: |targetStorage|, an array that has [{{Request}}, {{Response}}] pairs as its elements, optional + : Output + :: |resultArray|, an array that has [{{Request}}, {{Response}}] pairs as its elements + + 1. Let |requestArray| be an empty array. + 1. Let |responseArray| be an empty array. + 1. Let |resultArray| be an empty array. + 1. If |options|.{{CacheQueryOptions/ignoreMethod}} is false and |request|.method is not \`GET\`, return |resultArray|. + 1. Let |cachedURL| and |requestURL| be null. + 1. If the optional argument |targetStorage| is omitted, then: + 1. For each fetching record |entry| of its request to response map, in key insertion order: + 1. Set |cachedURL| to |entry|.\[[key]]'s associated [=Request/request=]'s [=request/url=]. + 1. Set |requestURL| to |request|'s associated [=Request/request=]'s [=request/url=]. + 1. If |options|.ignoreSearch is true, then: + 1. Set |cachedURL|'s [=url/query=] to the empty string. + 1. Set |requestURL|'s [=url/query=] to the empty string. + 1. If |cachedURL| [=url/equals=] |requestURL| with the *exclude fragments flag* set, then: + 1. Add a copy of |entry|.\[[key]] to |requestArray|. + 1. Add a copy of |entry|.\[[value]] to |responseArray|. + 1. Else: + 1. For each |record| in |targetStorage|: + 1. Set |cachedURL| to |record|[0]'s associated [=Request/request=]'s [=request/url=]. + 1. Set |requestURL| to |request|'s associated [=Request/request=]'s [=request/url=]. + 1. If |options|.{{CacheQueryOptions/ignoreSearch}} is true, then: + 1. Set |cachedURL|'s [=url/query=] to the empty string. + 1. Set |requestURL|'s [=url/query=] to the empty string. + 1. If |cachedURL| [=url/equals=] |requestURL| with the *exclude fragments flag* set, then: + 1. Add |record|[0] to |requestArray|. + 1. Add |record|[1] to |responseArray|. + 1. For each |cachedResponse| in |responseArray| with the index |index|: + 1. Let |cachedRequest| be the |index|th element in |requestArray|. + 1. If |cachedResponse|'s [=Response/response=]'s [=response/header list=] contains no header [=header/named=] \`Vary\`, or |options|.{{CacheQueryOptions/ignoreVary}} is true, then: + 1. Add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. + 1. Continue to the next iteration of the loop. + 1. Let |varyHeaders| be the array containing the elements corresponding to the [=http/field-values=] of the Vary header. + 1. Let |matchFailed| be false. + 1. For each |f| in |varyHeaders|: + 1. If |f| matches "*", or the result of running |cachedRequest|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument does not match the result of running |request|.{{Request/headers}} object's {{Headers/get(name)}} method with |f| as the argument, then: + 1. Set |matchFailed| to true. + 1. Break the loop. + 1. If |matchFailed| is false, add an array [|cachedRequest|, |cachedResponse|] to |resultArray|. + 1. Return |resultArray|. +
+ +
+

Batch Cache Operations

+ + : Input + :: |operations|, an array of {{CacheBatchOperation}} dictionary objects + : Output + :: |promise|, a promise resolves with an array of {{Response}} objects + + 1. Let |promise| be a promise resolved with no value. + 1. Return the result of transforming |promise| with a fulfillment handler that performs the following substeps in parallel: + 1. Let |itemsCopy| be a new request to response map that is a copy of its context object's request to response map. + 1. Let |addedRecords| be an empty array. + 1. Try running the following substeps atomically: + 1. Let |resultArray| be an empty array. + 1. For each |operation| in |operations|: + 1. If |operation|.{{CacheBatchOperation/type}} matches neither "delete" nor "put", throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete" and |operation|.{{CacheBatchOperation/response}} is not null, throw a TypeError. + 1. If the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}, |operation|.{{CacheBatchOperation/options}}, and |addedRecords| as the arguments is not an empty array, throw an "{{InvalidStateError}}" exception. + 1. Let |requestResponseArray| be the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}} and |operation|.{{CacheBatchOperation/options}} as the arguments. + 1. For each |requestResponse| in |requestResponseArray|: + 1. If |operation|.{{CacheBatchOperation/type}} matches "delete", remove the corresponding fetching record from request to response map. + 1. If |operation|.{{CacheBatchOperation/type}} matches "put", then: + 1. If |operation|.{{CacheBatchOperation/response}} is null, throw a TypeError. + 1. Let |r| be |operation|.{{CacheBatchOperation/request}}'s associated [=Request/request=]. + 1. If |r|'s [=request/url=]'s [=url/scheme=] is not one of "http" and "https", throw a TypeError. + 1. If |r|'s [=request/method=] is not \`GET\`, throw a TypeError. + 1. If |operation|.{{CacheBatchOperation/options}} is not null, throw a TypeError. + 1. Set |requestResponseArray| to the result of running Query Cache algorithm passing |operation|.{{CacheBatchOperation/request}}. + 1. If |requestResponseArray| is not an empty array, then: + 1. Let |requestResponse| be |requestResponseArray|[0]. + 1. Let |fetchingRecord| be the corresponding fetching record for |requestResponse|[0] and |requestResponse|[1] in request to response map. + 1. Set |fetchingRecord|.\[[key]] to |operation|.{{CacheBatchOperation/request}} and |fetchingRecord|.\[[value]] to |operation|.{{CacheBatchOperation/response}}. + 1. Else: + 1. Set a newly-created fetching record {\[[key]]: |operation|.{{CacheBatchOperation/request}}, \[[value]]: |operation|.{{CacheBatchOperation/response}}} to request to response map. + + Note: The cache commit is allowed as long as the response's headers are available. + + 1. If the cache write operation in the previous two steps failed due to exceeding the granted quota limit, throw a "{{QuotaExceededError}}" exception. + 1. Add an array [|operation|.request, |operation|.response] to |addedRecords|. + 1. Add |operation|.response to |resultArray|. + 1. Return |resultArray|. + 1. And then, if an exception was thrown, then: + 1. Set the context object's request to response map to |itemsCopy|. + 1. Throw the exception
@@ -3727,73 +2953,69 @@ spec: rfc7231; urlPrefix: https://tools.ietf.org/html/rfc7231

Service Worker Script Request

-

An HTTP request to fetch a service worker's script resource will include the following header:

+ An HTTP request to [=/fetch=] a [=/service worker=]'s script resource will include the following header: + + : \`Service-Worker\` + :: Indicates this request is a [=/service worker=]'s script resource request. -
-
`Service-Worker`
-
Indicates this request is a service worker's script resource request. -

This header helps administrators log the requests and detect threats.

-
-
+ Note: This header helps administrators log the requests and detect threats.

Service Worker Script Response

-

An HTTP response to a service worker's script resource request can include the following header:

+ An HTTP response to a [=/service worker=]'s script resource request can include the following header: -
-
`Service-Worker-Allowed`
-
Indicates the user agent will override the path restriction, which limits the maximum allowed scope url that the script can control, to the given value. -

The value is a URL. If a relative URL is given, it is parsed against the script's URL.

-
-
+ : \`Service-Worker-Allowed\` + :: Indicates the user agent will override the path restriction, which limits the maximum allowed [=service worker registration/scope url=] that the script can control, to the given value. + + Note: The value is a URL. If a relative URL is given, it is parsed against the script's URL.
Default scope: -
-// Maximum allowed scope defaults to the path the script sits in
-// "/js" in this example
-navigator.serviceWorker.register("/js/sw.js").then(function() {
-  console.log("Install succeeded with the default scope '/js'.");
-});
+      
+        // Maximum allowed scope defaults to the path the script sits in
+        // "/js" in this example
+        navigator.serviceWorker.register("/js/sw.js").then(() => {
+          console.log("Install succeeded with the default scope '/js'.");
+        });
       
Upper path without Service-Worker-Allowed header: -
-// Set the scope to an upper path of the script location
-// Response has no Service-Worker-Allowed header
-navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).catch(function() {
-  console.error("Install failed due to the path restriction violation.");
-});
+      
+        // Set the scope to an upper path of the script location
+        // Response has no Service-Worker-Allowed header
+        navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).catch(() => {
+          console.error("Install failed due to the path restriction violation.");
+        });
       
Upper path with Service-Worker-Allowed header: -
-// Set the scope to an upper path of the script location
-// Response included "Service-Worker-Allowed : /"
-navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).then(function() {
-  console.log("Install succeeded as the max allowed scope was overriden to '/'.");
-});
+      
+        // Set the scope to an upper path of the script location
+        // Response included "Service-Worker-Allowed : /"
+        navigator.serviceWorker.register("/js/sw.js", { scope: "/" }).then(() => {
+          console.log("Install succeeded as the max allowed scope was overriden to '/'.");
+        });
       
A path restriction voliation even with Service-Worker-Allowed header: -
-// Set the scope to an upper path of the script location
-// Response included "Service-Worker-Allowed : /foo"
-navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(function() {
-  console.error("Install failed as the scope is still out of the overriden maximum allowed scope.");
-});
+      
+        // Set the scope to an upper path of the script location
+        // Response included "Service-Worker-Allowed : /foo"
+        navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(() => {
+          console.error("Install failed as the scope is still out of the overriden maximum allowed scope.");
+        });
       
@@ -3801,28 +3023,29 @@ navigator.serviceWorker.register("/foo/bar/sw.js", { scope: "/" }).catch(functio

Syntax

-

ABNF for the values of the headers used by the service worker's script resource requests and responses:

+ ABNF for the values of the headers used by the [=/service worker=]'s script resource requests and responses:
-    Service-Worker = %x73.63.72.69.70.74 ; "script", case-sensitive
+      Service-Worker = %x73.63.72.69.70.74 ; "script", case-sensitive
     
-

The validation of the Service-Worker-Allowed header's values is done by URL parsing algorithm (in Update algorithm) instead of using ABNF.

+ Note: The validation of the Service-Worker-Allowed header's values is done by URL parsing algorithm (in Update algorithm) instead of using ABNF.

Acknowledgements

-

Deep thanks go to Andrew Betts for organizing and hosting a small workshop of like-minded individuals including: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. From the clarity of the day's discussions and the use-cases outlined there, much has become possible. Further thanks to Andrew for raising consciousness about the offline problem. His organization of EdgeConf and inclusion of Offline as a persistent topic there has created many opportunities and connections that have enabled this work to progress.

-

Anne van Kesteren has generously lent his encyclopedic knowledge of Web Platform arcana and standards development experience throughout the development of the service worker. This specification would be incomplete without his previous work in describing the real-world behavior of URLs, HTTP Fetch, Promises, and DOM. Similarly, this specification would not be possible without Ian Hickson's rigorous Web Worker spec. Much thanks to him.

+ Deep thanks go to Andrew Betts for organizing and hosting a small workshop of like-minded individuals including: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. From the clarity of the day's discussions and the use-cases outlined there, much has become possible. Further thanks to Andrew for raising consciousness about the offline problem. His organization of EdgeConf and inclusion of Offline as a persistent topic there has created many opportunities and connections that have enabled this work to progress. -

In no particular order, deep gratitude for design guidance and discussion goes to: Jungkee Song, Alec Flett, David Barrett-Kahn, Aaron Boodman, Michael Nordman, Tom Ashworth, Kinuko Yasuda, Darin Fisher, Jonas Sicking, Jesús Leganés Combarro, Mark Christian, Dave Hermann, Yehuda Katz, François Remy, Ilya Grigorik, Will Chan, Domenic Denicola, Nikhil Marathe, Yves Lafon, Adam Barth, Greg Simon, Devdatta Akhawe, Dominic Cooney, Jeffrey Yasskin, Joshua Bell, Boris Zbarsky, Matt Falkenhagen, Tobie Langel, Gavin Peters, Ben Kelly, Hiroki Nakagawa, Jake Archibald, Josh Soref, Jinho Bang and Yutaka Hirano.

+ Anne van Kesteren has generously lent his encyclopedic knowledge of Web Platform arcana and standards development experience throughout the development of the service worker. This specification would be incomplete without his previous work in describing the real-world behavior of URLs, HTTP Fetch, Promises, and DOM. Similarly, this specification would not be possible without Ian Hickson's rigorous Web Worker spec. Much thanks to him. -

Jason Weber, Chris Wilson, Paul Kinlan, Ehsan Akhgari, and Daniel Austin have provided valuable, well-timed feedback on requirements and the standardization process.

+ In no particular order, deep gratitude for design guidance and discussion goes to: Jungkee Song, Alec Flett, David Barrett-Kahn, Aaron Boodman, Michael Nordman, Tom Ashworth, Kinuko Yasuda, Darin Fisher, Jonas Sicking, Jesús Leganés Combarro, Mark Christian, Dave Hermann, Yehuda Katz, François Remy, Ilya Grigorik, Will Chan, Domenic Denicola, Nikhil Marathe, Yves Lafon, Adam Barth, Greg Simon, Devdatta Akhawe, Dominic Cooney, Jeffrey Yasskin, Joshua Bell, Boris Zbarsky, Matt Falkenhagen, Tobie Langel, Gavin Peters, Ben Kelly, Hiroki Nakagawa, Jake Archibald, Josh Soref, Jinho Bang and Yutaka Hirano. -

The authors would also like to thank Dimitri Glazkov for his scripts and formatting tools which have been essential in the production of this specification. The authors are also grateful for his considerable guidance.

+ Jason Weber, Chris Wilson, Paul Kinlan, Ehsan Akhgari, and Daniel Austin have provided valuable, well-timed feedback on requirements and the standardization process. -

Thanks also to Vivian Cromwell, Greg Simon, Alex Komoroske, Wonsuk Lee, and Seojin Kim for their considerable professional support.

-
+ The authors would also like to thank Dimitri Glazkov for his scripts and formatting tools which have been essential in the production of this specification. The authors are also grateful for his considerable guidance. + + Thanks also to Vivian Cromwell, Greg Simon, Alex Komoroske, Wonsuk Lee, and Seojin Kim for their considerable professional support. +
\ No newline at end of file
install {{ExtendableEvent}}[Lifecycle event] The service worker's containing service worker registration's installing worker changes. (See step 11.2 of the Install algorithm.)[Lifecycle event] The [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration's installing worker changes. (See step 11.2 of the Install algorithm.)
activate {{ExtendableEvent}}[Lifecycle event] The service worker's containing service worker registration's active worker changes. (See step 12.2 of the Activate algorithm.)[Lifecycle event] The [=ServiceWorkerGlobalScope/service worker=]'s containing service worker registration's active worker changes. (See step 12.2 of the Activate algorithm.)
fetch {{FetchEvent}}[Functional event] The http fetch invokes Handle Fetch with request. As a result of performing Handle Fetch, the service worker returns a response to the http fetch. The response, represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.)[Functional event] The [=/http fetch=] invokes Handle Fetch with |request|. As a result of performing Handle Fetch, the [=ServiceWorkerGlobalScope/service worker=] returns a [=/response=] to the [=/http fetch=]. The [=/response=], represented by a {{Response}} object, can be retrieved from a {{Cache}} object or directly from network using {{WindowOrWorkerGlobalScope/fetch(input, init)|self.fetch(input, init)}} method. (A custom {{Response}} object can be another option.)
message