From 1a334de5d3a2019d51f9c87570919fb38a12bc9b Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 8 Oct 2020 18:19:08 -0400 Subject: [PATCH] Move worklets into to the HTML Standard Closes https://github.com/w3c/css-houdini-drafts/issues/1000. Closes #2611. --- source | 914 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 831 insertions(+), 83 deletions(-) diff --git a/source b/source index 2529743aa6e..ebb04e0bb92 100644 --- a/source +++ b/source @@ -2639,6 +2639,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • primary interface
  • interface object
  • include
  • +
  • inherit
  • interface prototype object
  • [[Realm]] field of a platform object
  • callback context
  • @@ -3970,18 +3971,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute -
    Worklets
    - -
    -

    The following feature is defined in Worklets:

    - - -
    -
    Cooperative Scheduling of Background Tasks
    @@ -79661,12 +79650,12 @@ interface BarProp {
    1. Set settings object's id to - reservedEnvironment's id, settings - object's target browsing - context to reservedEnvironment's target browsing context, and - settings object's active - service worker to reservedEnvironment's reservedEnvironment's id, target browsing context to + reservedEnvironment's target browsing context, and active service worker to + reservedEnvironment's active service worker.

    2. @@ -88322,7 +88311,7 @@ interface ApplicationCache : EventTarget { obtaining a worker/worklet agent given outside settings, isShared, and true.

      -

      To obtain a worklet agent, given an environment settings object +

      To obtain a worklet agent, given an environment settings object outside settings, return the result of obtaining a worker/worklet agent given outside settings, false, and false.

      @@ -89204,7 +89193,7 @@ document.querySelector("button").addEventListener("click", bound);

      If global is a WorkletGlobalScope, then:

        -
      1. If global's owner +

      2. If global's owner document's relevant settings object is a secure context, then return true.

      3. @@ -89772,37 +89761,50 @@ document.querySelector("button").addEventListener("click", bound);

        To fetch a module worker script graph given a url, a fetch client settings object, a destination, a - credentials mode, and a module map settings object, run these steps. The - algorithm will asynchronously complete with either null (on failure) or a module - script (on success).

        + credentials mode, and a module map settings object, fetch a + worklet/module worker script graph given url, fetch client settings + object, destination, credentials mode, and module map settings + object, asynchronously completing with the asynchronous completion result of that + algorithm.

        + +

        To fetch a worklet script graph given a url, a fetch client settings + object, a destination, a credentials mode, a module map settings + object, and a module responses map, fetch a worklet/module worker script + graph given url, fetch client settings object, + destination, credentials mode, and module map settings object, + asynchronously completing with the asynchronous completion result of that algorithm. Use the + following custom steps to perform the fetch + given response:

          -
        1. Let options be a script fetch options whose cryptographic nonce is the empty string, integrity metadata is the empty string, - parser metadata is "not-parser-inserted", credentials mode is credentials - mode, and referrer - policy is the empty string.

          +
        2. Let requestURL be request's url.

        3. -
        4. Fetch a single module script given url, fetch client settings - object, destination, options, module map settings object, - "client", and with the top-level module fetch flag set. If the - caller of this algorithm specified custom perform - the fetch steps, pass those along as well. Wait until the algorithm asynchronously - completes with result.

        5. +
        6. If moduleResponsesMap[requestURL] is "fetching", wait in parallel until that entry's value changes, then + queue a task on the networking task source to proceed with running the + following steps.

        7. -
        8. If result is null, asynchronously complete this algorithm with null, and - return.

        9. +
        10. If moduleResponsesMap[requestURL] exists, then asynchronously complete the perform the fetch steps with + moduleResponsesMap[requestURL].

        11. -
        12. Let visited set be « url ».

        13. +
        14. Set moduleResponsesMap[requestURL] to + "fetching".

        15. -
        16. Fetch the - descendants of and link result given fetch client settings - object, destination, and visited set. When this asynchronously - completes with final result, asynchronously complete this algorithm with final - result.

        17. +
        18. +

          Fetch request. To process + response for the response response:

          + +
            +
          1. Set moduleResponsesMap[requestURL] to + response.

          2. + +
          3. Asynchronously complete the perform the + fetch steps with response.

          4. +
          +

        @@ -89814,7 +89816,7 @@ document.querySelector("button").addEventListener("click", bound);

        This diagram illustrates how these algorithms relate to the ones above, as well as to each other:

        - + fetch an external module script graph - + @@ -89856,7 +89858,7 @@ document.querySelector("button").addEventListener("click", bound); fetch an import() module script graph - + @@ -89864,7 +89866,7 @@ document.querySelector("button").addEventListener("click", bound); fetch a modulepreload module script graph - + @@ -89872,7 +89874,7 @@ document.querySelector("button").addEventListener("click", bound); fetch an inline module script graph - + @@ -89880,33 +89882,83 @@ document.querySelector("button").addEventListener("click", bound); fetch a module worker script graph - + + + + + + fetch a worklet script graph + + + - + + + + fetch a worklet/module worker script graph + + + + + fetch the descendants of and link a module script - + - + fetch the descendants of a module script - + - + internal module script graph fetching procedure - + +

        To fetch a worklet/module worker script graph given a url, a fetch + client settings object, a destination, a credentials mode, and a + module map settings object, run these steps. The algorithm will asynchronously complete + with either null (on failure) or a module script (on success).

        + +
          +
        1. Let options be a script fetch options whose cryptographic nonce is the empty string, integrity metadata is the empty string, + parser metadata is "not-parser-inserted", credentials mode is credentials + mode, and referrer + policy is the empty string.

          + +
        2. Fetch a single module script given url, fetch client settings + object, destination, options, module map settings object, + "client", and with the top-level module fetch flag set. If the + caller of this algorithm specified custom perform + the fetch steps, pass those along as well. Wait until the algorithm asynchronously + completes with result.

        3. + +
        4. If result is null, asynchronously complete this algorithm with null, and + return.

        5. + +
        6. Let visited set be « url ».

        7. + +
        8. Fetch the + descendants of and link result given fetch client settings + object, destination, and visited set. When this asynchronously + completes with final result, asynchronously complete this algorithm with final + result.

        9. +
        +

        To fetch the descendants of and link a module script module script, given a fetch client settings object, a destination, and a visited set, run these steps. The algorithm will asynchronously complete with either @@ -90642,16 +90694,18 @@ document.querySelector("button").addEventListener("click", bound); "Script error.", urlString to the empty string, line and col to 0, and errorValue to null.

        -
      4. Let notHandled be the result of firing an - event named error at target, using - ErrorEvent, with the cancelable attribute - initialized to true, the message attribute - initialized to message, the filename - attribute initialized to urlString, the lineno attribute initialized to line, the colno attribute initialized to col, and the error attribute initialized to - errorValue.

      5. +
      6. Let notHandled be true.

      7. + +
      8. If target implements EventTarget, then set notHandled + to the result of firing an event named error at target, using ErrorEvent, with the + cancelable attribute initialized to true, the message attribute initialized to message, the + filename attribute initialized to + urlString, the lineno attribute + initialized to line, the colno attribute + initialized to col, and the error attribute + initialized to errorValue.

      9. Let target no longer be in error reporting mode.

      10. @@ -100476,8 +100530,8 @@ interface SharedWorkerGlobalScope : WorkerGlobalScope { issue #207 for more details.

        -
      11. Execute the Initialize a global object's CSP list - algorithm on worker global scope and response.

      12. +
      13. Initialize a global object's CSP list given worker global scope + and response.

      14. Asynchronously complete the perform the fetch steps with response.

      15. @@ -100703,10 +100757,9 @@ interface SharedWorkerGlobalScope : WorkerGlobalScope {
        Script settings for workers
        -

        When the user agent is required to set up a worker environment settings object, - given a JavaScript execution context execution context and - environment settings object outside settings, it must run the following - steps:

        +

        To set up a worker environment settings object, given a JavaScript execution + context execution context and environment settings object + outside settings:

        1. Let inherited origin be outside settings's SharedWorkerGlobalScope : WorkerGlobalScope {

        2. Set settings object's id to a new - unique opaque string, settings object's creation URL to worker global - scope's url, settings object's top-level creation URL - to null, settings object's target browsing context to null, and - settings object's active - service worker to null.

        3. + unique opaque string, creation URL to + worker global scope's url, top-level creation URL to null, + target browsing context to + null, and active service worker + to null.

        4. If worker global scope is a DedicatedWorkerGlobalScope object, then set settings object's top-level origin to outside @@ -101404,6 +101455,695 @@ interface WorkerLocation {

        +

        Worklets

        + +

        Introduction

        + + + +

        Worklets are a piece of specification infrastructure which can be used for running scripts + independent of the main JavaScript execution environment, while not requiring any particular + implementation model.

        + +

        The worklet infrastructure specified here cannot be used directly by web developers. Instead, + other specifications build upon it to create directly-usable worklet types, specialized for + running in particular parts of the browser implementation pipeline.

        + +

        Motivations

        + + + +

        Allowing extension points to rendering, or other sensitive parts of the implementation pipeline + such as audio output, is difficult. If extension points were done with full access to the APIs + available on Window, engines would need to abandon previously-held assumptions for + what could happen in the middle of those phases. For example, during the layout phase, rendering + engines assume that no DOM will be modified.

        + +

        Additionaly, defining extension points in the Window environment would restrict + user agents to performing work in the same thread as the Window object. (Unless + implementations added complex, high-overhead infrastructure to allow thread-safe APIs, as well + as thread-joining guarantees.)

        + +

        Worklets are designed to allow extension points, while keeping guarantees that user agents + currently rely on. This is done through new global environments, based on subclasses of + WorkletGlobalScope.

        + +

        Worklets are similar to web workers. However, they:

        + +
          +
        • Are thread-agnostic. That is, they are not designed to run on a dedicated separate thread, + like each worker is. Implementations can run worklets wherever they choose (including on the main + thread).

        • + +
        • Are able to have multiple duplicate instances of the global scope created, for the purpose + of parallelism.

        • + +
        • Do not use an event-based API. Instead, classes are registered on the global scope, whose + methods are invoked by the user agent.

        • + +
        • Have a reduced API surface on the global scope.

        • + +
        • Have a lifetime for their global object which is defined by other + specifications, or is implementation-defined. They are not tied to the liftime of a + Window or Document.

        • +
        + +

        As worklets have relatively high overhead, they are best used sparingly. Due to this, a given + WorkletGlobalScope is expected to be shared between multiple separate scripts. (This + is similar to how a single Window is shared between multiple separate scripts.)

        + +

        Code idempotence

        + +

        Some specifications which use worklets are intended to allow user agents to parallelize work + over multiple threads, or to move work between threads as required. In these specifications, user + agents might invoke methods on a web-developer-provided class in an + implementation-defined order.

        + +

        As a result of this, to prevent interoperability issues, authors who register classes on such + WorkletGlobalScopes should make their code idempotent. That is, a method or set of + methods on the class should produce the same output given a particular input.

        + +

        This specification uses the following techniques in order to encourage authors to write code in + an idempotent way:

        + +
          + +
        • No reference to the global object is available (i.e., there is no counterpart to self on WorkletGlobalScope.

        • + +
        • Code is loaded as a module script, which results in the code being executed + in strict mode and with no shared this referencing the global + proxy.

        • +
        + +

        Together, these restrictions help prevent two different scripts from sharing state using + properties of the global object.

        + +

        Additionally, specifications which use worklets and intend to allow + implementation-defined behavior must obey the following:

        + +
          +
        • They must require user agents to always have at least two WorkletGlobalScope + instances per Worklet, and randomly assign a method or set of methods on a class to + a particular WorkletGlobalScope instance. These specifications may provide an + opt-out under memory constraints.

        • + +
        • These specifications must allow user agents to create and destroy instances of their + WorkletGlobalScope subclasses at any time.

        • +
        + +

        Speculative evaluation

        + +

        Some specifications which use worklets can invoke methods on a web-developer-provided class + based on the state of the user agent. To increase concurrency between threads, a user agent may + invoke a method speculatively, based on potential future states.

        + +

        In these specifications, user agents might invoke such methods at any time, and with any + arguments, not just ones corresponding to the current state of the user agent. The reuslts of such + speculative evaluations are not displayed immediately, but can be cached for use if the user agent + state matches the speculated state. This can increase the concurrency between the user agent and + worklet threads.

        + +

        As a result of this, to prevent interoperability risks between user agents, authors who + register classes on such WorkletGlobalScopes should make their code stateless. That + is, the only effect of invoking a method should be its result, and not any side effects such as + updating mutable state.

        + +

        The same techniques which encourage code idempotence also + encourage authors to write stateless code.

        + +
        + +

        Examples

        + + + +

        For these examples, we'll use a fake worklet. The Window object provides two + Worklet instances, which each run code in their own collection of + FakeWorkletGlobalScopes: + +

        partial interface Window {
        +  [SameObject] readonly attribute Worklet fakeWorklet1;
        +  [SameObject] readonly attribute Worklet fakeWorklet2;
        +};
        + +

        Each Window has two Worklet instances, fake worklet 1 and + fake worklet 2. Both of these have their worklet global scope type set to + FakeWorkletGlobalScope, and their worklet destination type set to "fakeworklet". User agents should create at least two + FakeWorkletGlobalScope instances per worklet.

        + +

        "fakeworklet" is not actually a valid destination per Fetch. But this + illustrates how real worklets would generally have their own worklet-specific destination.

        + +

        The fakeWorklet1 getter steps are to return + this's fake worklet 1.

        + +

        The fakeWorklet2 getter steps are to return + this's fake worklet 2.

        + +
        + +
        [Global=(Worklet,FakeWorklet),
        + Exposed=FakeWorklet]
        +interface FakeWorkletGlobalScope {
        +  undefined registerFake(DOMString type, Function classConstructor);
        +};
        + +

        Each FakeWorkletGlobalScope has a registered class constructors map, + which is an ordered map, initially empty.

        + +

        The registerFake(type, classConstructor) method + steps are to set this's registered class constructors + map[type] to classConstructor.

        + +

        Loading scripts

        + + + +

        To load scripts into fake worklet 1, a web developer would write:

        + +
        window.fakeWorklet1.addModule('script1.mjs');
        +window.fakeWorklet1.addModule('script2.mjs');
        + +

        Note that which script finishes fetching and runs first is dependent on network timing: it + could be either script1.mjs or script2.mjs. This + generally won't matter for well-written scripts intended to be loaded in worklets, if they follow + the suggestions about preparing for speculative + evaluation.

        + +

        If a web developer wants to perform a task only after the scripts have successfully run and + loaded into some worklets, they could write:

        + +
        Promise.all([
        +    window.fakeWorklet1.addModule('script1.mjs'),
        +    window.fakeWorklet2.addModule('script2.mjs')
        +]).then(() => {
        +    // Do something which relies on those scripts being loaded.
        +});
        + +
        + +

        Another important point about script-loading is that loaded scripts can be run in multiple + WorkletGlobalScopes per Worklet, as discussed in the section on code idempotence. In particular, the specification above + for fake worklet 1 and fake worklet 2 require this. So, consider a + scenario such as the following:

        + +
        // script.mjs
        +console.log("Hello from a FakeWorkletGlobalScope!");
        + +
        // app.mjs
        +window.fakeWorklet1.addModule("script.mjs");
        + +

        This could result in output such as the following from a user agent's console:

        + +
        [fakeWorklet1#1] Hello from a FakeWorkletGlobalScope!
        +[fakeWorklet1#4] Hello from a FakeWorkletGlobalScope!
        +[fakeWorklet1#2] Hello from a FakeWorkletGlobalScope!
        +[fakeWorklet1#3] Hello from a FakeWorkletGlobalScope!
        + +

        If the user agent at some point decided to kill and restart the third instance of + FakeWorkletGlobalScope, the console would again print [fakeWorklet1#3] Hello from a FakeWorkletGlobalScope! when this occurs.

        + +

        Registering a class and invoking its methods

        + + + +

        Let's say that one of the intended usages of our fake worklet by web developers is to allow + them to customize the highly-complex process of boolean negation. They might register their + customization as follows:

        + +
        // script.mjs
        +registerFake('negation-processor', class {
        +  process(arg) {
        +    return !arg;
        +  }
        +});
        + +
        // app.mjs
        +window.fakeWorklet1.addModule("script.mjs");
        + +

        To make use of such registered classes, the specification for fake worklets could define a + find the opposite of true algorithm, given a + Worklet worklet:

        + +
          +
        1. Optionally, create a worklet global scope for worklet.

        2. + +
        3. Let workletGlobalScope be one of worklet's global scopes, chosen in an + implementation-defined manner.

        4. + +
        5. Let classConstructor be workletGlobalScope's registered class + constructors map["negation-processor"].

        6. + +
        7. Let classInstance be the result of constructing classConstructor, with + no arguments.

        8. + +
        9. Let function be Get(classInstance, + "process"). Rethrow any exceptions.

          + +
        10. Let callback be the result of converting function to a Web IDL Function instance.

        11. + +
        12. Return the result of invoking + callback with the arguments « true » and with classInstance as the callback this value.

        13. +
        + +

        Another, perhaps better, specification architecture would be to extract the "process" property and convert it into a Function at registration time, as part of the registerFake() method steps.

        + +
        + +

        Infrastructure

        + +

        The global scope

        + +

        Subclasses of WorkletGlobalScope are used to create global objects wherein code loaded into a particular Worklet can + execute.

        + +
        [Exposed=Worklet]
        +interface WorkletGlobalScope {};
        + +

        Other specifications are intended to subclass WorkletGlobalScope, + adding APIs to register a class, as well as other APIs specific for their worklet type.

        + +
        + +

        Each WorkletGlobalScope has an associated owner document, which is a + Document or null. It is initially null.

        + + + +

        Each WorkletGlobalScope has an associated module map. It is a module map, + initially empty.

        + +
        + +
        Agents and event loops
        + + + +

        Each WorkletGlobalScope is contained in its own worklet agent, which + has its corresponding event loop. However, in + practice, implementation of these agents and event loops is expected to be different from most + others.

        + +

        A worklet agent exists for each WorkletGlobalScope since, in theory, + an implementation could use a separate thread for each WorkletGlobalScope instance, + and allowing this level of parallelism is best done using agents. However, because their + [[CanBlock]] value is false, there is no requirement that agents and threads are one-to-one. This + allows implementations the freedom to execute scripts loaded into a worklet on any thread, + including one running code from other agents with [[CanBlock]] of false, such as the thread of a + similar-origin window agent ("the main thread"). Contrast this with dedicated worker agents, whose true value for [[CanBlock]] + effectively requires them to get a dedicated operating system thread.

        + +

        Worklet event loops are also somewhat special. They are only + used for tasks associated with addModule(), tasks wherein the user agent invokes + author-defined methods, and microtasks. Thus, even though the event loop processing model specifies that all event loops + run continuously, implementations can achieve observably-equivalent results using a simpler + strategy, which just invokes author-provided + methods and then relies on that process to perform a microtask checkpoint.

        + +
        Creating worklet global scopes
        + +

        To create a worklet global scope for a Worklet + worklet:

        + +
          +
        1. Let outsideSettings be worklet's relevant settings + object.

        2. + +
        3. Let agent be the result of obtaining a + worklet agent given outsideSettings. Run the rest of these steps in that + agent.

        4. + +
        5. +

          Let realmExecutionContext be the result of creating a new JavaScript + realm given agent and the following customizations:

          + +
            +
          • For the global object, create a new object of the type given by worklet's + worklet global scope type.

          • +
          +
        6. + +
        7. Let workletGlobalScope be the global + object of realmExecutionContext's Realm component.

        8. + +
        9. Let insideSettings be the result of setting up a worklet environment settings object given + realmExecutionContext and outsideSettings.

        10. + +
        11. Set workletGlobalScope's owner document to + outsideSettings's global object's + associated Document.

        12. + +
        13. Initialize a global object's CSP list given workletGlobalScope. +

        14. + +
        15. Let moduleURLs be the result of getting the + keys of worklet's module + responses map.

        16. + +
        17. +

          For each moduleURL of worklet's + module responses map:

          + +
            +
          1. +

            Fetch a worklet script graph given moduleURL, + insideSettings, worklet's worklet destination type, what credentials mode?, insideSettings, and worklet's + module responses map. Wait until + the algorithm asynchronously completes with script.

            + +

            This will not actually perform a network request, as it will just reuse responses from worklet's module responses map. The main + purpose of this step is to create a new workletGlobalScope-specific module + script from the response.

            +
          2. + +
          3. Assert: script is not null, since the fetch succeeded and the source text was + successfully parsed when worklet's module responses map was initially + populated with moduleURL.

          4. + +
          5. Run a module script given script.

          6. + +
          7. Run the responsible event loop specified by + insideSettings.

          8. +
          +
        18. + +
        19. Append workletGlobalScope to + worklet's global scopes.

        20. +
        + +
        Script settings for worklets
        + +

        To set up a worklet environment settings object, given a JavaScript + execution context executionContext and an environment settings + object outsideSettings:

        + +
          +
        1. Let origin be a unique opaque + origin.

        2. + +
        3. Let inheritedAPIBaseURL be outsideSettings's API base + URL.

        4. + +
        5. Let inheritedReferrerPolicy be outsideSettings's referrer policy.

        6. + +
        7. Let inheritedEmbedderPolicy be outsideSettings's embedder policy.

        8. + +
        9. Let realm be the value of executionContext's Realm + component.

        10. + +
        11. Let workletGlobalScope be realm's global object.

        12. + +
        13. +

          Let settingsObject be a new environment settings object whose + algorithms are defined as follows:

          + +
          +
          The realm execution context
          +
          +

          Return executionContext.

          +
          + +
          The module map
          +
          +

          Return workletGlobalScope's module map.

          +
          + +
          The responsible document
          +

          Not applicable (the responsible event loop is not a window event + loop).

          + +
          The API URL character encoding
          +
          +

          Return UTF-8.

          +
          + +
          The API base URL
          +
          +

          Return inheritedAPIBaseURL.

          +
          + +
          The origin
          +
          +

          Return origin.

          +
          + +
          The referrer policy
          +
          +

          Return inheritedReferrerPolicy.

          +
          + +
          The embedder policy
          +
          +

          Return inheritedEmbedderPolicy.

          +
          + +
          The cross-origin + isolated capability
          +

          Return TODO.

          +
          +
        14. + +
        15. Set settingsObject's id to a new + unique opaque string, creation URL to + inheritedAPIBaseURL, top-level creation URL to null, top-level + origin to outsideSettings's top-level origin, target browsing context to null, and + active service worker to + null.

        16. + +
        17. Set realm's [[HostDefined]] field to settingsObject.

        18. + +
        19. Return settingsObject.

        20. +
        + +

        The Worklet class

        + +

        The Worklet class provides the capability to add module scripts into its + associated WorkletGlobalScopes. The user agent can then create classes registered on + the WorkletGlobalScopes and invoke their methods.

        + +
        [Exposed=Window]
        +interface Worklet {
        +  [NewObject] Promise<undefined> addModule(USVString moduleURL, optional WorkletOptions options = {});
        +};
        +
        +dictionary WorkletOptions {
        +  RequestCredentials credentials = "same-origin";
        +};
        + +

        Specifications that create Worklet instances must specify the following for a + given instance:

        + +
          +
        • its worklet global scope type, which must be a Web IDL type that inherits from WorkletGlobalScope; and

        • + +
        • its worklet destination type, which must be a destination, and is used when fetching + scripts.

        • +
        + +

        A Worklet has a list of global scopes, which contains + instances of the Worklet's worklet global scope type. It is initially + empty.

        + +

        A Worklet has a module + responses map, which is an ordered map from URLs to + responses, initially empty. Access to this map should be + thread-safe.

        + +
        +

        The module responses map exists to + ensure that WorkletGlobalScopes created at different times get equivalent module scripts run in them, based on the same source text. This + allows the creation of additional WorkletGlobalScopes to be transparent to the + author.

        + +

        In practice, user agents are not expected to implement the module responses map and the addModule() method using a thread-safe map. Instead, when + addModule() is called, user agents can fetch the + module graph on the main thread, and send the fetched source text (i.e., the important data + contained in the module responses map) + to each thread which has a WorkletGlobalScope.

        + +

        Then, when a user agent creates a new WorkletGlobalScope for a given + Worklet, it can simply send the map of fetched source text from the main thread to + the thread containing the new WorkletGlobalScope.

        +
        + +

        The addModule(moduleURL, + options) method steps are:

        + +
          +
        1. Let outsideSettings be the relevant settings object of + this.

        2. + +
        3. Parse moduleURL relative to + outsideSettings.

        4. + +
        5. If this fails, then return a promise rejected with a + "SyntaxError" DOMException.

        6. + +
        7. Let moduleURLRecord be the resulting URL record.

        8. + +
        9. Let promise be a new promise.

        10. + +
        11. +

          Run the following steps in parallel:

          + +
            +
          1. +

            If this's global scopes + is empty, then:

            + +
              +
            1. Create a worklet global scope given this.

            2. + +
            3. Optionally, create additional + global scope instances, depending on the specific worklet in question and its + specification.

            4. + +
            5. Wait for all steps of the creation + process(es) — including those taking place within the worklet + agents — to complete, before moving on.

            6. +
            +
          2. + +
          3. Let pendingTasks be this's global scopes's size.

          4. + +
          5. +

            For each workletGlobalScope of + this's global scopes, + queue a global task on the networking task source given + workletGlobalScope to perform the following steps:

            + +
              +
            1. Fetch a worklet script graph given moduleURLRecord, + outsideSettings, this's worklet destination type, + options["credentials"], + workletGlobalScope's relevant settings object, and + this's module responses + map. Wait until the algorithm asynchronously completes with + script.

            2. + +
            3. +

              If script is null, then queue a global task on the + networking task source given this's relevant global + object to perform the following steps:

              + +
                +
              1. +

                If pendingTasks is not −1, then:

                + +
                  +
                1. Set pendingTasks to −1.

                2. + +
                3. Reject promise with an "AbortError" + DOMException.

                4. +
                +
              2. +
              +
            4. + +
            5. +

              If script's error to + rethrow is not null, then queue a global task on the networking + task source given this's relevant global object to perform + the following steps:

              + +
                +
              1. +

                If pendingTasks is not −1, then:

                + +
                  +
                1. Set pendingTasks to −1.

                2. + +
                3. Reject promise with script's error to rethrow.

                4. +
                +
              2. +
              +
            6. + +
            7. Run a module script given script.

            8. + + +
            9. +

              Queue a global task on the + networking task source given this's relevant global + object to perform the following steps:

              + +
                +
              1. +

                If pendingTasks is not −1, then:

                + +
                  +
                1. Set pendingTasks to pendingTasks − 1.

                2. + +
                3. If pendingTasks is 0, then resolve promise.

                4. +
                +
              2. +
              +
            10. +
            +
          6. +
          +
        12. + +
        13. Return promise.

        14. +
        + +

        The worklet's lifetime

        + +

        The lifetime of a Worklet has no special considerations; it is tied to the object + it belongs to, such as the Window.

        + +

        The lifetime of a WorkletGlobalScope should be defined by specifications which + inherit from WorkletGlobalScope and define specific worklet types.

        + +

        Such specifications may define that worklet agents be + terminated at any time, particularly if their event + loop has no tasks queued, or if the user agent has no + pending operations planning to make use of the worklet, or if the user agent detects abnormal + operations such as infinite loops or callbacks exceeding imposed time limits.

        + +

        Web storage

        Introduction

        @@ -123386,9 +124126,6 @@ INSERT INTERFACES HERE
        [WHATWGWIKI]
        The WHATWG Wiki. WHATWG.
        -
        [WORKLETS]
        -
        Worklets. I. Kilpatrick. W3C.
        -
        [WSP]
        The WebSocket protocol, I. Fette, A. Melnikov. IETF.
        @@ -124519,6 +125256,10 @@ INSERT INTERFACES HERE William Chen for their contributions.

        +

        Special thanks to the CSSWG for developing + the worklets. In particular, thanks to Ian Kilpatrik for his work as + editor of the original worklets specification.

        +

        For about ten years starting in 2003, this standard was almost entirely written by Ian Hickson (Google, ian@hixie.ch). More recently, @@ -124616,6 +125357,13 @@ INSERT INTERFACES HERE repository, which is available under CC0.

        +

        Part of the revision history of the worklets feature can be found in the w3c/css-houdini-drafts + repository, which is available under the W3C Software and + Document License.

        +

        Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). This work is licensed under a Creative Commons Attribution 4.0 International License.