From cec5fcca61595dbaab2235d24a1e4e8655e4569f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 23 Nov 2024 12:49:07 +0100 Subject: [PATCH 1/2] Allow dedicated Workers to inherit the creator's import map This option adds an `importMap: "none" | "clone"` option to the `Worker` constructor, which defaults to `"none"`. When this option is set to `"clone"`, the `Worker` constructor will take a snapshot of the current import map and use it as the import map inside the worker. Passing the `importMap` option to `SharedWorker` is an error, to make it possible to give it a meaning in the future. --- source | 74 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/source b/source index f17c3694ad9..92ffce1972b 100644 --- a/source +++ b/source @@ -106488,10 +106488,11 @@ new PaymentRequest(…); // Allowed to use

A global object has an import map, initially an empty import map.

-

For now, only Window global - objects have their import map modified - from the initial empty one. The import map is - only accessed for the resolution of a root module script.

+

For now, only Window and DedicatedWorkerGlobalScope + global objects have their import map modified from the initial empty one. The + import map is only accessed for the resolution of + a root module script.

A global object has a resolved module set, a set of specifier resolution records, initially @@ -109215,12 +109216,9 @@ dictionary PromiseRejectionEventInit : EventInit -

  • Let importMap be an empty import map.

  • - -
  • If settingsObject's global - object implements Window, then set importMap to - settingsObject's global object's - import map.

  • +
  • Let importMap be settingsObject's global object's import map.

  • Let serializedBaseURL be baseURL, serialized.

  • @@ -120547,8 +120545,8 @@ interface SharedWorkerGlobalScope : WorkerGlobalScope

    When a user agent is to run a worker for a script with Worker or SharedWorker object worker, URL url, environment settings object outside settings, MessagePort - outside port, and a WorkerOptions dictionary options, it must - run the following steps.

    + outside port, a WorkerOptions dictionary options, and an + import map importMap, it must run the following steps.

    1. Let is shared be true if worker is a SharedWorker @@ -120591,6 +120589,9 @@ interface SharedWorkerGlobalScope : WorkerGlobalScope data-x="concept-WorkerGlobalScope-name">name to the value of options's name member.

    2. +
    3. Set worker global scope's import map to importMap.

    4. +
    5. Append owner to worker global scope's owner set.

    6. @@ -121005,7 +121006,7 @@ interface SharedWorkerGlobalScope : WorkerGlobalScope
      [Exposed=(Window,DedicatedWorker,SharedWorker)]
       interface Worker : EventTarget {
      -  constructor((TrustedScriptURL or USVString) scriptURL, optional WorkerOptions options = {});
      +  constructor((TrustedScriptURL or USVString) scriptURL, optional DedicatedWorkerOptions options = {});
       
         undefined terminate();
       
      @@ -121015,12 +121016,18 @@ interface Worker : EventTarget {
       
       dictionary WorkerOptions {
         WorkerType type = "classic";
      -  RequestCredentials credentials = "same-origin"; // credentials is only used if type is "module"
      +  RequestCredentials  credentials = "same-origin"; // credentials is only used if type is "module"
         DOMString name = "";
       };
       
      +dictionary DedicatedWorkerOptions : WorkerOptions {
      +  WorkerImportMapInheritance importMap = "none";
      +};
      +
       enum WorkerType { "classic", "module" };
       
      +enum WorkerImportMapInheritance { "none", "clone" };
      +
       Worker includes AbstractWorker;
       Worker includes MessageEventTarget;
      @@ -121108,6 +121115,27 @@ enum WorkerType { "classic", "module" };
    7. If worker URL is failure, then throw a "SyntaxError" DOMException.

    8. +
    9. Let importMap be an empty import map.

    10. + +
    11. +

      If options's importMap member is "clone", then:

      + +
        +
      1. If the current global object implements Window or + DedicatedWorkerGlobalScope, set importMap to a deep copy of the + current global object's import + map.

      2. + +
      3. Else, throw a TypeError exception.

      4. +
      + +

      The current global object's import map could be modified, by merging it with a new import map. Such + updates will not be reflected in the cloned import map.

      +
    12. +
    13. Let worker be a new Worker object.

    14. Let outside port be a new MessagePort in outside @@ -121123,7 +121151,7 @@ enum WorkerType { "classic", "module" };

      1. Run a worker given worker, worker URL, outside - settings, outside port, and options.

      2. + settings, outside port options, and importMap.

    15. @@ -121137,10 +121165,15 @@ enum WorkerType { "classic", "module" };
      [Exposed=Window]
       interface SharedWorker : EventTarget {
      -  constructor((TrustedScriptURL or USVString) scriptURL, optional (DOMString or WorkerOptions) options = {});
      +  constructor((TrustedScriptURL or USVString) scriptURL, optional (DOMString or SharedWorkerOptions) options = {});
       
         readonly attribute MessagePort port;
       };
      +
      +dictionary SharedWorkerOptions : WorkerOptions {
      + any importMap; // used to prevent passing DedicatedWorkerOptions' importMap option
      +};
      +
       SharedWorker includes AbstractWorker;
      @@ -121193,7 +121226,7 @@ interface SharedWorker : EventTarget { "script".

    16. If options is a DOMString, set - options to a new WorkerOptions dictionary whose options to a new SharedWorkerOptions dictionary whose name member is set to the value of options and whose other members are set to their default values.

    17. @@ -121212,6 +121245,9 @@ interface SharedWorker : EventTarget {
    18. If urlRecord is failure, then throw a "SyntaxError" DOMException.

    19. +
    20. If options's importMap member is not undefined, throw + a TypeError exception.

    21. +
    22. Let worker be a new SharedWorker object.

    23. Let outside port be a new MessagePort in outside @@ -121338,8 +121374,8 @@ interface SharedWorker : EventTarget {

    24. Otherwise, in parallel, run a worker given worker, - urlRecord, outside settings, outside port, and - options.

    25. + urlRecord, outside settings, outside port, options, + and an empty import map.

    From 6533032eb502af6210e57c6efaeb4b8f208ed8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 23 Nov 2024 16:51:18 +0100 Subject: [PATCH 2/2] Support passing an object as the import map to `Worker` This commit allows passing a JavaScript object to `Worker`'s `importMap` option, which is validated and used as the worker's import map. The existing validation of the JSON import map has been delegated to WebIDL, so that it can be re-used for this option's value. --- source | 94 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/source b/source index 92ffce1972b..527854c9155 100644 --- a/source +++ b/source @@ -2318,6 +2318,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • The forgiving-base64 encode and forgiving-base64 decode algorithms
  • exclusive range
  • +
  • parse a JSON string to a JavaScript value
  • parse a JSON string to an Infra value
  • HTML namespace
  • MathML namespace
  • @@ -2878,6 +2879,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • [LegacyUnenumerableNamedProperties]
  • [LegacyUnforgeable]
  • set entries
  • +
  • convert to an IDL value
  • Web IDL also defines the following types that are used in Web IDL fragments in @@ -109747,27 +109749,51 @@ dictionary PromiseRejectionEventInit : EventInit


    +
    dictionary ImportMap {
    +    record<DOMString, any> imports;
    +    record<DOMString, record<DOMString, any>> scopes;
    +    record<DOMString, any> integrity;
    +  };
    +

    To parse an import map string, given a string input and a URL baseURL:

      -
    1. Let parsed be the result of parsing a JSON string to an Infra value given input.

    2. +
    3. Let jsVal be the result of parsing a JSON string to a JavaScript value given input.

    4. + +
    5. If jsVal is null or undefined, throw a TypeError indicating that + the top-level value needs to be a JSON object.

    6. + +
    7. Let parsed be jsVal converted to an ImportMap.

      + +
    8. Let importMap be the result of creating an + import map given parsed and baseURL.

    9. -
    10. If parsed is not an ordered map, then throw a - TypeError indicating that the top-level value needs to be a JSON object.

    11. +
    12. +

      If jsVal.[[OwnPropertyKeys]]() contains any + items besides "imports", "scopes", or "integrity", then the user agent should report a warning to the + console indicating that an invalid top-level key was present in the import map.

      +

      This can help detect typos. It is not an error, because that would prevent any + future extensions from being added backward-compatibly.

      +
    13. + +
    14. Return importMap.

    15. +
    + +

    To create an import map, given an ImportMap parsed and a + URL baseURL:

    + +
    1. Let sortedAndNormalizedImports be an empty ordered map.

    2. -

      If parsed["imports"] exists, then:

      +

      If parsed["imports"] is not undefined, then:

        -
      1. If parsed["imports"] is not an ordered - map, then throw a TypeError indicating that the value for the "imports" top-level key needs to be a JSON object.

      2. -
      3. Set sortedAndNormalizedImports to the result of sorting and normalizing a module specifier map given parsed["imports"] and baseURL.

      4. @@ -109777,14 +109803,9 @@ dictionary PromiseRejectionEventInit : EventInit

        Let sortedAndNormalizedScopes be an empty ordered map.

      5. -

        If parsed["scopes"] exists, then:

        +

        If parsed["scopes"] is not undefined, then:

          -
        1. If parsed["scopes"] is not an ordered - map, then throw a TypeError indicating that the value for the "scopes" top-level key needs to be a JSON object.

        2. -
        3. Set sortedAndNormalizedScopes to the result of sorting and normalizing scopes given parsed["scopes"] and baseURL.

        4. @@ -109794,31 +109815,15 @@ dictionary PromiseRejectionEventInit : EventInit

          Let normalizedIntegrity be an empty ordered map.

        5. -

          If parsed["integrity"] exists, then:

          +

          If parsed["integrity"] is not undefined, then:

            -
          1. If parsed["integrity"] is not an ordered - map, then throw a TypeError indicating that the value for the "integrity" top-level key needs to be a JSON object.

          2. -
          3. Set normalizedIntegrity to the result of normalizing a module integrity map given parsed["integrity"] and baseURL.

        6. -
        7. -

          If parsed's keys contains any items besides "imports", "scopes", or "integrity", then the user agent should - report a warning to the console indicating that an invalid top-level key was - present in the import map.

          - -

          This can help detect typos. It is not an error, because that would prevent any - future extensions from being added backward-compatibly.

          -
        8. -
        9. Return an import map whose imports are sortedAndNormalizedImports, whose scopes are @@ -110197,8 +110202,8 @@ dictionary PromiseRejectionEventInit : EventInit

          To sort and normalize a module - specifier map, given an ordered map originalMap and a - URL baseURL:

          + specifier map, given a record<DOMString, any> + originalMap and a URL baseURL:

          1. Let normalized be an empty ordered map.

          2. @@ -110269,8 +110274,9 @@ dictionary PromiseRejectionEventInit : EventInitb's key.

          -

          To sort and normalize scopes, given an - ordered map originalMap and a URL baseURL:

          +

          To sort and normalize scopes, given a record<DOMString, record<DOMString, any>> originalMap and a + URL baseURL:

          1. Let normalized be an empty ordered map.

          2. @@ -110280,10 +110286,6 @@ dictionary PromiseRejectionEventInit : EventInitpotentialSpecifierMap of originalMap:

              -
            1. If potentialSpecifierMap is not an ordered map, then throw a - TypeError indicating that the value of the scope with prefix - scopePrefix needs to be a JSON object.

            2. -
            3. Let scopePrefixURL be the result of URL parsing scopePrefix with baseURL.

            4. @@ -110319,7 +110321,7 @@ dictionary PromiseRejectionEventInit : EventInitmodule specifier resolution.

              To normalize a module integrity map, - given an ordered map originalMap:

              + given a record<DOMString, any> originalMap:

              1. Let normalized be an empty ordered map.

              2. @@ -121021,7 +121023,7 @@ dictionary WorkerOptions { }; dictionary DedicatedWorkerOptions : WorkerOptions { - WorkerImportMapInheritance importMap = "none"; + (WorkerImportMapInheritance or ImportMap) importMap = "none"; }; enum WorkerType { "classic", "module" }; @@ -121136,6 +121138,12 @@ enum WorkerImportMapInheritance { "none", "clone" }; updates will not be reflected in the cloned import map.

                +
              3. Else, if options's importMap member is an + ImportMap, set importMap to the result of creating an import map given options's importMap + member and TODO: which base URL? The worker's, or the + creator's?.

              4. +
              5. Let worker be a new Worker object.

              6. Let outside port be a new MessagePort in outside