From 1a334de5d3a2019d51f9c87570919fb38a12bc9b Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 8 Oct 2020 18:19:08 -0400 Subject: [PATCH 01/12] 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.

        From d111244f32edbfba2b43980e3b88862a7273c2f6 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 13 Oct 2020 12:10:43 -0400 Subject: [PATCH 02/12] SecureContext --- source | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/source b/source index ebb04e0bb92..e0256bdc0f6 100644 --- a/source +++ b/source @@ -89190,15 +89190,9 @@ document.querySelector("button").addEventListener("click", bound);
      16. -

        If global is a WorkletGlobalScope, then:

        +

        If global is a WorkletGlobalScope, then return true.

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

        2. - -
        3. Return false.

        4. -
        +

        Worklets can only be created in secure contexts.

    3. @@ -101583,8 +101577,8 @@ interface WorkerLocation { FakeWorkletGlobalScopes:
      partial interface Window {
      -  [SameObject] readonly attribute Worklet fakeWorklet1;
      -  [SameObject] readonly attribute Worklet fakeWorklet2;
      +  [SameObject, SecureContext] readonly attribute Worklet fakeWorklet1;
      +  [SameObject, SecureContext] readonly attribute Worklet fakeWorklet2;
       };

      Each Window has two Worklet instances, fake worklet 1 and @@ -101607,7 +101601,8 @@ interface WorkerLocation {


      [Global=(Worklet,FakeWorklet),
      - Exposed=FakeWorklet]
      + Exposed=FakeWorklet,
      + SecureContext]
       interface FakeWorkletGlobalScope {
         undefined registerFake(DOMString type, Function classConstructor);
       };
      @@ -101733,7 +101728,7 @@ window.fakeWorklet1.addModule("script.mjs"); object">global objects wherein code loaded into a particular Worklet can execute.

      -
      [Exposed=Worklet]
      +  
      [Exposed=Worklet, SecureContext]
       interface WorkletGlobalScope {};

      Other specifications are intended to subclass WorkletGlobalScope, @@ -101953,7 +101948,7 @@ interface WorkletGlobalScope {};

      associated WorkletGlobalScopes. The user agent can then create classes registered on the WorkletGlobalScopes and invoke their methods.

      -
      [Exposed=Window]
      +  
      [Exposed=Window, SecureContext]
       interface Worklet {
         [NewObject] Promise<undefined> addModule(USVString moduleURL, optional WorkletOptions options = {});
       };
      
      From df73aedfa183ce0bb878e70528b74acd1148863d Mon Sep 17 00:00:00 2001
      From: Domenic Denicola 
      Date: Tue, 13 Oct 2020 12:10:56 -0400
      Subject: [PATCH 03/12] Tweaks
      
      ---
       source | 6 +++---
       1 file changed, 3 insertions(+), 3 deletions(-)
      
      diff --git a/source b/source
      index e0256bdc0f6..88334e36122 100644
      --- a/source
      +++ b/source
      @@ -101498,7 +101498,7 @@ interface WorkerLocation {
          
    4. Have a reduced API surface on the global scope.

    5. 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 + specifications, or is implementation-defined. They are not tied to the lifetime of a Window or Document.

    6. @@ -101589,8 +101589,8 @@ interface WorkerLocation {

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

      + illustrates how real worklets would generally have their own worklet-type-specific destination. +

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

      From 508cc5992153814706b2f878119061ed5931cfdd Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 13 Oct 2020 12:11:08 -0400 Subject: [PATCH 04/12] Lifetime/owner document overhaul --- source | 77 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/source b/source index 88334e36122..b20c827dab2 100644 --- a/source +++ b/source @@ -79382,6 +79382,11 @@ dictionary WindowPostMessageOptions : PostMessageOptions
    7. Remove document from the owner set of each WorkerGlobalScope object whose set contains document.

    8. + +
    9. For each workletGlobalScope in + document's worklet global + scopes, terminate + workletGlobalScope.

    To discard a browsing @@ -101736,12 +101741,6 @@ interface WorkletGlobalScope {};

    -

    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.

    @@ -101776,7 +101775,7 @@ interface WorkletGlobalScope {};
    strategy, which just invokes author-provided methods and then relies on that process to perform a microtask checkpoint.

    -
    Creating worklet global scopes
    +
    Creation and termination

    To create a worklet global scope for a Worklet worklet:

    @@ -101806,11 +101805,6 @@ interface WorkletGlobalScope {}; settings object">setting up a worklet environment settings object given realmExecutionContext and outsideSettings.

    -
  • Set workletGlobalScope's owner document to - outsideSettings's global object's - associated Document.

  • -
  • Initialize a global object's CSP list given workletGlobalScope.

  • @@ -101849,10 +101843,43 @@ interface WorkletGlobalScope {}; +
  • Append workletGlobalScope to + outsideSettings's global object's + associated Document's worklet global scopes.

  • +
  • Append workletGlobalScope to worklet's global scopes.

  • +

    To terminate a worklet global scope given a WorkletGlobalScope + workletGlobalScope:

    + +
      +
    1. Let eventLoop be workletGlobalScope's relevant agent's + event loop.

    2. + +
    3. If there are any tasks queued in eventLoop's + task queues, discard them without processing them.

    4. + +
    5. Wait for eventLoop to complete the currently running + task.

    6. + +
    7. If the previous step doesn't complete within an implementation-defined period + of time, then abort the script currently running in + the worklet.

    8. + +
    9. Remove workletGlobalScope from the global scopes of the Worklet whose + global scopes contains + workletGlobalScope.

    10. + +
    11. Remove workletGlobalScope from the worklet global scopes of the + Document whose worklet global + scopes contains workletGlobalScope.

    12. +
    +
    Script settings for worklets

    To set up a worklet environment settings object, given a JavaScript @@ -102129,14 +102156,26 @@ dictionary WorkletOptions {

    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.

    +

    Each Document has a worklet + global scopes, which is a set of WorkletGlobalScopes, initially + empty.

    -

    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.

    +

    The lifetime of a WorkletGlobalScope is, at a minimum, tied to the + Document whose worklet global + scopes contain it. In particular, discarding the + Document will terminate the + corresponding WorkletGlobalScope and allow it to be garbage-collected.

    + +

    Additionally, specifications which inherit from WorkletGlobalScope and define + specific worklet types can give more specific details on when to create or terminate + the WorkletGlobalScopes for a given worklet type. For example, they might create them + during specific processes that call upon worklet code, as in the example. Or they might terminate them if the + worklet agent's 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

    From af799ad073866ddc6f4a02058130578fde0f9473 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 13 Oct 2020 12:11:32 -0400 Subject: [PATCH 05/12] XXX for cross-origin-isolated capability --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index b20c827dab2..2169b0cfc68 100644 --- a/source +++ b/source @@ -101952,7 +101952,7 @@ interface WorkletGlobalScope {};
    The cross-origin isolated capability
    -

    Return TODO.

    +

    Return TODO.

    From 3b49f1fb2f8d77a10d49e0ce67d72388a8650355 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 13 Oct 2020 12:25:06 -0400 Subject: [PATCH 06/12] Fix event loop nesting --- source | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source b/source index 2169b0cfc68..9c8a57971aa 100644 --- a/source +++ b/source @@ -101837,12 +101837,12 @@ interface WorkletGlobalScope {}; populated with moduleURL.

  • Run a module script given script.

  • - -
  • Run the responsible event loop specified by - insideSettings.

  • +
  • Run the responsible event loop specified by + insideSettings.

  • +
  • Append workletGlobalScope to outsideSettings's global object's associated Document's Date: Tue, 13 Oct 2020 12:27:08 -0400 Subject: [PATCH 07/12] Also destroy the event loop --- source | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source b/source index 9c8a57971aa..f11a0a76c14 100644 --- a/source +++ b/source @@ -101869,6 +101869,8 @@ interface WorkletGlobalScope {}; of time, then abort the script currently running in the worklet.

  • +
  • Destroy eventLoop.

  • +
  • Remove workletGlobalScope from the global scopes of the Worklet whose global scopes contains From 44441dc12fda052e7786914e4a024b4316e97f3c Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 13 Oct 2020 12:50:24 -0400 Subject: [PATCH 08/12] Add XXX for globalThis issue --- source | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source b/source index f11a0a76c14..6236b5b5c48 100644 --- a/source +++ b/source @@ -101526,9 +101526,14 @@ interface WorkerLocation { an idempotent way:

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

    • +
    • +

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

      + +

      Although this was the intention when worklets were first specified, the + introduction of globalThis has made it no longer true. See issue #6059 for more discussion.

      +
    • 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 From c946cea03754732dd52380f28d43abb62438ab26 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 13 Oct 2020 13:28:39 -0400 Subject: [PATCH 09/12] Make the dev edition pretty --- source | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/source b/source index 6236b5b5c48..c7ab7123305 100644 --- a/source +++ b/source @@ -101586,28 +101586,40 @@ interface WorkerLocation { Worklet instances, which each run code in their own collection of FakeWorkletGlobalScopes: -

      partial interface Window {
      +  
      partial interface Window {
         [SameObject, SecureContext] readonly attribute Worklet fakeWorklet1;
         [SameObject, SecureContext] 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.

      +
      +
      window . fakeWorklet1
      +
      Returns one of the fake worklets.
      + +
      window . fakeWorklet2
      +
      Returns another of the fake worklets.
      +
      + +

      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-type-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),
      @@ -101617,6 +101629,17 @@ interface FakeWorkletGlobalScope {
         undefined registerFake(DOMString type, Function classConstructor);
       };
      +

      Inside a FakeWorkletGlobalScope, the following global method is + available:

      + +
      +
      registerFake(type, classConstructor)
      +
      Registers the JavaScript class given by classConstructor for use when the user + agent later wants to do some operation specified by type.
      +
      + +
      +

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

      @@ -101625,6 +101648,8 @@ interface FakeWorkletGlobalScope { steps are to set this's registered class constructors map[type] to classConstructor.

      +
      +

      Loading scripts

      @@ -101695,7 +101720,12 @@ 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:

      + Worklet worklet, which invokes the process method on any class registered to one of worklet's global + scopes as having type "negation-processor", with true as the argument, and + then uses the result in some way.:

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

      2. @@ -101730,11 +101760,13 @@ window.fakeWorklet1.addModule("script.mjs");
      + +

      Infrastructure

      The global scope

      -

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

      @@ -101780,6 +101812,8 @@ interface WorkletGlobalScope {}; strategy, which just invokes author-provided methods and then relies on that process to perform a microtask checkpoint.

      +
      +
      Creation and termination

      To create a worklet global scope for a Worklet @@ -101976,9 +102010,11 @@ interface WorkletGlobalScope {};

    • Return settingsObject.

    • + +

      The Worklet class

      -

      The Worklet class provides the capability to add module scripts into its +

      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.

      @@ -102003,6 +102039,29 @@ dictionary WorkletOptions { scripts.

    +
    +
    await worklet . addModule(moduleURL[, { credentials }])
    +
    +

    Loads and executes the module script given by moduleURL into all of + worklet's global scopes. It can + also create additional global scopes as part of this process, depending on the worklet type. The + returned promise will fulfill once the script has been successfully loaded and run in all global + scopes.

    + +

    The credentials option can be set to a + credentials mode to modify the + script-fetching process. It defaults to "same-origin".

    + +

    Any failures in fetching the script or its + dependencies will cause the returned promise to be rejected with an + "AbortError" DOMException. Any errors in parsing the + script or its dependencies will cause the returned promise to be rejected with the exception + generated during parsing.

    +
    +
    + +
    +

    A Worklet has a list of global scopes, which contains instances of the Worklet's worklet global scope type. It is initially @@ -102158,15 +102217,21 @@ dictionary WorkletOptions {

  • Return promise.

  • + +

    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.

    +
    +

    Each Document has a worklet global scopes, which is a set of WorkletGlobalScopes, initially empty.

    +
    +

    The lifetime of a WorkletGlobalScope is, at a minimum, tied to the Document whose worklet global scopes contain it. In particular, discarding the From 72f3addac6cded9a2fdd66ad7c31855d34a61014 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 14 Oct 2020 11:01:57 -0400 Subject: [PATCH 10/12] Updates per review --- source | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source b/source index c7ab7123305..66c699abb1c 100644 --- a/source +++ b/source @@ -101503,8 +101503,7 @@ interface WorkerLocation {

  • 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 lifetime of a - Window or Document.

  • + specifications, often in an implementation-defined manner.

    As worklets have relatively high overhead, they are best used sparingly. Due to this, a given @@ -101879,9 +101878,6 @@ interface WorkletGlobalScope {}; -

  • Run the responsible event loop specified by - insideSettings.

  • -
  • Append workletGlobalScope to outsideSettings's global object's associated Document's WorkletGlobalScope {};

  • Append workletGlobalScope to worklet's global scopes.

  • + +
  • Run the responsible event loop specified by + insideSettings.

  • To terminate a worklet global scope given a WorkletGlobalScope @@ -102122,8 +102121,8 @@ dictionary WorkletOptions {

  • Create a worklet global scope given this.

  • Optionally, create additional - global scope instances, depending on the specific worklet in question and its - specification.

  • + global scope instances given this, depending on the specific worklet in question + and its specification.

  • Wait for all steps of the creation process(es) — including those taking place within the worklet From 21b18d10ead44a25a905d777316d3517644edb0b Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 14 Oct 2020 11:34:17 -0400 Subject: [PATCH 11/12] Fixes to addModule() and global scope creation --- source | 120 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 42 deletions(-) diff --git a/source b/source index 66c699abb1c..1094ee18fbe 100644 --- a/source +++ b/source @@ -101846,13 +101846,9 @@ interface WorkletGlobalScope {};

  • Initialize a global object's CSP list given workletGlobalScope.

  • -
  • Let moduleURLs be the result of getting the - keys of worklet's module - responses map.

  • -
  • For each moduleURL of worklet's - module responses map:

    + added modules list:

    1. @@ -102066,29 +102062,33 @@ dictionary WorkletOptions { instances of the Worklet's worklet global scope type. It is initially empty.

      +

      A Worklet has an added modules + list, which is a list of URLs, initially empty. + Access to this list should be thread-safe.

      +

      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.

      +

      The added modules list and module responses map exist 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.

      +

      In practice, user agents are not expected to implement these data structures, and the + algorithms that consult them, using thread-safe programming techniques. 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.

      +

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

      The WorkletOptions { data-x="concept-Worklet-global-scopes">global scopes's size.

    2. +
    3. Let addedSuccessfully be false.

    4. +
    5. For each workletGlobalScope of this's global scopes, @@ -102141,55 +102143,89 @@ dictionary WorkletOptions { 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. +

        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.

        + +

        Only the first of these fetches will actually perform a network request; the + ones for other WorkletGlobalScopes will reuse reuse responses from this's module responses map.

        +
      4. -

        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:

        +

        If script is null, then:

        1. -

          If pendingTasks is not −1, then:

          +

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

            -
          1. Set pendingTasks to −1.

          2. +
          3. +

            If pendingTasks is not −1, then:

            + +
              +
            1. Set pendingTasks to −1.

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

            4. +
            5. Reject promise with an "AbortError" + DOMException.

            6. +
            +
        2. + +
        3. Abort these steps.

      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:

        + rethrow is not null, then:

        1. -

          If pendingTasks is not −1, then:

          +

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

            -
          1. Set pendingTasks to −1.

          2. +
          3. +

            If pendingTasks is not −1, then:

            + +
              +
            1. Set pendingTasks to −1.

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

            4. +
            5. Reject promise with script's error to rethrow.

            6. +
            +
        2. + +
        3. Abort these steps.

      6. -
      7. Run a module script given script.

      8. +
      9. +

        If addedSuccessfully is false, then:

        + +
          +
        1. Append moduleURLRecord to + this's added modules + list.

        2. +
        3. Set addedSuccessfully to true.

        4. +
        +
      10. + +
      11. Run a module script given script.

      12. Queue a global task on the From f629c6cf91acc4c172dc45184c10ade7759786ea Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 15 Oct 2020 11:33:01 -0400 Subject: [PATCH 12/12] Add info on API base URL and different worklet types --- source | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source b/source index 1094ee18fbe..da353fac63d 100644 --- a/source +++ b/source @@ -101510,6 +101510,12 @@ interface WorkerLocation { WorkletGlobalScope is expected to be shared between multiple separate scripts. (This is similar to how a single Window is shared between multiple separate scripts.)

        +

        Worklets are a general technology that serve different use cases. Some worklets, such as those + defined in CSS Painting API, provide extension points intended for stateless, + idempotent, and short-running computations, which have special considerations as described in the + next couple of sections. Others, such as those defined in Web Audio API, are used for + stateful, long-running operations.

        +

        Code idempotence

        Some specifications which use worklets are intended to allow user agents to parallelize work @@ -101969,6 +101975,13 @@ interface WorkletGlobalScope {};

        The API base URL

        Return inheritedAPIBaseURL.

        + +

        Unlike workers or other globals derived from a single resource, worklets have + no primary resource; instead, multiple scripts, each with their own URL, are loaded into the + global scope via worklet.addModule(). So this API base URL + is rather unlike that of other globals. However, so far this doesn't matter, as no APIs + available to worklet code make use of the API base URL.

        The origin
        @@ -123853,6 +123866,9 @@ INSERT INTERFACES HERE
        [CSSOVERFLOW]
        CSS Overflow Module, L. Baron, F. Rivoal. W3C.
        +
        [CSSPAINT]
        +
        (Non-normative) CSS Painting API, I. Kilpatrick, D. Jackson. W3C.
        +
        [CSSPOSITION]
        CSS Positioned Layout, R. Atanassov, A. Eicholz. W3C.
        @@ -124246,6 +124262,9 @@ INSERT INTERFACES HERE
        [WEBANIMATIONS]
        Web Animations, B. Birtles, S. Stephens, D. Stockwell. W3C.
        +
        [WEBAUDIO]
        +
        (Non-normative) Web Audio API, P. Adenot, H. Choi. W3C.
        +
        [WEBCRYPTO]
        (Non-normative) Web Cryptography API, M. Watson. W3C.