From 914e7d5cba1718a6ef1f4937cb076bf46a74c7f0 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Wed, 17 Jun 2020 16:56:31 -0700 Subject: [PATCH 01/58] Reland JSON modules Reland JSON modules by reverting a530f6fe47e1f1e09f2a0b47634693f590432b83, resolving merge conflicts, and updating the change with respect to the string changes in a9ef15d6ea4ca7db9acead6ce0111475da4a0c3e. --- source | 335 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 250 insertions(+), 85 deletions(-) diff --git a/source b/source index bd7ac3fb749..11c3d2ad1aa 100644 --- a/source +++ b/source @@ -2635,6 +2635,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • converting to a sequence of Unicode scalar values
  • overload resolution algorithm
  • +
  • CreateSyntheticModule
  • +
  • SetSyntheticModuleExport
  • +
  • Synthetic Module Record
  • exposed
  • [LegacyFactoryFunction]
  • [LegacyLenientThis]
  • @@ -57042,11 +57045,14 @@ interface HTMLScriptElement : HTMLElement { redundantly setting it.

  • Setting the attribute to an ASCII case-insensitive match for the string - "module" means that the script is a module script, to be - interpreted according to the JavaScript Module top-level - production. Module scripts are not affected by the defer - attribute, but are affected by the async attribute - (regardless of the state of the src attribute).

  • + "module" means that the script is a module script. If it has + a JavaScript MIME type, or if the script is embedded inline, then it will be + interpreted as a JavaScript module script according to the JavaScript Module top-level production; if it has a JSON MIME + type, then it will be interpreted as a JSON module script. Module scripts + are not affected by the defer attribute, but are + affected by the async attribute (regardless of the state + of the src attribute).

  • Setting the attribute to any other value means that the script is a data block, which is not processed. None of the script attributes (except HTMLScriptElement : HTMLElement { scripts. By using a valid MIME type string now, you ensure that your data block will not ever be reinterpreted as a different script type, even in future user agents.

    -

    Classic scripts and module - scripts can be embedded inline, or be imported from an external file using the Classic scripts and JavaScript module scripts can be embedded inline, or be imported from an external + file using the src attribute, which if specified gives the URL of the external script resource to use. If src is specified, - it must be a valid non-empty URL potentially surrounded by spaces. The contents of - inline script elements, or the external script resource, must conform with the - requirements of the JavaScript specification's Script or Module productions, for classic - scripts and module scripts respectively.

    + it must be a valid non-empty URL potentially surrounded by spaces.

    + +

    The contents of inline script elements, or the external script resource, must + conform with the requirements of the JavaScript specification's Script or Module productions, for classic scripts and JavaScript module scripts respectively.

    + +

    The contents of the external script resource for JSON module + scripts must conform to the requirements of the JSON specification .

    When used to include data blocks, the data must be embedded inline, the format of the data must be given using the type @@ -57310,7 +57320,7 @@ o............A....e

    The following sample shows how a script element can be used to include an - external module script. + external JavaScript module script.

    <script type="module" src="app.mjs"></script>
    @@ -57321,37 +57331,37 @@ o............A....e

    Additionally, if code from another script element in the same Window imports the module from app.mjs (e.g. via import - "./app.mjs";), then the same module script created by the + "./app.mjs";), then the same JavaScript module script created by the former script element will be imported.

    -

    This example shows how to include a module script for modern user agents, and a - classic script for older user agents:

    +

    This example shows how to include a JavaScript module script for modern user + agents, and a classic script for older user agents:

    <script type="module" src="app.mjs"></script>
     <script nomodule defer src="classic-app-bundle.js"></script>
    -

    In modern user agents that support module scripts, the - script element with the nomodule attribute - will be ignored, and the script element with a type of "module" will be fetched and - evaluated (as a module script). Conversely, older user agents will ignore the +

    In modern user agents that support JavaScript module + scripts, the script element with the nomodule attribute will be ignored, and the script element with a type of "module", as that is an unknown script type for them — but they will have no - problem fetching and evaluating the other script element (as a classic - script), since they do not implement the nomodule attribute.

    + data-x="">module
    " will be fetched and evaluated (as a JavaScript module + script). Conversely, older user agents will ignore the script element with a + type of "module", as that is an + unknown script type for them — but they will have no problem fetching and evaluating the other + script element (as a classic script), since they do not implement the + nomodule attribute.

    The following sample shows how a script element can be used to write an inline - module script that performs a number of substitutions on the document's text, in - order to make for a more interesting reading experience (e.g. on a news site): JavaScript module script that performs a number of substitutions on the document's + text, in order to make for a more interesting reading experience (e.g. on a news site):

    <script type="module">
    @@ -57383,12 +57393,30 @@ o............A....e
      walkAllTextNodeDescendants(document.body, substitute);
     </script>
    -

    Some notable features gained by using a module script include the ability to import functions - from other JavaScript modules, strict mode by default, and how top-level declarations do not - introduce new properties onto the global object. Also note that no matter where - this script element appears in the document, it will not be evaluated until both - document parsing has complete and its dependency (dom-utils.mjs) has been - fetched and evaluated.

    +

    Some notable features gained by using a JavaScript module script include the ability to import + functions from other JavaScript modules, strict mode by default, and how top-level declarations + do not introduce new properties onto the global object. Also note that no matter + where this script element appears in the document, it will not be evaluated until + both document parsing has complete and its dependency (dom-utils.mjs) has + been fetched and evaluated.

    + +
    + +
    + +

    The following sample shows how to you can import a JSON module script from inside + a JavaScript module script:

    + +
    <script type="module">
    +import peopleInSpace from "http://api.open-notify.org/astros.json";
    +
    +const list = document.querySelector("#people-in-space");
    +for (const { craft, name } of peopleInSpace.people) {
    +  const li = document.createElement("li");
    +  li.textContent = `${name} / ${craft}`;
    +  list.append(li);
    +}
    +</script>
    @@ -86151,7 +86179,7 @@ interface ApplicationCache : EventTarget {
    Definitions
    -

    A script is one of two possible A script is one of three possible structs. All scripts have:

    @@ -86162,10 +86190,22 @@ interface ApplicationCache : EventTarget {
    A record
    -

    Either a Script Record, for classic - scripts; a Source Text Module Record, for module scripts; or null. In the former two cases, it represents a parsed script; - null represents a failure parsing.

    +
    +

    One of the following:

    + +
      +
    • a script record, for classic + scripts;

    • + +
    • a Source Text Module Record, for JavaScript module scripts;

    • + +
    • a Synthetic Module Record, for JSON + module scripts; or

    • + +
    • null, representing a parsing failure.

    • +
    +
    A parse error
    @@ -86228,6 +86268,35 @@ interface ApplicationCache : EventTarget { data-x="concept-script">script. It has no additional items.

    +

    Module scripts can be classified into two types:

    + +
      +
    • A module script is a JavaScript module script if + its record is a Source Text Module + Record.

    • + +
    • +

      A module script is a JSON module script if its record is a Synthetic Module Record, and it + was created via the create a JSON module + script algorithm. JSON module scripts represent a parsed JSON document.

      + + +

      As JSON documents do not import dependent modules, and do not throw exceptions + on evaluation, the fetch options and + base URL of a JSON module script are + always null.

      +
    • +
    +

    The active script is determined by the following algorithm:

      @@ -86795,8 +86864,8 @@ interface ApplicationCache : EventTarget { success).

        -
      1. Let script be the result of creating a module script using - source text, settings object, base URL, and +

      2. Let script be the result of creating a JavaScript module script + using source text, settings object, base URL, and options.

      3. If script is null, asynchronously complete this algorithm with null, and abort @@ -87047,8 +87116,8 @@ interface ApplicationCache : EventTarget {

      4. Let options be the descendant script fetch options for module script's fetch options.

      5. -
      6. Assert: options is not null, as module script is a module - script.

      7. +
      8. Assert: options is not null, as module script is a JavaScript + module script.

      9. For each url in urls, perform the @@ -87169,25 +87238,53 @@ interface ApplicationCache : EventTarget {

      10. response's status is not an ok status

      11. + + -
      12. -

        The result of extracting a MIME type from - response's header list is not a - JavaScript MIME type

        +
      13. +

        Let type be the result of extracting a + MIME type from response's header + list.

        -

        For historical reasons, fetching a - classic script does not include MIME type checking. In contrast, module scripts will - fail to load if they are not of a correct MIME type.

        -
      14. - +

        For historical reasons, fetching a + classic script does not include MIME type checking. In contrast, module scripts' + interpretation is driven by their MIME type, and they will fail to load if they are not of + a supported MIME type.

        -
      15. Let source text be the result of UTF-8 - decoding response's body.

      16. +
      17. +

        Let module script be null.

        + +

        If the resource does not have a MIME type which HTML knows how to handle + as a module, then module script will remain null, which is interpreted as + failure.

        +
      18. + +
      19. +

        If type is a JavaScript MIME type, then:

        + +
          +
        1. Let source text be the result of UTF-8 + decoding response's body.

        2. + +
        3. Set module script to the result of creating a JavaScript module + script given source text, module map settings object, + response's url, and + options.

        4. +
        +
      20. + +
      21. +

        If type is a JSON MIME type, then:

        -
      22. Let module script be the result of creating a module script given - source text, module map settings object, response's url, and options.

      23. +
          +
        1. Let source text be the result of UTF-8 + decoding response's body.

        2. + +
        3. Set module script to the result of creating a JSON module + script given source text and module map settings object.

        4. +
        +
      24. Set moduleMap[url] to module @@ -87217,36 +87314,43 @@ interface ApplicationCache : EventTarget { then return moduleScript's parse error.

      25. -
      26. Let childSpecifiers be the value of moduleScript's record's [[RequestedModules]] internal slot.

      27. +
      28. +

        If moduleScript's record is a + Cyclic Module Record:

        -
      29. Let childURLs be the list obtained by calling - resolve a module specifier once for each item of childSpecifiers, given - moduleScript's base URL and that item. - (None of these will ever fail, as otherwise moduleScript would have been marked as - itself having a parse error.)

      30. +
          +
        1. Let childSpecifiers be the value of moduleScript's record's [[RequestedModules]] internal slot.

        2. -
        3. Let childModules be the list obtained by getting each value in moduleMap whose key is given by an - item of childURLs.

        4. +
        5. Let childURLs be the list obtained by calling + resolve a module specifier once for each item of childSpecifiers, given + moduleScript's base URL and that item. + (None of these will ever fail, as otherwise moduleScript would have been marked as + itself having a parse error.)

        6. -
        7. -

          For each childModule of - childModules:

          +
        8. Let childModules be the list obtained by getting each value in moduleMap whose key is given by an + item of childURLs.

        9. -
            -
          1. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module - scripts in the graph rooted at moduleScript will have successfully been - fetched.

          2. +
          3. +

            For each childModule of + childModules:

            + +
              +
            1. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module + scripts in the graph rooted at moduleScript will have successfully been + fetched.

            2. -
            3. If discoveredSet already contains - childModule, continue.

            4. +
            5. If discoveredSet already contains + childModule, continue.

            6. -
            7. Let childParseError be the result of finding the first parse - error given childModule and discoveredSet.

            8. +
            9. Let childParseError be the result of finding the first parse + error given childModule and discoveredSet.

            10. -
            11. If childParseError is not null, return childParseError.

            12. +
            13. If childParseError is not null, return childParseError.

            14. +
            +
          @@ -87309,10 +87413,10 @@ interface ApplicationCache : EventTarget {
        10. Return script.

        -

        To create a module script, given a - string source, an environment settings object - settings, a URL baseURL, and some script fetch - options options:

        +

        To create a JavaScript module script, + given a string source, an environment settings + object settings, a URL baseURL, and some script + fetch options options:

        1. If scripting is disabled for @@ -87387,6 +87491,53 @@ interface ApplicationCache : EventTarget {

        2. Return script.

        +

        To create a JSON module script, given a + string source and an environment settings object settings:

        + +
          +
        1. Let script be a new module script that this algorithm will + subsequently initialize.

        2. + +
        3. Set script's settings object to settings.

        4. + +
        5. Set script's base URL and + fetch options to null.

        6. + +
        7. Set script's parse error and + error to rethrow to null.

        8. + +
        9. +

          Let json be ? Call(%JSONParse%, undefined, + « source »).

          + +

          If this throws an exception, set script's parse error to that exception, and return + script.

          +
        10. + +
        11. Set script's record to the result + of creating a synthetic + module record with a default export of json with settings.

        12. + +
        13. Return script.

        14. +
        + +

        To create a synthetic module record with a default export of a JavaScript value + value with an environment settings object settings:

        + +
          +
        1. +

          Return CreateSyntheticModule(« "default" », the following steps, + settings's Realm, + value) with the following steps given module as an argument:

          + +
            +
          1. SetSyntheticModuleExport(module, "default", + module.[[HostDefined]]).
          2. +
          +
        2. +
        +
        Calling scripts

        To run a classic script given a classic script @@ -88491,6 +88642,9 @@ import "https://example.com/foo/../module2.mjs";

      31. Set base URL to referencing script's base URL.

      32. + +
      33. Assert: base URL is not null, as referencing script is a + classic script or a JavaScript module script.

      @@ -88564,6 +88718,10 @@ import "https://example.com/foo/../module2.mjs";
    1. Set fetch options to the descendant script fetch options for referencing script's fetch options.

    2. + +
    3. Assert: Neither base URL nor fetch options is null, as + referencing script is a classic script or a JavaScript module + script.

    As explained above for HostResolveImportedModule, in the common @@ -88612,6 +88770,10 @@ import "https://example.com/foo/../module2.mjs";

    1. Let module script be moduleRecord.[[HostDefined]].

    2. +
    3. Assert: module script's base + URL is not null, as module script is a JavaScript module + script.

    4. +
    5. Let urlString be module script's base URL, serialized.

    6. @@ -92095,6 +92257,9 @@ enum DOMParserSupportedType {
    7. Let base URL be initiating script's base URL.

    8. +
    9. Assert: base URL is not null, as initiating script is a + classic script or a JavaScript module script.

    10. +
    11. Let fetch options be a script fetch options whose cryptographic nonce is initiating From b058240e31d99d1c1b7233a4ce01458231a74480 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 18 Jun 2020 14:06:51 -0700 Subject: [PATCH 02/58] Add import attribute type checks and initial plumbing. Update all [[RequestedModules]] references to reflect the change from string to ModuleRequest. Pass ModuleRequest instead of url to 'internal module graph fetching procedure'. Add optional ModuleRequest param to 'fetch a single module script'. Add checks in 'fetch a single module script' to fail if the type doesn't match. --- source | 109 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 32 deletions(-) diff --git a/source b/source index 11c3d2ad1aa..7dc91b17412 100644 --- a/source +++ b/source @@ -2776,6 +2776,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

    12. The Source Text Module Record specification type and its Evaluate and Link methods
    13. +
    14. The ModuleRequest Record specification type
    15. The ArrayCreate abstract operation
    16. The Call abstract operation
    17. @@ -57408,7 +57409,7 @@ o............A....e a JavaScript module script:

      <script type="module">
      -import peopleInSpace from "http://api.open-notify.org/astros.json";
      +import peopleInSpace from "http://api.open-notify.org/astros.json" if { type: "json" };
       
       const list = document.querySelector("#people-in-space");
       for (const { craft, name } of peopleInSpace.people) {
      @@ -87083,16 +87084,17 @@ interface ApplicationCache : EventTarget {
          record.[[RequestedModules]] is empty,
          asynchronously complete this algorithm with module script.

      -
    18. Let urls be a new empty list.

    19. +
    20. Let moduleRequests be a new empty list.

    21. -

      For each string requested of - record.[[RequestedModules]],

      +

      For each ModuleRequest Record + requested of record.[[RequestedModules]],

      1. Let url be the result of resolving a module specifier given module script's base URL and requested.

      2. + data-x="concept-script-base-url">base URL and requested.[[Specifier]].

        +
      3. Assert: url is never failure, because resolving a module specifier must have been ApplicationCache : EventTarget { url, then:

          -
        1. Append url to urls.

        2. +
        3. Append requested to + moduleRequests.

        4. Append url to visited set.

        5. @@ -87120,11 +87123,12 @@ interface ApplicationCache : EventTarget { module script.

        6. -

          For each url in urls, perform the - internal module script graph fetching procedure given url, fetch - client settings object, destination, options, module - script's settings object, visited set, and module - script's base URL. If the caller of this +

          For each moduleRequest in + moduleRequests, perform the internal module script graph fetching + procedure given moduleRequest, fetch client settings object, + destination, options, module script's settings + object, visited set, and module script's base URL. If the caller of this algorithm specified custom perform the fetch steps, pass those along while performing the internal module script graph fetching procedure.

          @@ -87143,21 +87147,30 @@ interface ApplicationCache : EventTarget {

        To perform the internal module script graph fetching procedure given a - url, a fetch client settings object, a destination, some - options, a module map settings object, a visited set, and a + moduleRequest, a fetch client settings object, a destination, + some options, a module map settings object, a visited set, and a referrer, perform these steps. The algorithm will asynchronously complete with either null (on failure) or a module script (on success).

          +
        1. Let url be the result of resolving + a module specifier given referrer and + moduleRequst.[[Specifier]].

        2. + +
        3. Assert: url is never failure, because resolving a module specifier must have been previously successful with these same two + arguments.

        4. +
        5. Assert: visited set contains url.

        6. Fetch a single module script given url, fetch client settings object, destination, options, module map settings object, - referrer, and with the top-level module fetch flag unset. If the caller of - this algorithm specified custom perform the - fetch steps, pass those along while fetching a - single module script.

          + referrer, moduleRequest, and with the + top-level module fetch flag unset. If the caller of this algorithm specified custom + perform the fetch steps, pass those along + while fetching a single module script.

        7. Return from this algorithm, and run the following steps when fetching a single module script asynchronously completes with @@ -87176,11 +87189,21 @@ interface ApplicationCache : EventTarget {

          To fetch a single module script, given a url, a fetch client settings object, a destination, some options, a module map - settings object, a referrer, and a top-level module fetch flag, run - these steps. The algorithm will asynchronously complete with either null (on failure) or a - module script (on success).

          + settings object, a referrer, an optional moduleRequest, and + a top-level module fetch flag, run these steps. The algorithm will asynchronously + complete with either null (on failure) or a module script (on success).

            +
          1. +

            If moduleRequest was given and if moduleRequest.[[Attributes]] + has a Record entry such that entry.[[Key]] is "type", then + let module type be entry.[[Value]]

            +

            Otherwise let module type be undefined.

            +
          2. + +
          3. If module type is neither undefined nor "json", asynchronously complete this algorithm + with null, and abort these steps

          4. +
          5. Let moduleMap be module map settings object's module map.

          6. @@ -87188,9 +87211,27 @@ interface ApplicationCache : EventTarget { 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. If moduleMap[url] exists, - asynchronously complete this algorithm with moduleMap[url], and abort - these steps.

          8. +
          9. +

            If moduleMap[url] exists, then:

            + +
              +
            1. +

              If any of the following conditions are met, asynchronously complete this algorithm + with moduleMap[url], and abort these steps.

              + +
                +
              • moduleMap[url] is a JavaScript module script + and module type is undefined.

              • + +
              • moduleMap[url] is a JSON module script + and module type is "json".

              • +
              +
            2. + +
            3. Otherwise, asynchronously complete this algorithm with null, and abort these steps

              +
            4. +
            +
          10. Set moduleMap[url] to "fetching".

            @@ -87242,7 +87283,7 @@ interface ApplicationCache : EventTarget {
          11. -

            Let type be the result of extracting a +

            Let MIME type be the result of extracting a MIME type from response's header list.

            @@ -87261,7 +87302,8 @@ interface ApplicationCache : EventTarget {
          12. -

            If type is a JavaScript MIME type, then:

            +

            If MIME type is a JavaScript MIME type and module type is + undefined, then:

            1. Let source text be the result of UTF-8 @@ -87275,7 +87317,8 @@ interface ApplicationCache : EventTarget {

            2. -

              If type is a JSON MIME type, then:

              +

              If MIME type is a JSON MIME type and module type is + "json", then:

              1. Let source text be the result of UTF-8 @@ -87319,12 +87362,13 @@ interface ApplicationCache : EventTarget { Cyclic Module Record:

                  -
                1. Let childSpecifiers be the value of moduleScript's

                  Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

                2. Let childURLs be the list obtained by calling - resolve a module specifier once for each item of childSpecifiers, given - moduleScript's base URL and that item. + resolve a module specifier once for each item moduleRequest of + moduleRequest, given moduleScript's base URL and moduleRequest.[[Specifier]]. (None of these will ever fail, as otherwise moduleScript would have been marked as itself having a parse error.)

                3. @@ -87457,13 +87501,13 @@ interface ApplicationCache : EventTarget {
                4. -

                  For each string requested of - result.[[RequestedModules]]:

                  +

                  For each ModuleRequest record + requested of result.[[RequestedModules]]:

                  1. Let url be the result of resolving a module specifier given script's base - URL and requested.

                  2. + URL and requested.[[Specifier]].

                  3. If url is failure, then:

                    @@ -121394,6 +121438,7 @@ INSERT INTERFACES HERE Daniel Brumbaugh Keeney, Daniel Buchner, Daniel Cheng, + Daniel Clark, Daniel Davis, Daniel Ehrenberg, Daniel Glazman, From d0137f5478da1e5c9c61cd3df02fd276ecf74e0e Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 18 Jun 2020 16:15:15 -0700 Subject: [PATCH 03/58] Plumb through ModuleRequest instead of string for 'fetch an import() module script graph', HostResolveImportedModule, and HostResolveImportedModuleDynamically. --- source | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/source b/source index 7dc91b17412..39a3f657c01 100644 --- a/source +++ b/source @@ -86795,24 +86795,25 @@ interface ApplicationCache : EventTarget { result.

                  -

                  To fetch an import() module script graph given a specifier, a base - URL, a settings object, and some options, run these steps. The - algorithm will asynchronously complete with either null (on failure) or a module +

                  To fetch an import() module script graph given a moduleRequest, a + base URL, a settings object, and some options, run these steps. + The algorithm will asynchronously complete with either null (on failure) or a module script (on success).

                  1. Let url be the result of resolving a - module specifier given base URL and specifier.

                  2. + module specifier given base URL and moduleRequest.[[Specifier]].

                    +
                  3. If url is failure, then asynchronously complete this algorithm with null, and abort these steps.

                  4. Fetch a single module script given url, settings object, "script", options, 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. + "client", moduleRequest, 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.

                  6. If result is null, asynchronously complete this algorithm with null, and abort these steps.

                  7. @@ -88662,7 +88663,7 @@ import "https://example.com/foo/../module2.mjs";
    22. HostResolveImportedModule(referencingScriptOrModule, - specifier)
      + moduleRequest)

      JavaScript contains an implementation-defined HostResolveImportedModule abstract operation. User @@ -88710,7 +88711,8 @@ import "https://example.com/foo/../module2.mjs"; data-x="concept-settings-object-module-map">module map.

    23. Let url be the result of resolving a - module specifier given base URL and specifier.

    24. + module specifier given base URL and moduleRequest.[[Specifier]].

      +
    25. Assert: url is never failure, because resolving a module specifier must have been previously successful with these @@ -88731,7 +88733,7 @@ import "https://example.com/foo/../module2.mjs";

    HostImportModuleDynamically(referencingScriptOrModule, - specifier, promiseCapability)
    + moduleRequest, promiseCapability)

    JavaScript contains an implementation-defined HostImportModuleDynamically abstract operation. @@ -88772,9 +88774,9 @@ import "https://example.com/foo/../module2.mjs"; case, referencingScriptOrModule is non-null.

  • -
  • Fetch an import() module script graph given specifier, base - URL, settings object, and fetch options. Wait until the algorithm - asynchronously completes with result.

  • +
  • Fetch an import() module script graph given moduleRequest, + base URL, settings object, and fetch options. Wait until the + algorithm asynchronously completes with result.

  • If result is null, then:

    @@ -88784,7 +88786,7 @@ import "https://example.com/foo/../module2.mjs"; TypeError, [[Target]]: empty }.

  • Perform FinishDynamicImport(referencingScriptOrModule, - specifier, promiseCapability, completion).

  • + moduleRequest, promiseCapability, completion).

  • Return.

  • @@ -88794,11 +88796,11 @@ import "https://example.com/foo/../module2.mjs"; the rethrow errors boolean set to true.

  • If running the module script throws an exception, then perform - FinishDynamicImport(referencingScriptOrModule, specifier, + FinishDynamicImport(referencingScriptOrModule, moduleRequest, promiseCapability, the thrown exception completion).

  • Otherwise, perform - FinishDynamicImport(referencingScriptOrModule, specifier, + FinishDynamicImport(referencingScriptOrModule, moduleRequest, promiseCapability, NormalCompletion(undefined)).

  • Return undefined.

  • From b2e7065117775e10dd1767bbe4466ecb7ca71e31 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 18 Jun 2020 16:47:42 -0700 Subject: [PATCH 04/58] Don't cache a null entry in the module map in the case where the MIME type is valid but doesn't match the requested type. --- source | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/source b/source index 39a3f657c01..c59c4290858 100644 --- a/source +++ b/source @@ -87297,37 +87297,49 @@ interface ApplicationCache : EventTarget {
  • Let module script be null.

    -

    If the resource does not have a MIME type which HTML knows how to handle - as a module, then module script will remain null, which is interpreted as - failure.

    +
    +

    If the resource does not have a MIME type which HTML knows how to handle + as a module or if the MIME type does not match the type specified in moduleRequest, + then module script will remain null, which is interpreted as failure.

    + +

    In the former case where a non-module MIME type is received, a null entry is added to + moduleMap so that future attempts to fetch a module at url will always + fail. On the other hand for the case where the MIME type is valid but does not match the + requested module type, nothing is cached in moduleMap, meaning that + future attempts to fetch the same url in another module graph could succeed if the correct + type were specified.

    +
  • -

    If MIME type is a JavaScript MIME type and module type is - undefined, then:

    +

    If MIME type is a JavaScript MIME type, then:

    -
      -
    1. Let source text be the result of UTF-8 - decoding response's body.

    2. +
        +
      1. If module type is not undefined, asynchronously complete this algorithm with + null, and abort these steps.

      2. -
      3. Set module script to the result of creating a JavaScript module - script given source text, module map settings object, - response's url, and - options.

      4. -
      +
    3. Let source text be the result of UTF-8 + decoding response's body.

    4. + +
    5. Set module script to the result of creating a JavaScript module + script given source text, module map settings object, + response's url, and + options.

    6. +
  • -

    If MIME type is a JSON MIME type and module type is - "json", then:

    +

    If MIME type is a JSON MIME type, then:

    +
      +
    1. If module type is not "json", asynchronously complete + this algorithm with null, and abort these steps.

    2. -
        -
      1. Let source text be the result of UTF-8 - decoding response's body.

      2. +
      3. Let source text be the result of UTF-8 + decoding response's body.

      4. -
      5. Set module script to the result of creating a JSON module - script given source text and module map settings object.

      6. -
      +
    3. Set module script to the result of creating a JSON module + script given source text and module map settings object.

    4. +
  • From 0cbf597276299bee4730ff593507d6bbd517d9c2 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 19 Jun 2020 10:07:50 -0700 Subject: [PATCH 05/58] Allow modulepreload to work for all module types without needing to specify type at the point of preload. Achieve this by adding 'module type must match' flag to 'fetch a single module script', which is unset only in the case of modulepreload. --- source | 59 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/source b/source index c59c4290858..18c0f5a1cde 100644 --- a/source +++ b/source @@ -86778,10 +86778,10 @@ interface ApplicationCache : EventTarget {
    1. Fetch a single module script given url, settings object, "script", options, 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.

    2. + "client", with the module type must match flag set, 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. If result is null, asynchronously complete this algorithm with null, and abort these steps.

    4. @@ -86810,10 +86810,11 @@ interface ApplicationCache : EventTarget {
    5. Fetch a single module script given url, settings object, "script", options, settings object, - "client", moduleRequest, 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.

    6. + "client", moduleRequest, with the module type must + match flag set, 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.

    7. If result is null, asynchronously complete this algorithm with null, and abort these steps.

    8. @@ -86835,14 +86836,15 @@ interface ApplicationCache : EventTarget {
      1. Fetch a single module script given url, settings object, destination, options, settings object, "client", and with the top-level module fetch flag set. Wait until - algorithm asynchronously completes with result.

      2. + data-x="">client", with the module type must match flag unset, and with the + top-level module fetch flag set. Wait until algorithm asynchronously completes with + result.

      3. Asynchronously complete this algorithm with result, but do not abort these steps.

      4. -

        Optionally, perform the following steps:

        +

        If result is not null, optionally perform the following steps:

        1. Let visited set be « url ».

        2. @@ -86900,10 +86902,10 @@ interface ApplicationCache : EventTarget {
        3. 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.

        4. + "client", with the module type must match flag set, 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. If result is null, asynchronously complete this algorithm with null, and abort these steps.

        6. @@ -87168,10 +87170,11 @@ interface ApplicationCache : EventTarget {
        7. Fetch a single module script given url, fetch client settings object, destination, options, module map settings object, - referrer, moduleRequest, and with the - top-level module fetch flag unset. If the caller of this algorithm specified custom - perform the fetch steps, pass those along - while fetching a single module script.

          + referrer, moduleRequest, with the module type must match flag + set, and with the top-level module fetch flag unset. If the caller of this algorithm + specified custom perform the fetch steps, + pass those along while fetching a single module + script.

        8. Return from this algorithm, and run the following steps when fetching a single module script asynchronously completes with @@ -87190,9 +87193,10 @@ interface ApplicationCache : EventTarget {

          To fetch a single module script, given a url, a fetch client settings object, a destination, some options, a module map - settings object, a referrer, an optional moduleRequest, and - a top-level module fetch flag, run these steps. The algorithm will asynchronously - complete with either null (on failure) or a module script (on success).

          + settings object, a referrer, an optional moduleRequest, a + module type must match flag, and a top-level module fetch flag, run these + steps. The algorithm will asynchronously complete with either null (on failure) or a + module script (on success).

          1. @@ -87221,6 +87225,8 @@ interface ApplicationCache : EventTarget { with moduleMap[url], and abort these steps.

              +
            • The module type must match flag is unset.

            • +
            • moduleMap[url] is a JavaScript module script and module type is undefined.

            • @@ -87315,8 +87321,8 @@ interface ApplicationCache : EventTarget {

              If MIME type is a JavaScript MIME type, then:

                -
              1. If module type is not undefined, asynchronously complete this algorithm with - null, and abort these steps.

              2. +
              3. If the module type must match flag is set and module type is not + undefined, asynchronously complete this algorithm with null, and abort these steps.

              4. Let source text be the result of UTF-8 decoding response's body.

              5. @@ -87331,8 +87337,9 @@ interface ApplicationCache : EventTarget {
              6. If MIME type is a JSON MIME type, then:

                  -
                1. If module type is not "json", asynchronously complete - this algorithm with null, and abort these steps.

                2. +
                3. If the module type must match flag is set and module type is not + "json", asynchronously complete this algorithm with null, and abort + these steps.

                4. Let source text be the result of UTF-8 decoding response's body.

                5. From 69320747089a1c3c43e9d14077620dd1e2e823d7 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 19 Jun 2020 11:33:05 -0700 Subject: [PATCH 06/58] After rebase, fix build break from name change to JSON.Parse in https://github.com/whatwg/html/commit/b1078ae50e1b08a2ab1592efab36d417444c8313 --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 18c0f5a1cde..1b7e9f911a8 100644 --- a/source +++ b/source @@ -87571,7 +87571,7 @@ interface ApplicationCache : EventTarget { error to rethrow to null.

                6. -

                  Let json be ? Call(%JSONParse%, undefined, +

                  Let json be ? Call(%JSON.Parse%, undefined, « source »).

                  If this throws an exception, set script's Date: Mon, 22 Jun 2020 11:37:00 -0700 Subject: [PATCH 07/58] Fix typo in JSON modules example and add note on requiring JSON MIME type. --- source | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source b/source index 1b7e9f911a8..03d4602a4fc 100644 --- a/source +++ b/source @@ -57405,7 +57405,7 @@ o............A....e

                  -

                  The following sample shows how to you can import a JSON module script from inside +

                  The following sample shows how a JSON module script can be imported from inside a JavaScript module script:

                  <script type="module">
                  @@ -57419,6 +57419,13 @@ for (const { craft, name } of peopleInSpace.people) {
                   }
                   </script>
                  +

                  MIME type checking for module scripts is strict. In order for the fetch of the + JSON module script to succeed, the HTTP reponse must have a + JSON MIME type, for example Content-Type: text/json. On the + other hand, if the if { type: "json" } part of the statement is omitted, + it is assumed that the intent is to import a JavaScript module script, and the fetch + will fail if the HTTP response has a MIME type that is not a JavaScript MIME type. +

                  @@ -87235,7 +87242,7 @@ interface ApplicationCache : EventTarget {
          2. -
          3. Otherwise, asynchronously complete this algorithm with null, and abort these steps

            +
          4. Otherwise, asynchronously complete this algorithm with null, and abort these steps.

        9. From a3621dd6a43ab0b0471c8f97cd9632fff6283795 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Mon, 22 Jun 2020 12:27:48 -0700 Subject: [PATCH 08/58] Update ModuleRequest definition to reference the import-attributes proposal spec --- source | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source b/source index 03d4602a4fc..97420a32059 100644 --- a/source +++ b/source @@ -2776,7 +2776,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
        10. The Source Text Module Record specification type and its Evaluate and Link methods
        11. -
        12. The ModuleRequest Record specification type
        13. The ArrayCreate abstract operation
        14. The Call abstract operation
        15. @@ -2858,6 +2857,14 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
        16. The HostGetImportMetaProperties abstract operation
        17. +

          User agents that support JavaScript must also implement the import attributes + proposal. The following term is defined there, and used in this specification:

          + +
            +
          • The ModuleRequest Record specification type
          • +
          +

          Users agents that support JavaScript must also implement ECMAScript Internationalization API.

          @@ -120939,6 +120946,9 @@ INSERT INTERFACES HERE
          [JSERRORSTACKS]
          (Non-normative) Error Stacks. Ecma International.
          +
          [JSIMPORTATTRIBUTES]
          +
          Import Attributes. Ecma International.
          +
          [JSIMPORTMETA]
          import.meta. Ecma International.
          From 55ebd12561f803f3caff4beb6f6b992069ec7853 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Mon, 22 Jun 2020 12:31:29 -0700 Subject: [PATCH 09/58] Revert added null check in 'fetch a modulepreload module script graph'; I'll add this in a separate PR. --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 97420a32059..18a58a9c7d5 100644 --- a/source +++ b/source @@ -86858,7 +86858,7 @@ interface ApplicationCache : EventTarget { these steps.

        18. -

          If result is not null, optionally perform the following steps:

          +

          Optionally, perform the following steps:

          1. Let visited set be « url ».

          2. From af41b281a413b697296d1ee1f1c0cc036dc47509 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Mon, 22 Jun 2020 13:16:58 -0700 Subject: [PATCH 10/58] Reference ParseJSONModule from import-attributes proposal instead of defining steps in HTML spec --- source | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/source b/source index 18a58a9c7d5..ca4dd18761e 100644 --- a/source +++ b/source @@ -2635,8 +2635,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
          3. converting to a sequence of Unicode scalar values
          4. overload resolution algorithm
          5. -
          6. CreateSyntheticModule
          7. -
          8. SetSyntheticModuleExport
          9. Synthetic Module Record
          10. exposed
          11. [LegacyFactoryFunction]
          12. @@ -2858,11 +2856,12 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

            User agents that support JavaScript must also implement the import attributes - proposal. The following term is defined there, and used in this specification:

            • The ModuleRequest Record specification type
            • +
            • The ParseJSONModule abstract operation

            Users agents that support JavaScript must also implement ECMAScript @@ -87585,37 +87584,18 @@ interface ApplicationCache : EventTarget { error to rethrow to null.

          13. -

            Let json be ? Call(%JSON.Parse%, undefined, - « source »).

            +

            Let result be ParseJSONModule(source).

            If this throws an exception, set script's parse error to that exception, and return script.

          14. -
          15. Set script's record to the result - of creating a synthetic - module record with a default export of json with settings.

          16. +
          17. Set script's record to result.

          18. Return script.

          -

          To create a synthetic module record with a default export of a JavaScript value - value with an environment settings object settings:

          - -
            -
          1. -

            Return CreateSyntheticModule(« "default" », the following steps, - settings's Realm, - value) with the following steps given module as an argument:

            - -
              -
            1. SetSyntheticModuleExport(module, "default", - module.[[HostDefined]]).
            2. -
            -
          2. -
          -
          Calling scripts

          To run a classic script given a classic script From a2d42607ad7241e9ce4827d2e3224035305582ca Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 23 Jun 2020 10:13:45 -0700 Subject: [PATCH 11/58] Cache an entry in the module map if the fetched module was valid but does not match the type specified at the import site. --- source | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/source b/source index ca4dd18761e..b5b03d8c56e 100644 --- a/source +++ b/source @@ -87319,14 +87319,14 @@ interface ApplicationCache : EventTarget {

          If the resource does not have a MIME type which HTML knows how to handle as a module or if the MIME type does not match the type specified in moduleRequest, - then module script will remain null, which is interpreted as failure.

          + then this algorithm will complete with null, which is interpreted as failure.

          In the former case where a non-module MIME type is received, a null entry is added to moduleMap so that future attempts to fetch a module at url will always fail. On the other hand for the case where the MIME type is valid but does not match the - requested module type, nothing is cached in moduleMap, meaning that - future attempts to fetch the same url in another module graph could succeed if the correct - type were specified.

          + requested module type, module script is cached in moduleMap, + meaning that future attempts to fetch the same url in another module graph could succeed if the + correct type were specified, without triggering another network request.

        19. @@ -87334,9 +87334,6 @@ interface ApplicationCache : EventTarget {

          If MIME type is a JavaScript MIME type, then:

            -
          1. If the module type must match flag is set and module type is not - undefined, asynchronously complete this algorithm with null, and abort these steps.

          2. -
          3. Let source text be the result of UTF-8 decoding response's body.

          4. @@ -87350,10 +87347,6 @@ interface ApplicationCache : EventTarget {
          5. If MIME type is a JSON MIME type, then:

              -
            1. If the module type must match flag is set and module type is not - "json", asynchronously complete this algorithm with null, and abort - these steps.

            2. -
            3. Let source text be the result of UTF-8 decoding response's body.

            4. @@ -87364,7 +87357,7 @@ interface ApplicationCache : EventTarget {
            5. Set moduleMap[url] to module - script, and asynchronously complete this algorithm with module script.

              + script

              It is intentional that the module map is keyed by the request URL, whereas the ApplicationCache : EventTarget { set to the response URL. The former is used to deduplicate fetches, while the latter is used for URL resolution.

            6. + + +
            7. +

              If any of the following conditions are met, asynchronously complete this algorithm + with module script.

              + +
                +
              • The module type must match flag is unset.

              • + +
              • module script is a JavaScript module script + and module type is undefined.

              • + +
              • module script is a JSON module script + and module type is "json".

              • +
              + +

              Otherwise, asynchronously complete this algorithm with null.

              +
            8. +

            To find the first parse error given a root From f79c01f2a77f1ccaf9d4aa68da70b1eedac251fe Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 23 Jun 2020 11:02:38 -0700 Subject: [PATCH 12/58] Extend note to be clear that the module must have no effect until a request matches its type and it is evalutated --- source | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source b/source index b5b03d8c56e..6c5d18e19b4 100644 --- a/source +++ b/source @@ -87326,7 +87326,10 @@ interface ApplicationCache : EventTarget { fail. On the other hand for the case where the MIME type is valid but does not match the requested module type, module script is cached in moduleMap, meaning that future attempts to fetch the same url in another module graph could succeed if the - correct type were specified, without triggering another network request.

            + requested type matched the MIME type, without triggering another network request. An important + detail of this process is that parsing a module and inserting it into the module map is + side-effect-free, so a module will have no observable effect until it is evaluated, which can + only happen after the type is matched.

          6. From 7c900a18f32788de774d043cb1f11e2af06c3d1f Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 25 Jun 2020 16:23:35 -0700 Subject: [PATCH 13/58] When a valid MIME type is received that doesn't match the requested type, cache the fetch response instead of creating and caching the module script. The module script is created only when there is a type match. This addreses concerns that parsing modules (perhaps even types of modules that don't yet exist) could have side-effects. --- source | 216 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 109 insertions(+), 107 deletions(-) diff --git a/source b/source index 6c5d18e19b4..4640f9387f1 100644 --- a/source +++ b/source @@ -86791,10 +86791,10 @@ interface ApplicationCache : EventTarget {
            1. Fetch a single module script given url, settings object, "script", options, settings object, - "client", with the module type must match flag set, 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.

            2. + "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. If result is null, asynchronously complete this algorithm with null, and abort these steps.

            4. @@ -86823,11 +86823,10 @@ interface ApplicationCache : EventTarget {
            5. Fetch a single module script given url, settings object, "script", options, settings object, - "client", moduleRequest, with the module type must - match flag set, 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.

            6. + "client", moduleRequest, 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.

            7. If result is null, asynchronously complete this algorithm with null, and abort these steps.

            8. @@ -86849,9 +86848,8 @@ interface ApplicationCache : EventTarget {
              1. Fetch a single module script given url, settings object, destination, options, settings object, "client", with the module type must match flag unset, and with the - top-level module fetch flag set. Wait until algorithm asynchronously completes with - result.

              2. + data-x="">client", and with the top-level module fetch flag set. Wait until + algorithm asynchronously completes with result.

              3. Asynchronously complete this algorithm with result, but do not abort these steps.

              4. @@ -86915,10 +86913,10 @@ interface ApplicationCache : EventTarget {
              5. Fetch a single module script given url, fetch client settings object, destination, options, module map settings object, - "client", with the module type must match flag set, 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.

              6. + "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.

              7. If result is null, asynchronously complete this algorithm with null, and abort these steps.

              8. @@ -87183,11 +87181,10 @@ interface ApplicationCache : EventTarget {
              9. Fetch a single module script given url, fetch client settings object, destination, options, module map settings object, - referrer, moduleRequest, with the module type must match flag - set, and with the top-level module fetch flag unset. If the caller of this algorithm - specified custom perform the fetch steps, - pass those along while fetching a single module - script.

                + referrer, moduleRequest, and with the + top-level module fetch flag unset. If the caller of this algorithm specified custom + perform the fetch steps, pass those along + while fetching a single module script.

              10. Return from this algorithm, and run the following steps when fetching a single module script asynchronously completes with @@ -87206,10 +87203,9 @@ interface ApplicationCache : EventTarget {

                To fetch a single module script, given a url, a fetch client settings object, a destination, some options, a module map - settings object, a referrer, an optional moduleRequest, a - module type must match flag, and a top-level module fetch flag, run these - steps. The algorithm will asynchronously complete with either null (on failure) or a - module script (on success).

                + settings object, a referrer, an optional moduleRequest, and a + top-level module fetch flag, run these steps. The algorithm will asynchronously + complete with either null (on failure) or a module script (on success).

                1. @@ -87229,29 +87225,15 @@ interface ApplicationCache : EventTarget { in parallel until that entry's value changes, then queue a task on the networking task source to proceed with running the following steps.

                2. -
                3. -

                  If moduleMap[url] exists, then:

                  - -
                    -
                  1. -

                    If any of the following conditions are met, asynchronously complete this algorithm - with moduleMap[url], and abort these steps.

                    +
                  2. If moduleMap[url] is a fetch response, then asynchronously complete this algorithm with the + result of creating a module script + with matching type given url, requested type, + moduleMap[url], options, and module map settings + object, and abort these steps.

                  3. -
                      -
                    • The module type must match flag is unset.

                    • - -
                    • moduleMap[url] is a JavaScript module script - and module type is undefined.

                    • - -
                    • moduleMap[url] is a JSON module script - and module type is "json".

                    • -
                    - - -
                  4. Otherwise, asynchronously complete this algorithm with null, and abort these steps.

                    -
                  5. -
                  -
                4. +
                5. If moduleMap[url] is null, asynchronously complete this algorithm + with null, and abort these steps.

                6. Set moduleMap[url] to "fetching".

                  @@ -87299,94 +87281,113 @@ interface ApplicationCache : EventTarget {
                7. response's status is not an ok status

                8. - - -
                9. -

                  Let MIME type be the result of extracting a - MIME type from response's header - list.

                  +
                10. +

                  The result of extracting a + MIME type from response's header + list is neither a JavaScript MIME type nor a JSON MIME type. +

                  -

                  For historical reasons, fetching a - classic script does not include MIME type checking. In contrast, module scripts' - interpretation is driven by their MIME type, and they will fail to load if they are not of - a supported MIME type.

                  +
                  +

                  For historical reasons, fetching a + classic script does not include MIME type checking.

                  + +

                  In contrast, module scripts' interpretation is driven by their MIME type, and they will + fail to load if they are not of a supported MIME type. If the resource does not have a MIME + type which HTML knows how to handle as a module then this algorithm will complete with null, + which is interpreted as failure, and a null entry is added to moduleMap so that + future attempts to fetch a module at url will always fail.

                  +
                  +
                11. +
                12. -

                  Let module script be null.

                  +

                  Set moduleMap[url] to + response.

                  -

                  If the resource does not have a MIME type which HTML knows how to handle - as a module or if the MIME type does not match the type specified in moduleRequest, - then this algorithm will complete with null, which is interpreted as failure.

                  - -

                  In the former case where a non-module MIME type is received, a null entry is added to - moduleMap so that future attempts to fetch a module at url will always - fail. On the other hand for the case where the MIME type is valid but does not match the - requested module type, module script is cached in moduleMap, - meaning that future attempts to fetch the same url in another module graph could succeed if the - requested type matched the MIME type, without triggering another network request. An important - detail of this process is that parsing a module and inserting it into the module map is - side-effect-free, so a module will have no observable effect until it is evaluated, which can - only happen after the type is matched.

                  +

                  If the MIME type is valid but does not match the requested module type, then + create a module script with matching type will fail and response will + remain cached in the module map. Then, future attempts to fetch the same url in + another module graph could succeed if the requested type matched the MIME type, without + triggering another network request. Caching response instead of creating and + caching a module script at this point is done to ensure that no side-effects occur until there + is a type match.

                  + +

                  If requested type does turn out to match the MIME type then create a module + script with matching type will create a module script and overwrite this module + map entry with it.

                13. +
                14. Asychronously complete this algorithm with the result of creating a module script with matching + type given url, requested type, response, + options, and module map settings object.

                15. +
                + +

                To create a module script with matching type, given a url, a + requested type, a fetch response + response, some options, and module map settings object, + run these steps. The algorithm will complete with either null (on failure) or a + module script (on success).

                + +
                  +
                1. Let module script be null.

                2. + +
                3. Let MIME type be the result of extracting a + MIME type from response's header + list.

                4. +
                5. -

                  If MIME type is a JavaScript MIME type, then:

                  +

                  If MIME type is a JavaScript MIME type and module type is + undefined, then:

                  -
                    +
                    • Let source text be the result of UTF-8 - decoding response's body.

                    • + decoding response's body.

                      +
                    • Set module script to the result of creating a JavaScript module - script given source text, module map settings object, + script given source, module map settings object, response's url, and options.

                    • -
                  +
                6. -

                  If MIME type is a JSON MIME type, then:

                  -
                    +

                    If MIME type is a JSON MIME type and module type is + "json", then:

                    + +
                    • Let source text be the result of UTF-8 - decoding response's body.

                    • + decoding response's body.

                      +
                    • Set module script to the result of creating a JSON module script given source text and module map settings object.

                    • -
                  -
                7. - -
                8. -

                  Set moduleMap[url] to module - script

                  - -

                  It is intentional that the module map is keyed by the request URL, whereas the base URL for the module script is - set to the response URL. The former is used to - deduplicate fetches, while the latter is used for URL resolution.

                  +
                9. -
                10. -

                  If any of the following conditions are met, asynchronously complete this algorithm - with module script.

                  - -
                    -
                  • The module type must match flag is unset.

                  • +

                    If module script is not null, then:

                    -
                  • module script is a JavaScript module script - and module type is undefined.

                  • +
                      +
                    1. Let moduleMap be module map settings object's module map.

                    2. -
                    3. module script is a JSON module script - and module type is "json".

                    4. -
                  +
                11. Set moduleMap[url] to module script.

                12. -

                  Otherwise, asynchronously complete this algorithm with null.

                  +

                  It is intentional that the module map is keyed by the request URL, whereas the base URL for the module script is + set to the response URL. The former is used to + deduplicate fetches, while the latter is used for URL resolution.

                  +
              11. +
              12. Return module script.

              To find the first parse error given a root @@ -88572,10 +88573,11 @@ document.querySelector("button").addEventListener("click", bound);

              A module map is a map of URL records to values that are either a module script, - null (used to represent failed fetches), or a placeholder value "fetching". Module maps are used to ensure - that imported JavaScript modules are only fetched, parsed, and evaluated once per - Document or worker.

              + null (used to represent failed fetches), a placeholder value "fetching", or a fetch response. + Module maps are used to ensure that imported JavaScript modules + are only fetched, parsed, and evaluated once per Document or worker.

              Since module maps are keyed by URL, the following code will From 55c9ed9bef7b43175624858d1e1fd0d130231789 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 26 Jun 2020 10:32:08 -0700 Subject: [PATCH 14/58] Wrap

              in

            9. so it's not directly under an
                , which the Travis CI build doesn't like. --- source | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source b/source index 4640f9387f1..468b9b51647 100644 --- a/source +++ b/source @@ -87377,13 +87377,15 @@ interface ApplicationCache : EventTarget {
              1. Let moduleMap be module map settings object's module map.

              2. -
              3. Set moduleMap[url] to module script.

              4. +
              5. +

                Set moduleMap[url] to module script.

                -

                It is intentional that the module map is keyed by the request URL, whereas the base URL for the module script is - set to the response URL. The former is used to - deduplicate fetches, while the latter is used for URL resolution.

                +

                It is intentional that the module map is keyed by the request URL, whereas the base URL for the module script is + set to the response URL. The former is used to + deduplicate fetches, while the latter is used for URL resolution.

                +
            10. From 322808d4415dba48746c93c0030a9cab2f91baed Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 26 Jun 2020 14:37:25 -0700 Subject: [PATCH 15/58] Whitespace change: remove double spaces after sentences in notes. Hopefully unstick CI build, which seems to be stuck. --- source | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source b/source index 468b9b51647..c1ea9a27c0b 100644 --- a/source +++ b/source @@ -87293,7 +87293,7 @@ interface ApplicationCache : EventTarget { classic script does not include MIME type checking.

              In contrast, module scripts' interpretation is driven by their MIME type, and they will - fail to load if they are not of a supported MIME type. If the resource does not have a MIME + fail to load if they are not of a supported MIME type. If the resource does not have a MIME type which HTML knows how to handle as a module then this algorithm will complete with null, which is interpreted as failure, and a null entry is added to moduleMap so that future attempts to fetch a module at url will always fail.

              @@ -87309,9 +87309,9 @@ interface ApplicationCache : EventTarget {

              If the MIME type is valid but does not match the requested module type, then create a module script with matching type will fail and response will - remain cached in the module map. Then, future attempts to fetch the same url in + remain cached in the module map. Then, future attempts to fetch the same url in another module graph could succeed if the requested type matched the MIME type, without - triggering another network request. Caching response instead of creating and + triggering another network request. Caching response instead of creating and caching a module script at this point is done to ensure that no side-effects occur until there is a type match.

              From 9f2ae27b45760d696faf2c73c324ea7774df783b Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 30 Jun 2020 10:35:57 -0700 Subject: [PATCH 16/58] Reword invocations of 'create a module script with matching type' to ensure they are synchronous with respect to the calling 'fetch a single module script' --- source | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/source b/source index c0232218d4f..f1b961e0853 100644 --- a/source +++ b/source @@ -88807,11 +88807,11 @@ document.querySelector("button").addEventListener("click", bound); the networking task source to proceed with running the following steps.

            11. If moduleMap[url] is a fetch response, then asynchronously complete this algorithm with the - result of creating a module script - with matching type given url, requested type, + data-x="concept-response">response, then create a module script with matching + type given url, requested type, moduleMap[url], options, and module map settings - object, and abort these steps.

            12. + object, asynchronously complete this algorithm with the result, and abort these steps.

              +
            13. If moduleMap[url] is null, asynchronously complete this algorithm with null, and abort these steps.

            14. @@ -88902,13 +88902,11 @@ document.querySelector("button").addEventListener("click", bound);
              -
            15. Asychronously complete this algorithm with the result of creating a module script with matching - type given url, requested type, response, - options, and module map settings object.

            16. +
            17. Create a module script with matching type given url, + requested type, response, options, and module map settings + object, and asychronously complete this algorithm with the result.

            -

            To create a module script with matching type, given a url, a requested type, a fetch response response, some options, and module map settings object, From e86dd65581b26f9eb7a8c40f4f449247b6f66525 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 30 Jun 2020 12:15:38 -0700 Subject: [PATCH 17/58] Change 'fetch a single module script' to fail if there are any unrecognized import attributes, and assert that there is only one of key 'type' (which should be guaranteed by Ecma262) --- source | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/source b/source index f1b961e0853..39a2d05ab51 100644 --- a/source +++ b/source @@ -88789,11 +88789,25 @@ document.querySelector("button").addEventListener("click", bound); complete with either null (on failure) or a module script (on success).

              +
            1. Let module type be undefined.

            2. +
            3. -

              If moduleRequest was given and if moduleRequest.[[Attributes]] - has a Record entry such that entry.[[Key]] is - "type", then let module type be entry.[[Value]]

              -

              Otherwise let module type be undefined.

              +

              If moduleRequest was given, then:

              + +
                +
              1. If moduleRequest.[[Attributes]] has any Record entry + such that entry.[[Key]] is not "type", then asynchronously + complete this algorithm with null, and + abort these steps.

              2. + +
              3. +

                If moduleRequest.[[Attributes]] has a Record entry such + that entry.[[Key]] is "type", then set module + type to entry.[[Value]].

                + +

                Assert: No more than one such Record exists.

                +
              4. +
            4. If module type is neither undefined nor "json", From 3318ed318a1a82f5011e0504f7526efc304375cc Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 7 Jul 2020 16:40:55 -0700 Subject: [PATCH 18/58] Instead of passing fetch response parameter to 'create a module script with matching type', retrieve it from the module map within the algorithm. --- source | 56 +++++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/source b/source index 39a2d05ab51..bf1f622c4e7 100644 --- a/source +++ b/source @@ -88822,10 +88822,9 @@ document.querySelector("button").addEventListener("click", bound);

            5. If moduleMap[url] is a fetch response, then create a module script with matching - type given url, requested type, - moduleMap[url], options, and module map settings - object, asynchronously complete this algorithm with the result, and abort these steps.

              -
            6. + type given url, requested type, options, and + module map settings object, asynchronously complete this algorithm with the result, + and abort these steps.

            7. If moduleMap[url] is null, asynchronously complete this algorithm with null, and abort these steps.

            8. @@ -88917,19 +88916,26 @@ document.querySelector("button").addEventListener("click", bound);
            9. Create a module script with matching type given url, - requested type, response, options, and module map settings + requested type, options, and module map settings object, and asychronously complete this algorithm with the result.

            To create a module script with matching type, given a url, a - requested type, a fetch response - response, some options, and module map settings object, + requested type, some options, and module map settings object, run these steps. The algorithm will complete with either null (on failure) or a module script (on success).

            1. Let module script be null.

            2. +
            3. Let moduleMap be module map settings object's module map.

            4. + +
            5. Let response be moduleMap[url].

            6. + +
            7. Assert: response is a fetch response.

              +

            8. +
            9. Let MIME type be the result of extracting a MIME type from response's header list.

            10. @@ -88943,10 +88949,18 @@ document.querySelector("button").addEventListener("click", bound); decoding response's body.

              -
            11. Set module script to the result of creating a JavaScript module - script given source, module map settings object, - response's url, and - options.

            12. +
            13. +

              Set module script to the result of creating a JavaScript module + script given source, module map settings object, + response's url, and + options.

              + +

              It is intentional that the module map is keyed by the request URL, whereas the base URL for the JavaScript module script + is set to the response URL. The former is used to + deduplicate fetches, while the latter is used for URL resolution.

              +
            14. @@ -88964,24 +88978,8 @@ document.querySelector("button").addEventListener("click", bound); -
            15. -

              If module script is not null, then:

              - -
                -
              1. Let moduleMap be module map settings object's module map.

              2. - -
              3. -

                Set moduleMap[url] to module script.

                - -

                It is intentional that the module map is keyed by the request URL, whereas the base URL for the module script is - set to the response URL. The former is used to - deduplicate fetches, while the latter is used for URL resolution.

                -
              4. -
              -
            16. +
            17. If module script is not null, then set moduleMap[url] to + module script

            18. Return module script.

            From 3c0dce2d2db9abdd4932f8e7e3d19c0d6f42e8b9 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 7 Jul 2020 16:56:32 -0700 Subject: [PATCH 19/58] Add assert that 'create a module script with matching type' is not running in parallel --- source | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source b/source index bf1f622c4e7..2a8d738d675 100644 --- a/source +++ b/source @@ -88926,6 +88926,9 @@ document.querySelector("button").addEventListener("click", bound); module script (on success).

              +
            1. Assert: These steps are running on the event loop, not + in parallel.

            2. +
            3. Let module script be null.

            4. Let moduleMap be module map settings object's Date: Wed, 8 Jul 2020 11:20:45 -0700 Subject: [PATCH 20/58] Reword caching comment --- source | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/source b/source index 2a8d738d675..ba04d1d893f 100644 --- a/source +++ b/source @@ -88903,11 +88903,12 @@ document.querySelector("button").addEventListener("click", bound);

              If the MIME type is valid but does not match the requested module type, then create a module script with matching type will fail and response will - remain cached in the module map. Then, future attempts to fetch the same url in - another module graph could succeed if the requested type matched the MIME type, without - triggering another network request. Caching response instead of creating and - caching a module script at this point is done to ensure that no side-effects occur until there - is a type match.

              + remain cached in the module map. Future attempts to fetch the same url in another + module graph could succeed, without triggering another network request, if the requested type + matched the MIME type.

              + +

              Caching response instead of creating and caching a module script at this point is + done to ensure that no side-effects occur until there is a type match.

              If requested type does turn out to match the MIME type then create a module script with matching type will create a module script and overwrite this module From 3247e99275b9fbeb97c957a7f9b779c72fba6bf6 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 9 Jul 2020 14:10:10 -0700 Subject: [PATCH 21/58] Handle rename in TC39 proposal from import attributes to import conditions --- source | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/source b/source index ba04d1d893f..8e123402d7d 100644 --- a/source +++ b/source @@ -2869,13 +2869,13 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

            5. The HostGetImportMetaProperties abstract operation
            6. -

              User agents that support JavaScript must also implement the import attributes - proposal. The following terms are defined there, and used in this specification:

              +

              User agents that support JavaScript must also implement the import conditions + proposal. The following terms are defined there, and used in this specification:

                -
              • The ModuleRequest Record specification type
              • -
              • The ParseJSONModule abstract operation
              • +
              • The ModuleRequest Record specification type
              • +
              • The ParseJSONModule abstract operation

              Users agents that support JavaScript must also implement ECMAScript @@ -88795,13 +88795,12 @@ document.querySelector("button").addEventListener("click", bound);

              If moduleRequest was given, then:

                -
              1. If moduleRequest.[[Attributes]] has any Record entry +

              2. If moduleRequest.[[Conditions]] has any Record entry such that entry.[[Key]] is not "type", then asynchronously - complete this algorithm with null, and - abort these steps.

              3. + complete this algorithm with null, and abort these steps.

              4. -

                If moduleRequest.[[Attributes]] has a Record entry such +

                If moduleRequest.[[Conditions]] has a Record entry such that entry.[[Key]] is "type", then set module type to entry.[[Value]].

                @@ -121876,8 +121875,8 @@ INSERT INTERFACES HERE
                [JSERRORSTACKS]
                (Non-normative) Error Stacks. Ecma International.
                -
                [JSIMPORTATTRIBUTES]
                -
                Import Attributes. Ecma International.
                +
                [JSIMPORTCONDITIONS]
                +
                Import Conditions. Ecma International.
                [JSIMPORTMETA]
                import.meta. Ecma International.
                From dca376bb5aa947d032424715a61429702232cab8 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 24 Jul 2020 10:42:51 -0700 Subject: [PATCH 22/58] Update for the latest rename of the proposal from 'Import Conditions' to 'Import Assertions' --- source | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source b/source index 8e123402d7d..a359f0af886 100644 --- a/source +++ b/source @@ -2869,13 +2869,13 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
              5. The HostGetImportMetaProperties abstract operation
              6. -

                User agents that support JavaScript must also implement the import conditions +

                User agents that support JavaScript must also implement the import assertions proposal. The following terms are defined there, and used in this specification:

                + spec=JSIMPORTASSERTIONS>

                  -
                • The ModuleRequest Record specification type
                • -
                • The ParseJSONModule abstract operation
                • +
                • The ModuleRequest Record specification type
                • +
                • The ParseJSONModule abstract operation

                Users agents that support JavaScript must also implement ECMAScript @@ -88795,12 +88795,12 @@ document.querySelector("button").addEventListener("click", bound);

                If moduleRequest was given, then:

                  -
                1. If moduleRequest.[[Conditions]] has any Record entry +

                2. If moduleRequest.[[Assertions]] has any Record entry such that entry.[[Key]] is not "type", then asynchronously complete this algorithm with null, and abort these steps.

                3. -

                  If moduleRequest.[[Conditions]] has a Record entry such +

                  If moduleRequest.[[Assertions]] has a Record entry such that entry.[[Key]] is "type", then set module type to entry.[[Value]].

                  @@ -121875,8 +121875,8 @@ INSERT INTERFACES HERE
                  [JSERRORSTACKS]
                  (Non-normative) Error Stacks. Ecma International.
                  -
                  [JSIMPORTCONDITIONS]
                  -
                  Import Conditions. Ecma International.
                  +
                  [JSIMPORTASSERTIONS]
                  +
                  Import Assertions. Ecma International.
                  [JSIMPORTMETA]
                  import.meta. Ecma International.
                  From e3359b5f4d4d19993552dd577a62a2b5f125f64d Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Mon, 27 Jul 2020 10:00:12 -0700 Subject: [PATCH 23/58] Use module type as part of module map cache key instead of caching response body in the case of a failed type check. --- source | 213 ++++++++++++++++++++++----------------------------------- 1 file changed, 81 insertions(+), 132 deletions(-) diff --git a/source b/source index a359f0af886..9637fffe52e 100644 --- a/source +++ b/source @@ -2192,6 +2192,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
                4. surrogate
                5. scalar value
                6. tuple
                7. +
                8. pair
                9. noncharacter
                10. string, code unit, @@ -88815,21 +88816,16 @@ document.querySelector("button").addEventListener("click", bound);
                11. Let moduleMap be module map settings object's module map.

                12. -
                13. If moduleMap[url] 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.

                14. +
                15. If moduleMap[url / module type] 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.

                16. -
                17. If moduleMap[url] is a fetch response, then create a module script with matching - type given url, requested type, options, and - module map settings object, asynchronously complete this algorithm with the result, - and abort these steps.

                18. - -
                19. If moduleMap[url] is null, asynchronously complete this algorithm - with null, and abort these steps.

                20. +
                21. If moduleMap[url / module type] is null, asynchronously + complete this algorithm with null, and abort these steps.

                22. -
                23. Set moduleMap[url] to "fetching".

                  +
                24. Set moduleMap[url / + module type] to "fetching".

                25. Let request be a new request whose url is url,

                26. -

                  If any of the following conditions are met, set +

                  If either of the following conditions are met, set moduleMap[url] to null, asynchronously complete this algorithm with null, and abort these steps:

                  @@ -88874,117 +88870,53 @@ document.querySelector("button").addEventListener("click", bound);
                27. response's status is not an ok status

                28. - -
                29. -

                  The result of extracting a - MIME type from response's header - list is neither a JavaScript MIME type nor a JSON MIME type. -

                  - -
                  -

                  For historical reasons, fetching a - classic script does not include MIME type checking.

                  - -

                  In contrast, module scripts' interpretation is driven by their MIME type, and they will - fail to load if they are not of a supported MIME type. If the resource does not have a MIME - type which HTML knows how to handle as a module then this algorithm will complete with null, - which is interpreted as failure, and a null entry is added to moduleMap so that - future attempts to fetch a module at url will always fail.

                  -
                  -
                30. -

                  Set moduleMap[url] to - response.

                  +

                  Let MIME type be the result of extracting a + MIME type from response's header + list.

                  -

                  If the MIME type is valid but does not match the requested module type, then - create a module script with matching type will fail and response will - remain cached in the module map. Future attempts to fetch the same url in another - module graph could succeed, without triggering another network request, if the requested type - matched the MIME type.

                  - -

                  Caching response instead of creating and caching a module script at this point is - done to ensure that no side-effects occur until there is a type match.

                  - -

                  If requested type does turn out to match the MIME type then create a module - script with matching type will create a module script and overwrite this module - map entry with it.

                  +

                  For historical reasons, fetching a + classic script does not include MIME type checking.

                  + +

                  In contrast, module scripts' interpretation is driven by their MIME type, and they will + fail to load if they are not of a supported MIME type. If the resource does not have a MIME + type which HTML knows how to handle as a module then this algorithm will complete with null, + which is interpreted as failure, and a null entry is added to moduleMap so that + future attempts to fetch a module at url will always fail.

                31. -
                32. Create a module script with matching type given url, - requested type, options, and module map settings - object, and asychronously complete this algorithm with the result.

                33. -
                - -

                To create a module script with matching type, given a url, a - requested type, some options, and module map settings object, - run these steps. The algorithm will complete with either null (on failure) or a - module script (on success).

                - -
                  -
                1. Assert: These steps are running on the event loop, not - in parallel.

                2. +
                3. Let source text be the result of UTF-8 + decoding response's body.

                4. Let module script be null.

                5. -
                6. Let moduleMap be module map settings object's module map.

                7. - -
                8. Let response be moduleMap[url].

                9. - -
                10. Assert: response is a fetch response.

                  +

                11. If MIME type is a JavaScript MIME type and module type + is undefined, then set module script to the result of creating a JavaScript + module script given source text, module map settings object, + response's url, and options.

                12. -
                13. Let MIME type be the result of extracting a - MIME type from response's header - list.

                14. - -
                15. -

                  If MIME type is a JavaScript MIME type and module type is - undefined, then:

                  - -
                    -
                  • Let source text be the result of UTF-8 - decoding response's body.

                    -
                  • - -
                  • -

                    Set module script to the result of creating a JavaScript module - script given source, module map settings object, - response's url, and - options.

                    - -

                    It is intentional that the module map is keyed by the request URL, whereas the base URL for the JavaScript module script - is set to the response URL. The former is used to - deduplicate fetches, while the latter is used for URL resolution.

                    -
                  • -
                  -
                16. +
                17. If MIME type is a JSON MIME type and module type is + "json", then set module script to the result of creating + a JSON module script given source text and module map settings + object.

                18. -

                  If MIME type is a JSON MIME type and module type is - "json", then:

                  - -
                    -
                  • Let source text be the result of UTF-8 - decoding response's body.

                    -
                  • +

                    Set moduleMap[url / + module type] to module script, and asynchronously complete this algorithm + with module script.

                    -
                  • Set module script to the result of creating a JSON module - script given source text and module map settings object.

                  • -
                  +

                  It is intentional that the module map is keyed by the request URL, whereas the base URL for the module script is + set to the response URL. The former is used to + deduplicate fetches, while the latter is used for URL resolution.

                19. - -
                20. If module script is not null, then set moduleMap[url] to - module script

                  - -
                21. Return module script.

                To find the first parse error given a root @@ -89011,22 +88943,25 @@ document.querySelector("button").addEventListener("click", bound);

              7. Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

              8. -
              9. Let childURLs be the list obtained by calling - resolve a module specifier once for each item moduleRequest of - moduleRequest, given moduleScript's base URL and moduleRequest.[[Specifier]]. - (None of these will ever fail, as otherwise moduleScript would have been marked as - itself having a parse error.)

              10. - -
              11. Let childModules be the list obtained by getting each value in moduleMap whose key is given by an - item of childURLs.

              12. -
              13. -

                For each childModule of - childModules:

                +

                For each moduleRequest of + moduleRequests:

                  +
                1. Let childURL be the result of resolving a module specifier given + moduleScript's base URL and + moduleRequest.[[Specifier]]. (This will never fail, as otherwise + moduleScript would have been marked as itself having a parse error.)

                2. + +
                3. If moduleRequest.[[Assertions]] has a Record entry + such that entry.[[Key]] is "type", then let module + type be entry.[[Value]]. Otherwise let module type be undefined. +

                4. + +
                5. Let childModule be moduleMap[childURL / + module type].

                6. +
                7. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module scripts in the graph rooted at moduleScript will have successfully been @@ -89921,18 +89856,18 @@ dictionary PromiseRejectionEventInit : EventInit { -

                  A module map is a map of URL records to values that are either a module script, - null (used to represent failed fetches), a placeholder value "fetching", or a fetch response. - Module maps are used to ensure that imported JavaScript modules - are only fetched, parsed, and evaluated once per Document or worker.

                  +

                  A module map is a map keyed by + URL record / module type string pairs whose values are + either a module script, null (used to represent failed fetches), or a placeholder + value "fetching". Module maps are + used to ensure that imported JavaScript modules are only fetched, parsed, and evaluated once per + Document or worker.

                  -

                  Since module maps are keyed by URL, the following code will - create three separate entries in the module map, since it results in three different - URLs:

                  +

                  Since module maps are keyed by URL / module type, the + following code will create three separate entries in the module map, since it + results in three different URL/module type pairs (all with null type): +

                  import "https://example.com/module.mjs";
                   import "https://example.com/module.mjs#map-buster";
                  @@ -89957,6 +89892,15 @@ import "https://example.com/foo/../module2.mjs";

                  Note that this behavior is the same as how shared workers are keyed by their parsed constructor url.

                  + +

                  Since module type is also part of the module map key, the following code will + create two separate entries in the module map (the type is undefined for the first, + and "json" for the second): + +

                  import "https://example.com/module.json";
                  +import "https://example.com/module.json" assert { type: "json" };
                  + +

                  Therefore two separate fetches and two separate module evaluations will be performed.

                  @@ -90194,8 +90138,13 @@ import "https://example.com/foo/../module2.mjs"; same two arguments (either while creating the corresponding module script, or in HostImportModuleDynamically).

                8. -
                9. Let resolved module script be moduleMap[url]. (This entry - must exist for us to have gotten to this point.)

                10. +
                11. If moduleRequest.[[Assertions]] has a Record entry such + that entry.[[Key]] is "type", then let module type + be entry.[[Value]]. Otherwise let module type be undefined.

                12. + +
                13. Let resolved module script be moduleMap[url / + module type]. (This entry must exist for us to have + gotten to this point.)

                14. Assert: resolved module script is a module script (i.e., is not null or "fetching").

                15. From aafb25692ce430cc380230f43cf085ec112afbfd Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 27 Aug 2020 14:19:32 -0700 Subject: [PATCH 24/58] Change 'abort these steps' to 'return' to match recent changes in 'fetch a single module script'. --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 4f602536fc6..6017f8f65fc 100644 --- a/source +++ b/source @@ -89627,7 +89627,7 @@ document.querySelector("button").addEventListener("click", bound);
                  1. If moduleRequest.[[Assertions]] has any Record entry such that entry.[[Key]] is not "type", then asynchronously - complete this algorithm with null, and abort these steps.

                  2. + complete this algorithm with null, and return.

                  3. If moduleRequest.[[Assertions]] has a Record entry such From 9164acf16e14c0e715f7b7269959217e76a31c91 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 28 Aug 2020 16:02:35 -0700 Subject: [PATCH 25/58] Remove JSON modules references, switch JavaScript module script references back to just 'module script' --- source | 366 +++++++++++++++++---------------------------------------- 1 file changed, 111 insertions(+), 255 deletions(-) diff --git a/source b/source index 6017f8f65fc..251697ab967 100644 --- a/source +++ b/source @@ -2657,7 +2657,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

                  4. converting to a sequence of Unicode scalar values
                  5. overload resolution algorithm
                  6. -
                  7. Synthetic Module Record
                  8. exposed
                  9. [LegacyFactoryFunction]
                  10. [LegacyLenientThis]
                  11. @@ -2874,12 +2873,11 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute Internationalization API.

                    User agents that support JavaScript must also implement the import assertions - proposal. The following terms are defined there, and used in this specification:

                    • The ModuleRequest Record specification type
                    • -
                    • The ParseJSONModule abstract operation
                    @@ -57386,14 +57384,11 @@ interface HTMLScriptElement : HTMLElement { redundantly setting it.

                  12. Setting the attribute to an ASCII case-insensitive match for the string - "module" means that the script is a module script. If it has - a JavaScript MIME type, or if the script is embedded inline, then it will be - interpreted as a JavaScript module script according to the JavaScript Module top-level production; if it has a JSON MIME - type, then it will be interpreted as a JSON module script. Module scripts - are not affected by the defer attribute, but are - affected by the async attribute (regardless of the state - of the src attribute).

                  13. + "module" means that the script is a module script, to be + interpreted according to the JavaScript Module top-level + production. Module scripts are not affected by the defer + attribute, but are affected by the async attribute + (regardless of the state of the src attribute).

                  14. Setting the attribute to any other value means that the script is a data block, which is not processed. None of the script attributes (except HTMLScriptElement : HTMLElement { scripts. By using a valid MIME type string now, you ensure that your data block will not ever be reinterpreted as a different script type, even in future user agents.

                    -

                    Classic scripts and JavaScript module scripts can be embedded inline, or be imported from an external - file using the Classic scripts and module + scripts can be embedded inline, or be imported from an external file using the src attribute, which if specified gives the URL of the external script resource to use. If src is specified, - it must be a valid non-empty URL potentially surrounded by spaces.

                    - -

                    The contents of inline script elements, or the external script resource, must - conform with the requirements of the JavaScript specification's Script or Module productions, for classic scripts and JavaScript module scripts respectively.

                    - -

                    The contents of the external script resource for JSON module - scripts must conform to the requirements of the JSON specification .

                    + it must be a valid non-empty URL potentially surrounded by spaces. The contents of + inline script elements, or the external script resource, must conform with the + requirements of the JavaScript specification's Script or Module productions, for classic + scripts and module scripts respectively.

                    When used to include data blocks, the data must be embedded inline, the format of the data must be given using the type @@ -57661,7 +57652,7 @@ o............A....e

                    The following sample shows how a script element can be used to include an - external JavaScript module script. + external module script.

                    <script type="module" src="app.mjs"></script>
                    @@ -57672,37 +57663,37 @@ o............A....e

                    Additionally, if code from another script element in the same Window imports the module from app.mjs (e.g. via import - "./app.mjs";), then the same JavaScript module script created by the + "./app.mjs";), then the same module script created by the former script element will be imported.

                    -

                    This example shows how to include a JavaScript module script for modern user - agents, and a classic script for older user agents:

                    +

                    This example shows how to include a module script for modern user agents, and a + classic script for older user agents:

                    <script type="module" src="app.mjs"></script>
                     <script nomodule defer src="classic-app-bundle.js"></script>
                    -

                    In modern user agents that support JavaScript module - scripts, the script element with the nomodule attribute will be ignored, and the +

                    In modern user agents that support module scripts, the + script element with the nomodule attribute + will be ignored, and the script element with a type of "module" will be fetched and + evaluated (as a module script). Conversely, older user agents will ignore the script element with a type of "module" will be fetched and evaluated (as a JavaScript module - script). Conversely, older user agents will ignore the script element with a - type of "module", as that is an - unknown script type for them — but they will have no problem fetching and evaluating the other - script element (as a classic script), since they do not implement the - nomodule attribute.

                    + data-x="">module
                    ", as that is an unknown script type for them — but they will have no + problem fetching and evaluating the other script element (as a classic + script), since they do not implement the nomodule attribute.

                    The following sample shows how a script element can be used to write an inline - JavaScript module script that performs a number of substitutions on the document's - text, in order to make for a more interesting reading experience (e.g. on a news site): module script that performs a number of substitutions on the document's text, in + order to make for a more interesting reading experience (e.g. on a news site):

                    <script type="module">
                    @@ -57734,38 +57725,13 @@ o............A....e
                      walkAllTextNodeDescendants(document.body, substitute);
                     </script>
                    -

                    Some notable features gained by using a JavaScript module script include the ability to import - functions from other JavaScript modules, strict mode by default, and how top-level declarations - do not introduce new properties onto the global object. Also note that no matter - where this script element appears in the document, it will not be evaluated until - both document parsing has complete and its dependency (dom-utils.mjs) has - been fetched and evaluated.

                    - -
                    - -
                    - -

                    The following sample shows how a JSON module script can be imported from inside - a JavaScript module script:

                    +

                    Some notable features gained by using a module script include the ability to import functions + from other JavaScript modules, strict mode by default, and how top-level declarations do not + introduce new properties onto the global object. Also note that no matter where + this script element appears in the document, it will not be evaluated until both + document parsing has complete and its dependency (dom-utils.mjs) has been + fetched and evaluated.

                    -
                    <script type="module">
                    -import peopleInSpace from "http://api.open-notify.org/astros.json" if { type: "json" };
                    -
                    -const list = document.querySelector("#people-in-space");
                    -for (const { craft, name } of peopleInSpace.people) {
                    -  const li = document.createElement("li");
                    -  li.textContent = `${name} / ${craft}`;
                    -  list.append(li);
                    -}
                    -</script>
                    - -

                    MIME type checking for module scripts is strict. In order for the fetch of the - JSON module script to succeed, the HTTP reponse must have a - JSON MIME type, for example Content-Type: text/json. On the - other hand, if the if { type: "json" } part of the statement is omitted, - it is assumed that the intent is to import a JavaScript module script, and the fetch - will fail if the HTTP response has a MIME type that is not a JavaScript MIME type. -

                    @@ -88727,7 +88693,7 @@ document.querySelector("button").addEventListener("click", bound);
                    Scripts
                    -

                    A script is one of three possible A script is one of two possible structs. All scripts have:

                    @@ -88738,22 +88704,10 @@ document.querySelector("button").addEventListener("click", bound);
                    A record
                    -
                    -

                    One of the following:

                    - -
                      -
                    • a script record, for classic - scripts;

                    • - -
                    • a Source Text Module Record, for JavaScript module scripts;

                    • - -
                    • a Synthetic Module Record, for JSON - module scripts; or

                    • - -
                    • null, representing a parsing failure.

                    • -
                    -
                    +

                    Either a Script Record, for classic + scripts; a Source Text Module Record, for module scripts; or null. In the former two cases, it represents a parsed script; + null represents a failure parsing.

                    A parse error
                    @@ -88816,35 +88770,6 @@ document.querySelector("button").addEventListener("click", bound); data-x="concept-script">script. It has no additional items.

                    -

                    Module scripts can be classified into two types:

                    - -
                      -
                    • A module script is a JavaScript module script if - its record is a Source Text Module - Record.

                    • - -
                    • -

                      A module script is a JSON module script if its record is a Synthetic Module Record, and it - was created via the create a JSON module - script algorithm. JSON module scripts represent a parsed JSON document.

                      - - -

                      As JSON documents do not import dependent modules, and do not throw exceptions - on evaluation, the fetch options and - base URL of a JSON module script are - always null.

                      -
                    • -
                    -

                    The active script is determined by the following algorithm:

                      @@ -89292,8 +89217,8 @@ document.querySelector("button").addEventListener("click", bound); success).

                        -
                      1. Let script be the result of creating a JavaScript module script - using source text, settings object, base URL, and +

                      2. Let script be the result of creating a module script using + source text, settings object, base URL, and options.

                      3. If script is null, asynchronously complete this algorithm with null, and @@ -89544,8 +89469,8 @@ document.querySelector("button").addEventListener("click", bound);

                      4. Let options be the descendant script fetch options for module script's fetch options.

                      5. -
                      6. Assert: options is not null, as module script is a JavaScript - module script.

                      7. +
                      8. Assert: options is not null, as module script is a module + script.

                      9. For each moduleRequest in @@ -89619,42 +89544,30 @@ document.querySelector("button").addEventListener("click", bound); complete with either null (on failure) or a module script (on success).

                          -
                        1. Let module type be undefined.

                        2. -
                        3. -

                          If moduleRequest was given, then:

                          - -
                            -
                          1. If moduleRequest.[[Assertions]] has any Record entry - such that entry.[[Key]] is not "type", then asynchronously - complete this algorithm with null, and return.

                          2. - -
                          3. -

                            If moduleRequest.[[Assertions]] has a Record entry such - that entry.[[Key]] is "type", then set module - type to entry.[[Value]].

                            +

                            If moduleRequest was given and moduleRequest.[[Assertions]] contains + any Records, then asynchronously complete this algorithm with null, + and return.

                            -

                            Assert: No more than one such Record exists.

                            -
                          4. -
                          +

                          Currently no import assertions are supported, so we conservatively fail + if any are present. Eventually these will be used for checks such as confirming that the + type of the module matches the type expected by the importer.

                        4. -
                        5. If module type is neither undefined nor "json", - asynchronously complete this algorithm with null, and return.

                        6. -
                        7. Let moduleMap be module map settings object's module map.

                        8. -
                        9. If moduleMap[url / module type] is +

                        10. If moduleMap[url / undefined] 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.

                        11. -
                        12. If moduleMap[url / module type] is null, asynchronously - complete this algorithm with null, and return.

                        13. +
                        14. If moduleMap[url / undefined] exists, + asynchronously complete this algorithm with moduleMap[url / undefined], and + return.

                        15. -
                        16. Set moduleMap[url / - module type] to "fetching".

                          +
                        17. Set moduleMap[url / undefined] to + "fetching".

                        18. Let request be a new request whose url is url,

                        19. -

                          If either of the following conditions are met:

                          +

                          If any of the following conditions are met:

                          • response's type is "error"; or

                          • response's status is not an - ok status,

                          • -
                          + ok status; or

                        20. -

                          then set moduleMap[url / module - type] to null, asynchronously complete this algorithm with null, and return.

                          +
                        21. the result of extracting a MIME type from + response's header list is not a + JavaScript MIME type,

                        22. + + +

                          then set moduleMap[url / undefined] to + null, asynchronously complete this algorithm with null, and return.

                        23. Let source text be the result of UTF-8 decoding response's body.

                        24. -
                        25. Let module script be null.

                        26. - -
                        27. If MIME type is a JavaScript MIME type and module type - is undefined, then set module script to the result of creating a JavaScript - module script given source text, module map settings object, - response's url, and options.

                          -
                        28. - -
                        29. If MIME type is a JSON MIME type and module type is - "json", then set module script to the result of creating - a JSON module script given source text and module map settings - object.

                        30. +
                        31. Let module script be the result of creating a module script given + source text, module map settings object, response's url, and options.

                        32. -

                          Set moduleMap[url / - module type] to module script, and asynchronously complete this algorithm - with module script.

                          +

                          Set moduleMap[url / undefined] to + module script, and asynchronously complete this algorithm with module + script.

                          It is intentional that the module map is keyed by the request URL, whereas the moduleScript's parse error.

                        33. +
                        34. Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

                        35. +
                        36. -

                          If moduleScript's record is a - Cyclic Module Record:

                          +

                          For each moduleRequest of + moduleRequests:

                            -
                          1. Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

                          2. - -
                          3. -

                            For each moduleRequest of - moduleRequests:

                            - -
                              -
                            1. Let childURL be the result of resolving a module specifier given - moduleScript's base URL and - moduleRequest.[[Specifier]]. (This will never fail, as otherwise - moduleScript would have been marked as itself having a parse error.)

                            2. - -
                            3. If moduleRequest.[[Assertions]] has a Record entry - such that entry.[[Key]] is "type", then let module - type be entry.[[Value]]. Otherwise let module type be undefined. -

                            4. +
                            5. Let childURL be the result of resolving a module specifier given + moduleScript's base URL and + moduleRequest.[[Specifier]]. (This will never fail, as otherwise + moduleScript would have been marked as itself having a parse error.)

                            6. -
                            7. Let childModule be moduleMap[childURL / - module type].

                            8. +
                            9. Let childModule be moduleMap[childURL / undefined]. +

                            10. -
                            11. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module - scripts in the graph rooted at moduleScript will have successfully been - fetched.

                            12. +
                            13. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module + scripts in the graph rooted at moduleScript will have successfully been + fetched.

                            14. -
                            15. If discoveredSet already contains - childModule, continue.

                            16. +
                            17. If discoveredSet already contains + childModule, continue.

                            18. -
                            19. Let childParseError be the result of finding the first parse - error given childModule and discoveredSet.

                            20. +
                            21. Let childParseError be the result of finding the first parse + error given childModule and discoveredSet.

                            22. -
                            23. If childParseError is not null, return childParseError.

                            24. -
                            -
                          4. +
                          5. If childParseError is not null, return childParseError.

                        37. @@ -89861,10 +89757,10 @@ document.querySelector("button").addEventListener("click", bound);
                        38. Return script.

                        -

                        To create a JavaScript module script, - given a string source, an environment settings - object settings, a URL baseURL, and some script - fetch options options:

                        +

                        To create a module script, given a + string source, an environment settings object + settings, a URL baseURL, and some script fetch + options options:

                        1. If scripting is disabled for @@ -89939,34 +89835,6 @@ document.querySelector("button").addEventListener("click", bound);

                        2. Return script.

                        -

                        To create a JSON module script, given a - string source and an environment settings object settings:

                        - -
                          -
                        1. Let script be a new module script that this algorithm will - subsequently initialize.

                        2. - -
                        3. Set script's settings object to settings.

                        4. - -
                        5. Set script's base URL and - fetch options to null.

                        6. - -
                        7. Set script's parse error and - error to rethrow to null.

                        8. - -
                        9. -

                          Let result be ParseJSONModule(source). - -

                          If this throws an exception, set script's parse error to that exception, and return - script.

                          -
                        10. - -
                        11. Set script's record to result. - -

                        12. Return script.

                        13. -
                        -
                        Calling scripts

                        To run a classic script given a classic script @@ -90684,7 +90552,9 @@ dictionary PromiseRejectionEventInit : EventInit { either a module script, null (used to represent failed fetches), or a placeholder value "fetching". Module maps are used to ensure that imported JavaScript modules are only fetched, parsed, and evaluated once per - Document or worker.

                        + Document or worker. Currently only JavaScript + module scripts are supported, so the module type will always + be null until additional module types are introduced.

                        Since module maps are keyed by URL / module type, the @@ -90716,14 +90586,18 @@ import "https://example.com/foo/../module2.mjs"; data-x="SharedWorker">shared workers are keyed by their parsed constructor url.

                        -

                        Since module type is also part of the module map key, the following code will - create two separate entries in the module map (the type is undefined for the first, - and "json" for the second): +

                        Once additional module types are introduced, it will be possible to have multiple map entries + for a single URL since module type is also part of the module map key. For + example, once JSON modules are introduced the following code will create two separate entries in + the module map (the type is undefined for the first, and + "json" for the second):

                        import "https://example.com/module.json";
                         import "https://example.com/module.json" assert { type: "json" };
                        -

                        Therefore two separate fetches and two separate module evaluations will be performed.

                        +

                        Therefore two separate fetches and two separate module evaluations will be performed. Note + however that least one of the imports will fail the module type check unless the server + responds with a different MIME type for each.

                        @@ -90819,10 +90693,6 @@ import "https://example.com/module.json" assert { type: "json" };
                        1. Let module script be moduleRecord.[[HostDefined]].

                        2. -
                        3. Assert: module script's base - URL is not null, as module script is a JavaScript module - script.

                        4. -
                        5. Let urlString be module script's base URL, serialized.

                        6. @@ -90862,10 +90732,6 @@ import "https://example.com/module.json" assert { type: "json" };
                        7. Set fetch options to the descendant script fetch options for referencing script's fetch options.

                        8. - -
                        9. Assert: Neither base URL nor fetch options is null, as - referencing script is a classic script or a JavaScript module - script.

                        As explained above for HostResolveImportedModule, in the common @@ -90929,9 +90795,6 @@ import "https://example.com/module.json" assert { type: "json" };

                      10. Set base URL to referencing script's base URL.

                      11. - -
                      12. Assert: base URL is not null, as referencing script is a - classic script or a JavaScript module script.

                      @@ -90961,13 +90824,9 @@ import "https://example.com/module.json" assert { type: "json" }; same two arguments (either while creating the corresponding module script, or in HostImportModuleDynamically).

                      -
                    1. If moduleRequest.[[Assertions]] has a Record entry such - that entry.[[Key]] is "type", then let module type - be entry.[[Value]]. Otherwise let module type be undefined.

                    2. - -
                    3. Let resolved module script be moduleMap[url / - module type]. (This entry must exist for us to have - gotten to this point.)

                    4. +
                    5. Let resolved module script be moduleMap[url / undefined]. + (This entry must exist for us to have gotten to this point.) +

                    6. Assert: resolved module script is a module script (i.e., is not null or "fetching").

                    7. @@ -93952,9 +93811,6 @@ enum DOMParserSupportedType {
                    8. Let base URL be initiating script's base URL.

                    9. -
                    10. Assert: base URL is not null, as initiating script is a - classic script or a JavaScript module script.

                    11. -
                    12. Let fetch options be a script fetch options whose cryptographic nonce is initiating From 73f2be25d70587f550d0142e19f78e662a397736 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Wed, 30 Sep 2020 15:44:56 -0700 Subject: [PATCH 26/58] Update module map dfn note to explain purpose of having module type in key, and that in practice fetches and module evalutations will only occur once per specifier --- source | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/source b/source index 8ff86ee141a..5bc1727ae52 100644 --- a/source +++ b/source @@ -91094,12 +91094,18 @@ import "https://example.com/foo/../module2.mjs"; the module map (the type is undefined for the first, and "json" for the second): -

                      import "https://example.com/module.json";
                      -import "https://example.com/module.json" assert { type: "json" };
                      - -

                      Therefore two separate fetches and two separate module evaluations will be performed. Note - however that least one of the imports will fail the module type check unless the server - responds with a different MIME type for each.

                      +
                      import "https://example.com/module";
                      +import "https://example.com/module" assert { type: "json" };
                      + +

                      In theory, this means that two separate fetches and two separate module evaluations would be + performed. In practice, due to the memory cache the resource will only be fetched once. + Additionally, as long as all module types are mutually exclusive, the module type check in + fetch a single module script will fail for at least one of the imports, so at most + one module evaluation will occur.

                      + +

                      The purpose of including the type in the module map key is so that an import + with the wrong type assertion does not prevent a different import of the same specifier but with + the correct type from succeeding.

                    13. From 6ed447425c3b2e5f0bf46586efa74a9c9c679d91 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Wed, 30 Sep 2020 16:13:48 -0700 Subject: [PATCH 27/58] Ignore unknown import assertions instead of failing. Continue failing for unrecognized types (which is to say, any type at all). --- source | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/source b/source index 5bc1727ae52..67904f2c488 100644 --- a/source +++ b/source @@ -90047,13 +90047,18 @@ document.querySelector("button").addEventListener("click", bound);
                      1. -

                        If moduleRequest was given and moduleRequest.[[Assertions]] contains - any Records, then asynchronously complete this algorithm with null, - and return.

                        +

                        If moduleRequest was given and moduleRequest.[[Assertions]] has a + Record entry such that entry.[[Key]] is "type", then asynchronously complete this algorithm with null, and return.

                        + +
                        +

                        Currently no non-JS module types are supported, so we conservatively fail + if any type is specified. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + matches the type expected by the importer.

                        -

                        Currently no import assertions are supported, so we conservatively fail - if any are present. Eventually these will be used for checks such as confirming that the - type of the module matches the type expected by the importer.

                        +

                        Assertions with unknown keys are ignored.

                        +
                      2. Let moduleMap be module map settings object's Date: Mon, 5 Oct 2020 14:14:18 -0700 Subject: [PATCH 28/58] Move check for unknown type assertion to 'create a module script'. --- source | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/source b/source index 67904f2c488..fb06c2111e3 100644 --- a/source +++ b/source @@ -89661,6 +89661,21 @@ document.querySelector("button").addEventListener("click", bound);

                      3. If url is failure, then asynchronously complete this algorithm with null, and return.

                      4. +
                      5. +

                        If moduleRequest.[[Assertions]] has a Record entry such + that entry.[[Key]] is "type" then asynchronously complete this + algorithm with null, and return.

                        + +
                        +

                        Currently no non-JS module types are supported, so we conservatively fail if any type + assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + matches the type expected by the importer.

                        + +

                        Assertions with unknown keys are ignored.

                        +
                        +
                      6. +
                      7. Fetch a single module script given url, settings object, "script", options, settings object, "client", moduleRequest, and with the @@ -90046,21 +90061,6 @@ document.querySelector("button").addEventListener("click", bound); complete with either null (on failure) or a module script (on success).

                          -
                        1. -

                          If moduleRequest was given and moduleRequest.[[Assertions]] has a - Record entry such that entry.[[Key]] is "type", then asynchronously complete this algorithm with null, and return.

                          - -
                          -

                          Currently no non-JS module types are supported, so we conservatively fail - if any type is specified. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module - matches the type expected by the importer.

                          - -

                          Assertions with unknown keys are ignored.

                          -
                          -
                        2. -
                        3. Let moduleMap be module map settings object's module map.

                        4. @@ -90317,7 +90317,9 @@ document.querySelector("button").addEventListener("click", bound); URL and requested.[[Specifier]].

                        5. -

                          If url is failure, then:

                          +

                          If url is failure, or if requested.[[Assertions]] has a + Record entry such that entry.[[Key]] is "type" then:

                          1. Let error be a new TypeError exception.

                          2. @@ -90330,10 +90332,19 @@ document.querySelector("button").addEventListener("click", bound);
                          -

                          This step is essentially validating all of the requested module specifiers. We - treat a module with unresolvable module specifiers the same as one that cannot be parsed; in - both cases, a syntactic issue makes it impossible to ever contemplate linking the module - later.

                          +
                          +

                          This step is essentially validating all of the requested module specifiers and type + assertions. We treat a module with unresolvable module specifiers or an unsupported type + assertion the same as one that cannot be parsed; in both cases, a syntactic issue makes + it impossible to ever contemplate linking the module later.

                          + +

                          Currently no non-JS module types are supported, so we conservatively fail if any type + assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + matches the type expected by the importer.

                          + +

                          Assertions with unknown keys are ignored.

                          +
                        6. Set script's record to From f9f0e40d4680cb7d0c087eb5ae137fb9ea28c115 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 27 Oct 2020 14:40:32 -0700 Subject: [PATCH 29/58] Import assertions HTML integration. --- source | 240 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 157 insertions(+), 83 deletions(-) diff --git a/source b/source index 97abc1f8269..6cb1138444c 100644 --- a/source +++ b/source @@ -2187,6 +2187,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

                        7. surrogate
                        8. scalar value
                        9. tuple
                        10. +
                        11. pair
                        12. noncharacter
                        13. string, code unit, @@ -2867,8 +2868,15 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

                          Users agents that support JavaScript must also implement ECMAScript Internationalization API.

                          - +

                          User agents that support JavaScript must also implement the import assertions + proposal. The following term is defined there, and used in this specification:

                          + +
                            +
                          • The ModuleRequest Record specification type
                          • +
                          +
                          WebAssembly
                          @@ -2881,7 +2889,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute -
                          DOM
                          @@ -89801,24 +89808,40 @@ document.querySelector("button").addEventListener("click", bound); result.

                        -

                        To fetch an import() module script graph given a specifier, a base - URL, a settings object, and some options, run these steps. The - algorithm will asynchronously complete with either null (on failure) or a module +

                        To fetch an import() module script graph given a moduleRequest, a + base URL, a settings object, and some options, run these steps. + The algorithm will asynchronously complete with either null (on failure) or a module script (on success).

                        1. Let url be the result of resolving a - module specifier given base URL and specifier.

                        2. + module specifier given base URL and moduleRequest.[[Specifier]].

                          +
                        3. If url is failure, then asynchronously complete this algorithm with null, and return.

                        4. +
                        5. +

                          If moduleRequest.[[Assertions]] has a Record entry such + that entry.[[Key]] is "type" then asynchronously complete this + algorithm with null, and return.

                          + +
                          +

                          Currently no non-JS module types are supported, so we conservatively fail if any type + assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + matches the type expected by the importer.

                          + +

                          Assertions with unknown keys are ignored.

                          +
                          +
                        6. +
                        7. Fetch a single module script given url, settings object, "script", options, 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.

                        8. + "client", moduleRequest, 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.

                        9. If result is null, asynchronously complete this algorithm with null, and return.

                        10. @@ -90152,16 +90175,16 @@ document.querySelector("button").addEventListener("click", bound); record.[[RequestedModules]] is empty, asynchronously complete this algorithm with module script.

                          -
                        11. Let urls be a new empty list.

                        12. +
                        13. Let moduleRequests be a new empty list.

                        14. -

                          For each string requested of - record.[[RequestedModules]],

                          +

                          For each ModuleRequest Record + requested of record.[[RequestedModules]],

                          1. Let url be the result of resolving - a module specifier given module script's base URL and requested.

                          2. + data-x="concept-script-base-url">base URL and requested.[[Specifier]].

                            +
                          3. Assert: url is never failure, because resolving a module specifier must have been url, then:

                              -
                            1. Append url to urls.

                            2. +
                            3. Append requested to + moduleRequests.

                            4. Append url to visited set.

                            5. @@ -90189,11 +90213,12 @@ document.querySelector("button").addEventListener("click", bound); script.

                            6. -

                              For each url in urls, perform the - internal module script graph fetching procedure given url, fetch - client settings object, destination, options, module - script's settings object, visited set, and module - script's base URL. If the caller of this +

                              For each moduleRequest in + moduleRequests, perform the internal module script graph fetching + procedure given moduleRequest, fetch client settings object, + destination, options, module script's settings + object, visited set, and module script's base URL. If the caller of this algorithm specified custom perform the fetch steps, pass those along while performing the internal module script graph fetching procedure.

                              @@ -90212,21 +90237,30 @@ document.querySelector("button").addEventListener("click", bound);

                            To perform the internal module script graph fetching procedure given a - url, a fetch client settings object, a destination, some - options, a module map settings object, a visited set, and a + moduleRequest, a fetch client settings object, a destination, + some options, a module map settings object, a visited set, and a referrer, perform these steps. The algorithm will asynchronously complete with either null (on failure) or a module script (on success).

                              +
                            1. Let url be the result of resolving + a module specifier given referrer and + moduleRequst.[[Specifier]].

                            2. + +
                            3. Assert: url is never failure, because resolving a module specifier must have been previously successful with these same two + arguments.

                            4. +
                            5. Assert: visited set contains url.

                            6. Fetch a single module script given url, fetch client settings object, destination, options, module map settings object, - referrer, and with the top-level module fetch flag unset. If the caller of - this algorithm specified custom perform the - fetch steps, pass those along while fetching a - single module script.

                              + referrer, moduleRequest, and with the + top-level module fetch flag unset. If the caller of this algorithm specified custom + perform the fetch steps, pass those along + while fetching a single module script.

                            7. Return from this algorithm, and run the following steps when fetching a single module script asynchronously completes with @@ -90245,24 +90279,25 @@ document.querySelector("button").addEventListener("click", bound);

                              To fetch a single module script, given a url, a fetch client settings object, a destination, some options, a module map - settings object, a referrer, and a top-level module fetch flag, run - these steps. The algorithm will asynchronously complete with either null (on failure) or a - module script (on success).

                              + settings object, a referrer, an optional moduleRequest, and a + top-level module fetch flag, run these steps. The algorithm will asynchronously + complete with either null (on failure) or a module script (on success).

                              1. Let moduleMap be module map settings object's module map.

                              2. -
                              3. If moduleMap[url] 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.

                              4. +
                              5. If moduleMap[url / undefined] 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.

                              6. -
                              7. If moduleMap[url] exists, - asynchronously complete this algorithm with moduleMap[url], and +

                              8. If moduleMap[url / undefined] exists, + asynchronously complete this algorithm with moduleMap[url / undefined], and return.

                              9. -
                              10. Set moduleMap[url] to "fetching".

                                +
                              11. Set moduleMap[url / undefined] to + "fetching".

                              12. Let request be a new request whose url is url,

                                the result of extracting a MIME type from response's header list is not a JavaScript MIME type,

                              13. - + -

                                then set moduleMap[url] to null, - asynchronously complete this algorithm with null, and return.

                                +

                                then set moduleMap[url / undefined] to + null, asynchronously complete this algorithm with null, and return.

                              14. Let source text be the result of UTF-8 @@ -90323,8 +90358,9 @@ document.querySelector("button").addEventListener("click", bound); data-x="concept-response-url">url, and options.

                              15. -

                                Set moduleMap[url] to module - script, and asynchronously complete this algorithm with module script.

                                +

                                Set moduleMap[url / undefined] to + module script, and asynchronously complete this algorithm with module + script.

                                It is intentional that the module map is keyed by the request URL, whereas the moduleScript's parse error.

                              16. -
                              17. Let childSpecifiers be the value of moduleScript's

                                Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

                              18. -
                              19. Let childURLs be the list obtained by calling - resolve a module specifier once for each item of childSpecifiers, given - moduleScript's base URL and that item. - (None of these will ever fail, as otherwise moduleScript would have been marked as itself having a parse error.)

                              20. - -
                              21. Let childModules be the list obtained by getting each value in moduleMap whose key is given by an - item of childURLs.

                              22. -
                              23. -

                                For each childModule of - childModules:

                                +

                                For each moduleRequest of + moduleRequests:

                                  +
                                1. Let childURL be the result of resolving a module specifier given + moduleScript's base URL and + moduleRequest.[[Specifier]]. (This will never fail, as otherwise + moduleScript would have been marked + as itself having a parse error.)

                                2. + +
                                3. Let childModule be moduleMap[childURL / undefined]. +

                                4. +
                                5. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module scripts in the graph rooted at moduleScript will have successfully been @@ -90496,16 +90532,18 @@ document.querySelector("button").addEventListener("click", bound);

                                6. -

                                  For each string requested of - result.[[RequestedModules]]:

                                  +

                                  For each ModuleRequest record + requested of result.[[RequestedModules]]:

                                  1. Let url be the result of resolving a module specifier given script's base - URL and requested.

                                  2. + URL and requested.[[Specifier]].

                                  3. -

                                    If url is failure, then:

                                    +

                                    If url is failure, or if requested.[[Assertions]] has a + Record entry such that entry.[[Key]] is "type" then:

                                    1. Let error be a new TypeError exception.

                                    2. @@ -90518,10 +90556,19 @@ document.querySelector("button").addEventListener("click", bound);
                                    -

                                    This step is essentially validating all of the requested module specifiers. We - treat a module with unresolvable module specifiers the same as one that cannot be parsed; in - both cases, a syntactic issue makes it impossible to ever contemplate linking the module - later.

                                    +
                                    +

                                    This step is essentially validating all of the requested module specifiers and type + assertions. We treat a module with unresolvable module specifiers or an unsupported type + assertion the same as one that cannot be parsed; in both cases, a syntactic issue makes + it impossible to ever contemplate linking the module later.

                                    + +

                                    Currently no non-JS module types are supported, so we conservatively fail if any type + assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + matches the type expected by the importer.

                                    + +

                                    Assertions with unknown keys are ignored.

                                    +
                                  4. Set script's record to @@ -91244,17 +91291,20 @@ dictionary PromiseRejectionEventInit : EventInit {

                    -

                    A module map is a map of URL records to values that are either a module script, - null (used to represent failed fetches), or a placeholder value "fetching". Module maps are used to ensure - that imported JavaScript modules are only fetched, parsed, and evaluated once per - Document or worker.

                    +

                    A module map is a map keyed by + URL record / module type string pairs whose values are + either a module script, null (used to represent failed fetches), or a placeholder + value "fetching". Module maps are + used to ensure that imported JavaScript modules are only fetched, parsed, and evaluated once per + Document or worker. Currently only JavaScript + module scripts are supported, so the module type will always + be null until additional module types are introduced.

                    -

                    Since module maps are keyed by URL, the following code will - create three separate entries in the module map, since it results in three different - URLs:

                    +

                    Since module maps are keyed by URL / module type, the + following code will create three separate entries in the module map, since it + results in three different URL/module type pairs (all with null type): +

                    import "https://example.com/module.mjs";
                     import "https://example.com/module.mjs#map-buster";
                    @@ -91279,6 +91329,25 @@ import "https://example.com/foo/../module2.mjs";

                    Note that this behavior is the same as how shared workers are keyed by their parsed constructor url.

                    + +

                    Once additional module types are introduced, it will be possible to have multiple map entries + for a single URL since module type is also part of the module map key. For + example, once JSON modules are introduced the following code will create two separate entries in + the module map (the type is undefined for the first, and + "json" for the second): + +

                    import "https://example.com/module";
                    +import "https://example.com/module" assert { type: "json" };
                    + +

                    In theory, this means that two separate fetches and two separate module evaluations would be + performed. In practice, due to the memory cache the resource will only be fetched once. + Additionally, as long as all module types are mutually exclusive, the module type check in + fetch a single module script will fail for at least one of the imports, so at most + one module evaluation will occur.

                    + +

                    The purpose of including the type in the module map key is so that an import + with the wrong type assertion does not prevent a different import of the same specifier but with + the correct type from succeeding.

                    @@ -91382,7 +91451,7 @@ import "https://example.com/foo/../module2.mjs";
                  HostImportModuleDynamically(referencingScriptOrModule, - specifier, promiseCapability)
                  + moduleRequest, promiseCapability)

                  JavaScript contains an implementation-defined HostImportModuleDynamically abstract operation. @@ -91434,9 +91503,9 @@ import "https://example.com/foo/../module2.mjs"; case, referencingScriptOrModule is non-null.

                  -
                16. Fetch an import() module script graph given specifier, base - URL, settings object, and fetch options. Wait until the algorithm - asynchronously completes with result.

                17. +
                18. Fetch an import() module script graph given moduleRequest, + base URL, settings object, and fetch options. Wait until the + algorithm asynchronously completes with result.

                19. If result is null, then:

                  @@ -91446,7 +91515,7 @@ import "https://example.com/foo/../module2.mjs"; TypeError, [[Target]]: empty }.

                20. Perform FinishDynamicImport(referencingScriptOrModule, - specifier, promiseCapability, completion).

                21. + moduleRequest, promiseCapability, completion).

                22. Return.

                @@ -91456,18 +91525,18 @@ import "https://example.com/foo/../module2.mjs"; the rethrow errors boolean set to true.

              14. If running the module script throws an exception, then perform - FinishDynamicImport(referencingScriptOrModule, specifier, + FinishDynamicImport(referencingScriptOrModule, moduleRequest, promiseCapability, the thrown exception completion).

              15. Otherwise, perform - FinishDynamicImport(referencingScriptOrModule, specifier, + FinishDynamicImport(referencingScriptOrModule, moduleRequest, promiseCapability, NormalCompletion(undefined)).

              16. Return undefined.

              HostResolveImportedModule(referencingScriptOrModule, - specifier)
              + moduleRequest)

              JavaScript contains an implementation-defined HostResolveImportedModule abstract operation. User @@ -91512,15 +91581,17 @@ import "https://example.com/foo/../module2.mjs"; data-x="concept-settings-object-module-map">module map.

            7. Let url be the result of resolving a - module specifier given base URL and specifier.

            8. + module specifier given base URL and moduleRequest.[[Specifier]].

              +
            9. Assert: url is never failure, because resolving a module specifier must have been previously successful with these same two arguments (either while creating the corresponding module script, or in fetch an import() module script graph).

            10. -
            11. Let resolved module script be moduleMap[url]. (This entry - must exist for us to have gotten to this point.)

            12. +
            13. Let resolved module script be moduleMap[url / undefined]. + (This entry must exist for us to have gotten to this point.) +

            14. Assert: resolved module script is a module script (i.e., is not null or "fetching").

            15. @@ -124149,6 +124220,9 @@ INSERT INTERFACES HERE
              [JSERRORSTACKS]
              (Non-normative) Error Stacks. Ecma International.
              +
              [JSIMPORTASSERTIONS]
              +
              Import Assertions. Ecma International.
              +
              [JSINTL]
              ECMAScript Internationalization API Specification. Ecma International.
              From f90a05db51c6b346e073067bbfc7190a506930e8 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 29 Oct 2020 11:15:04 -0700 Subject: [PATCH 30/58] Add CSS Modules --- source | 415 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 288 insertions(+), 127 deletions(-) diff --git a/source b/source index 6cb1138444c..335530697f0 100644 --- a/source +++ b/source @@ -2647,6 +2647,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
            16. frozen array and creating a frozen array
            17. create a new object implementing the interface
            18. +
            19. CreateSyntheticModule
            20. +
            21. SetSyntheticModuleExport
            22. +
            23. Synthetic Module Record
            24. callback this value
            25. converting between Web IDL types and JS types
            26. invoking and @@ -3701,6 +3704,13 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
              • 'color-scheme'
              + +

              The following features are defined in Constructable Stylesheet Objects:

              + +
                +
              • CSSStyleSheet constructor
              • +
              • CSSStyleSheet.replaceSync
              • +
              @@ -57660,12 +57670,16 @@ interface HTMLScriptElement : HTMLElement { Authors should omit the type attribute instead of redundantly setting it.

            27. +
            28. Setting the attribute to an ASCII case-insensitive match for the string - "module" means that the script is a module script, to be - interpreted according to the JavaScript Module top-level - production. Module scripts are not affected by the defer - attribute, but are affected by the async attribute - (regardless of the state of the src attribute).

            29. + "module" means that the script is a module script. If it has + a JavaScript MIME type, or if the script is embedded inline, then it will be + interpreted as a JavaScript module script according to the JavaScript Module top-level production; if it has a MIME type of + text/css, then it will be interpreted as a CSS module script. Module + scripts are not affected by the defer attribute, but are + affected by the async attribute (regardless of the state + of the src attribute).

            30. Setting the attribute to any other value means that the script is a data block, which is not processed. None of the script attributes (except HTMLScriptElement : HTMLElement { scripts. By using a valid MIME type string now, you ensure that your data block will not ever be reinterpreted as a different script type, even in future user agents.

              -

              Classic scripts and module - scripts can be embedded inline, or be imported from an external file using the src attribute, which if - specified gives the URL of the external script resource to use. If src is specified, it must be a valid non-empty URL - potentially surrounded by spaces. The contents of inline script elements, or - the external script resource, must conform with the requirements of the JavaScript specification's - Script or Module productions, for - classic scripts and module - scripts respectively.

              +

              Classic scripts and JavaScript module scripts can be embedded inline, or be + imported from an external file using the src attribute, which if specified gives the URL + of the external script resource to use. If src is specified, + it must be a valid non-empty URL potentially surrounded by spaces.

              + +

              The contents of inline script elements, or the external script resource, must + conform with the requirements of the JavaScript specification's Script or Module productions, for classic scripts and JavaScript module scripts respectively.

              + +

              The contents of the external script resource for CSS module + scripts must conform to the requirements of the CSS specification.

              When used to include data blocks, the data must be embedded inline, the format of the data must be given using the type @@ -57931,7 +57950,7 @@ o............A....e

              The following sample shows how a script element can be used to include an - external module script. + external JavaScript module script.

              <script type="module" src="app.mjs"></script>
              @@ -57942,37 +57961,37 @@ o............A....e

              Additionally, if code from another script element in the same Window imports the module from app.mjs (e.g. via import - "./app.mjs";), then the same module script created by the + "./app.mjs";), then the same JavaScript module script created by the former script element will be imported.

              -

              This example shows how to include a module script for modern user agents, and a - classic script for older user agents:

              +

              This example shows how to include a JavaScript module script for modern user + agents, and a classic script for older user agents:

              <script type="module" src="app.mjs"></script>
               <script nomodule defer src="classic-app-bundle.js"></script>
              -

              In modern user agents that support module scripts, the - script element with the nomodule attribute - will be ignored, and the script element with a type of "module" will be fetched and - evaluated (as a module script). Conversely, older user agents will ignore the +

              In modern user agents that support JavaScript module + scripts, the script element with the nomodule attribute will be ignored, and the script element with a type of "module", as that is an unknown script type for them — but they will have no - problem fetching and evaluating the other script element (as a classic - script), since they do not implement the nomodule attribute.

              + data-x="">module" will be fetched and evaluated (as a JavaScript module + script). Conversely, older user agents will ignore the script element with a + type of "module", as that is an + unknown script type for them — but they will have no problem fetching and evaluating the other + script element (as a classic script), since they do not implement the + nomodule attribute.

              The following sample shows how a script element can be used to write an inline - module script that performs a number of substitutions on the document's text, in - order to make for a more interesting reading experience (e.g. on a news site): JavaScript module script that performs a number of substitutions on the document's + text, in order to make for a more interesting reading experience (e.g. on a news site):

              <script type="module">
              @@ -58004,12 +58023,12 @@ o............A....e
                walkAllTextNodeDescendants(document.body, substitute);
               </script>
              -

              Some notable features gained by using a module script include the ability to import functions - from other JavaScript modules, strict mode by default, and how top-level declarations do not - introduce new properties onto the global object. Also note that no matter where - this script element appears in the document, it will not be evaluated until both - document parsing has complete and its dependency (dom-utils.mjs) has been - fetched and evaluated.

              +

              Some notable features gained by using a JavaScript module script include the ability to import + functions from other JavaScript modules, strict mode by default, and how top-level declarations + do not introduce new properties onto the global object. Also note that no matter + where this script element appears in the document, it will not be evaluated until + both document parsing has complete and its dependency (dom-utils.mjs) has + been fetched and evaluated.

              @@ -89357,7 +89376,7 @@ document.querySelector("button").addEventListener("click", bound);
              Scripts
              -

              A script is one of two possible A script is one of three possible structs. All scripts have:

              @@ -89368,10 +89387,22 @@ document.querySelector("button").addEventListener("click", bound);
              A record
              -

              Either a Script Record, for classic - scripts; a Source Text Module Record, for module scripts; or null. In the former two cases, it represents a parsed script; - null represents a failure parsing.

              +
              +

              One of the following:

              + +
                +
              • a script record, for classic + scripts;

              • + +
              • a Source Text Module Record, for JavaScript module scripts;

              • + +
              • a Synthetic Module Record, for CSS + module scripts; or

              • + +
              • null, representing a parsing failure.

              • +
              +
              A parse error
              @@ -89433,6 +89464,35 @@ document.querySelector("button").addEventListener("click", bound); data-x="concept-script">script. It has no additional items.

              +

              Module scripts can be classified into two types:

              + +
                +
              • A module script is a JavaScript module script if + its record is a Source Text Module + Record.

              • + +
              • +

                A module script is a CSS module script if its record is a Synthetic Module Record, and it + was created via the create a CSS module + script algorithm. CSS module scripts represent a parsed CSS stylesheet.

                + + +

                As CSS stylesheets do not import dependent modules, and do not throw exceptions + on evaluation, the fetch options and + base URL of a CSS module script are + always null.

                +
              • +
              +

              The active script is determined by the following algorithm:

                @@ -89821,20 +89881,10 @@ document.querySelector("button").addEventListener("click", bound);
              1. If url is failure, then asynchronously complete this algorithm with null, and return.

              2. -
              3. -

                If moduleRequest.[[Assertions]] has a Record entry such - that entry.[[Key]] is "type" then asynchronously complete this - algorithm with null, and return.

                - -
                -

                Currently no non-JS module types are supported, so we conservatively fail if any type - assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module - matches the type expected by the importer.

                - -

                Assertions with unknown keys are ignored.

                -
                -
              4. +
              5. If moduleRequest.[[Assertions]] has a Record entry + such that entry.[[Key]] is "type" and + entry.[[Value]] is neither undefined nor "css", then + asynchronously complete this algorithm with null, and return.

              6. Fetch a single module script given url, settings object, "script", options, settings object, @@ -89894,8 +89944,8 @@ document.querySelector("button").addEventListener("click", bound); success).

                  -
                1. Let script be the result of creating a module script using - source text, settings object, base URL, and +

                2. Let script be the result of creating a JavaScript module script + using source text, settings object, base URL, and options.

                3. If script is null, asynchronously complete this algorithm with null, and @@ -90209,8 +90259,8 @@ document.querySelector("button").addEventListener("click", bound);

                4. Let options be the descendant script fetch options for module script's fetch options.

                5. -
                6. Assert: options is not null, as module script is a module - script.

                7. +
                8. Assert: options is not null, as module script is a JavaScript + module script.

                9. For each moduleRequest in @@ -90284,20 +90334,40 @@ document.querySelector("button").addEventListener("click", bound); complete with either null (on failure) or a module script (on success).

                    +
                  1. Let module type be undefined.

                  2. + +
                  3. +

                    If moduleRequest was given and moduleRequest.[[Assertions]] has a + Record entry such that entry.[[Key]] is "type", then:

                    + +
                      +
                    1. Assert: No more than one such Record exists.

                    2. + +
                    3. Set module type to entry.[[Value]].

                    4. +
                    +
                  4. + +
                  5. Assert: module type is either undefined or "css". + Otherwise we would not have reached this point because a failure would have been raised when + inspecting moduleRequest.[[Assertions]] in create a JavaScript module script or fetch + an import() module script graph.

                  6. +
                  7. Let moduleMap be module map settings object's module map.

                  8. -
                  9. If moduleMap[url / undefined] is +

                  10. If moduleMap[url / module type] 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.

                  11. -
                  12. If moduleMap[url / undefined] exists, - asynchronously complete this algorithm with moduleMap[url / undefined], and - return.

                  13. +
                  14. If moduleMap[url / module type] exists, asynchronously complete this algorithm with + moduleMap[url / module type], and return.

                  15. -
                  16. Set moduleMap[url / undefined] to - "fetching".

                    +
                  17. Set moduleMap[url / + module type] to "fetching".

                  18. Let request be a new request whose url is url,

                  19. -

                    If any of the following conditions are met:

                    +

                    If either of the following conditions are met:

                    • response's type is "

                      response's status is not an ok status; or

                    • +
                    -
                  20. the result of extracting a MIME type from - response's header list is not a - JavaScript MIME type,

                  21. - - -

                    then set moduleMap[url / undefined] to - null, asynchronously complete this algorithm with null, and return.

                    +

                    then set moduleMap[url / + module type] to null, asynchronously complete this algorithm with null, and return. +

                  22. Let source text be the result of UTF-8 decoding response's body.

                  23. -
                  24. Let module script be the result of creating a module script given - source text, module map settings object, response's url, and options.

                  25. +
                  26. Let module script be null.

                  27. + +
                  28. If MIME type is a JavaScript MIME type and module type + is undefined, then set module script to the result of creating a JavaScript + module script given source text, module map settings object, + response's url, and options.

                    +
                  29. + +
                  30. If MIME type is text/css and module type is + "css", then set module script to the result of creating + a CSS module script given source text and module map settings + object.

                  31. -

                    Set moduleMap[url / undefined] to - module script, and asynchronously complete this algorithm with module - script.

                    +

                    Set moduleMap[url / + module type] to module script, and asynchronously complete this algorithm + with module script.

                    It is intentional that the module map is keyed by the request URL, whereas the moduleScript's parse error.

                  32. -
                  33. Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

                  34. -
                  35. -

                    For each moduleRequest of - moduleRequests:

                    +

                    If moduleScript's record is a + Cyclic Module Record:

                      -
                    1. Let childURL be the result of resolving a module specifier given - moduleScript's base URL and - moduleRequest.[[Specifier]]. (This will never fail, as otherwise - moduleScript would have been marked - as itself having a parse error.)

                    2. - -
                    3. Let childModule be moduleMap[childURL / undefined]. -

                    4. +
                    5. Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

                    6. + +
                    7. +

                      For each moduleRequest of + moduleRequests:

                      + +
                        +
                      1. Let childURL be the result of resolving a module specifier given + moduleScript's base URL and + moduleRequest.[[Specifier]]. (This will never fail, as otherwise + moduleScript would have been marked + as itself having a parse error.)

                      2. + +
                      3. If moduleRequest.[[Assertions]] has a Record entry + such that entry.[[Key]] is "type", then let module + type be entry.[[Value]]. Otherwise let module type be undefined. +

                      4. + +
                      5. Let childModule be moduleMap[childURL / + module type].

                      6. -
                      7. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module - scripts in the graph rooted at moduleScript will have successfully been - fetched.

                      8. +
                      9. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module + scripts in the graph rooted at moduleScript will have successfully been + fetched.

                      10. -
                      11. If discoveredSet already contains - childModule, continue.

                      12. +
                      13. If discoveredSet already contains + childModule, continue.

                      14. -
                      15. Let childParseError be the result of finding the first parse - error given childModule and discoveredSet.

                      16. +
                      17. Let childParseError be the result of finding the first parse + error given childModule and discoveredSet.

                      18. -
                      19. If childParseError is not null, return childParseError.

                      20. +
                      21. If childParseError is not null, return childParseError.

                      22. +
                      +
                  36. @@ -90488,10 +90576,10 @@ document.querySelector("button").addEventListener("click", bound);
                  37. Return script.

                  -

                  To create a module script, given a - string source, an environment settings object - settings, a URL baseURL, and some script fetch - options options:

                  +

                  To create a JavaScript module script, + given a string source, an environment settings + object settings, a URL baseURL, and some script + fetch options options:

                  1. If scripting is disabled for @@ -90531,6 +90619,62 @@ document.querySelector("button").addEventListener("click", bound);

                10. +

                  To create a CSS module script, given a + string source and an environment settings object settings:

                  + +
                    +
                  1. Let script be a new module script that this algorithm will + subsequently initialize.

                  2. + +
                  3. Set script's settings object to settings.

                  4. + +
                  5. Set script's base URL and + fetch options to null.

                  6. + +
                  7. Set script's parse error and + error to rethrow to null.

                  8. + +
                  9. Let sheet be the result of calling the CSSStyleSheet constructor + with no arguments.

                  10. + +
                  11. +

                    Call sheet.replaceSync(source).

                    + +

                    If this throws an exception, set script's parse error to that exception, and return + script.

                    + +

                    CSSStyleSheet.replaceSync will throw if source contains + any @import references. This is by-design for now because there is not + yet an agreement on how to handle these for CSS module scripts; therefore they are blocked altogether + until a consensus is reached.

                    +
                  12. + +
                  13. Set script's record to the result + of creating a synthetic + module record with a default export of sheet with settings.

                    +
                  14. + +
                  15. Return script.

                  16. +
                  + +

                  To create a synthetic module record with a default export of a JavaScript value + value with an environment settings object settings:

                  + +
                    +
                  1. +

                    Return CreateSyntheticModule(« "default" », the following steps, + settings's Realm, + value) with the following steps given module as an argument:

                    + +
                      +
                    1. SetSyntheticModuleExport(module, "default", + module.[[HostDefined]]).
                    2. +
                    +
                  2. +
                  +
                11. For each ModuleRequest record requested of result.[[RequestedModules]]:

                  @@ -90540,11 +90684,13 @@ document.querySelector("button").addEventListener("click", bound); a module specifier given script's base URL and requested.[[Specifier]].

                12. -
                13. -

                  If url is failure, or if requested.[[Assertions]] has a - Record entry such that entry.[[Key]] is "type" then:

                  +
                14. If requested.[[Assertions]] has a Record entry such + that entry.[[Key]] is "type", then let module type + be entry.[[Value]]. Otherwise let module type be undefined.

                15. +
                16. +

                  If url is failure, or if module type is neither undefined nor + "css", then:

                  1. Let error be a new TypeError exception.

                  2. @@ -90558,15 +90704,10 @@ document.querySelector("button").addEventListener("click", bound);

                    This step is essentially validating all of the requested module specifiers and type - assertions. We treat a module with unresolvable module specifiers or an unsupported type - assertion the same as one that cannot be parsed; in both cases, a syntactic issue makes + assertions. We treat a module with unresolvable module specifiers or unsupported type + assertions the same as one that cannot be parsed; in both cases, a syntactic issue makes it impossible to ever contemplate linking the module later.

                    -

                    Currently no non-JS module types are supported, so we conservatively fail if any type - assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module - matches the type expected by the importer.

                    -

                    Assertions with unknown keys are ignored.

                    @@ -91295,7 +91436,7 @@ dictionary PromiseRejectionEventInit : EventInit { URL record / module type string pairs whose values are either a module script, null (used to represent failed fetches), or a placeholder value "fetching". Module maps are - used to ensure that imported JavaScript modules are only fetched, parsed, and evaluated once per + used to ensure that imported modules are only fetched, parsed, and evaluated once per Document or worker. Currently only JavaScript module scripts are supported, so the module type will always be null until additional module types are introduced.

                    @@ -91330,14 +91471,13 @@ import "https://example.com/foo/../module2.mjs";
                    data-x="SharedWorker">shared workers are keyed by their parsed constructor url.

                    -

                    Once additional module types are introduced, it will be possible to have multiple map entries - for a single URL since module type is also part of the module map key. For - example, once JSON modules are introduced the following code will create two separate entries in - the module map (the type is undefined for the first, and - "json" for the second): +

                    It is possible to have multiple map entries for a single URL since module type is also part + of the module map key. For example, the following code will create two separate + entries in the module map (the type is undefined for the first, and + "css" for the second):

                    import "https://example.com/module";
                    -import "https://example.com/module" assert { type: "json" };
                    +import "https://example.com/module" assert { type: "css" };

                    In theory, this means that two separate fetches and two separate module evaluations would be performed. In practice, due to the memory cache the resource will only be fetched once. @@ -91443,6 +91583,10 @@ import "https://example.com/module" assert { type: "json" };

                    1. Let module script be moduleRecord.[[HostDefined]].

                    2. +
                    3. Assert: module script's base + URL is not null, as module script is a JavaScript module + script.

                    4. +
                    5. Let urlString be module script's base URL, serialized.

                    6. @@ -91497,6 +91641,10 @@ import "https://example.com/module" assert { type: "json" };
                    7. Set fetch options to the descendant script fetch options for referencing script's fetch options.

                    8. + +
                    9. Assert: Neither base URL nor fetch options is null, as + referencing script is a classic script or a JavaScript module + script.

                    As explained above for HostResolveImportedModule, in the common @@ -91560,6 +91708,9 @@ import "https://example.com/module" assert { type: "json" };

                  3. Set base URL to referencing script's base URL.

                  4. + +
                  5. Assert: base URL is not null, as referencing script is a + classic script or a JavaScript module script.

                  @@ -91589,9 +91740,13 @@ import "https://example.com/module" assert { type: "json" }; same two arguments (either while creating the corresponding module script, or in fetch an import() module script graph).

                17. -
                18. Let resolved module script be moduleMap[url / undefined]. - (This entry must exist for us to have gotten to this point.) -

                19. +
                20. If moduleRequest.[[Assertions]] has a Record entry such + that entry.[[Key]] is "type", then let module type + be entry.[[Value]]. Otherwise let module type be undefined.

                21. + +
                22. Let resolved module script be moduleMap[url / + module type]. (This entry must exist for us to have + gotten to this point.)

                23. Assert: resolved module script is a module script (i.e., is not null or "fetching").

                24. @@ -94571,6 +94726,9 @@ enum DOMParserSupportedType {
                25. Let base URL be initiating script's base URL.

                26. +
                27. Assert: base URL is not null, as initiating script is a + classic script or a JavaScript module script.

                28. +
                29. Let fetch options be a script fetch options whose cryptographic nonce is initiating @@ -124038,6 +124196,9 @@ INSERT INTERFACES HERE

                  [CSSCOLORADJUST]
                  CSS Color Adjustment Module, E. Etemad, R. Atanassov, R. Lillesveen, T. Atkins. W3C.
                  +
                  [CSSCONSTRUCTORS]
                  +
                  Constructable Stylesheet Objects, T. Atkins, E. Willigers, R. Z. Amni.
                  +
                  [CSSDISPLAY]
                  CSS Display, T. Atkins, E. Etemad. W3C.
                  From 3338fffd32ac8f6fa5f1ea87d630d1b3d0643edc Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 29 Oct 2020 11:51:53 -0700 Subject: [PATCH 31/58] Fix up bad merge where validate-requested-module-specifiers got place in the wrong spot --- source | 114 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/source b/source index 335530697f0..a820a48635d 100644 --- a/source +++ b/source @@ -90619,62 +90619,6 @@ document.querySelector("button").addEventListener("click", bound);
              7. -

                To create a CSS module script, given a - string source and an environment settings object settings:

                - -
                  -
                1. Let script be a new module script that this algorithm will - subsequently initialize.

                2. - -
                3. Set script's settings object to settings.

                4. - -
                5. Set script's base URL and - fetch options to null.

                6. - -
                7. Set script's parse error and - error to rethrow to null.

                8. - -
                9. Let sheet be the result of calling the CSSStyleSheet constructor - with no arguments.

                10. - -
                11. -

                  Call sheet.replaceSync(source).

                  - -

                  If this throws an exception, set script's parse error to that exception, and return - script.

                  - -

                  CSSStyleSheet.replaceSync will throw if source contains - any @import references. This is by-design for now because there is not - yet an agreement on how to handle these for CSS module scripts; therefore they are blocked altogether - until a consensus is reached.

                  -
                12. - -
                13. Set script's record to the result - of creating a synthetic - module record with a default export of sheet with settings.

                  -
                14. - -
                15. Return script.

                16. -
                - -

                To create a synthetic module record with a default export of a JavaScript value - value with an environment settings object settings:

                - -
                  -
                1. -

                  Return CreateSyntheticModule(« "default" », the following steps, - settings's Realm, - value) with the following steps given module as an argument:

                  - -
                    -
                  1. SetSyntheticModuleExport(module, "default", - module.[[HostDefined]]).
                  2. -
                  -
                2. -
                -
              8. For each ModuleRequest record requested of result.[[RequestedModules]]:

                @@ -90718,6 +90662,64 @@ document.querySelector("button").addEventListener("click", bound);
              9. Return script.

              + + +

              To create a CSS module script, given a + string source and an environment settings object settings:

              + +
                +
              1. Let script be a new module script that this algorithm will + subsequently initialize.

              2. + +
              3. Set script's settings object to settings.

              4. + +
              5. Set script's base URL and + fetch options to null.

              6. + +
              7. Set script's parse error and + error to rethrow to null.

              8. + +
              9. Let sheet be the result of calling the CSSStyleSheet constructor + with no arguments.

              10. + +
              11. +

                Call sheet.replaceSync(source).

                + +

                If this throws an exception, set script's parse error to that exception, and return + script.

                + +

                CSSStyleSheet.replaceSync will throw if source contains + any @import references. This is by-design for now because there is not + yet an agreement on how to handle these for CSS module scripts; therefore they are blocked altogether + until a consensus is reached.

                +
              12. + +
              13. Set script's record to the result + of creating a synthetic + module record with a default export of sheet with settings.

                +
              14. + +
              15. Return script.

              16. +
              + +

              To create a synthetic module record with a default export of a JavaScript value + value with an environment settings object settings:

              + +
                +
              1. +

                Return CreateSyntheticModule(« "default" », the following steps, + settings's Realm, + value) with the following steps given module as an argument:

                + +
                  +
                1. SetSyntheticModuleExport(module, "default", + module.[[HostDefined]]).
                2. +
                +
              2. +
              +
              Calling scripts

              To run a classic script given a classic script script From 3c94b3151c45c6fdbdcd0c21ce93b899ae68f7ba Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 12 Nov 2020 14:14:13 -0800 Subject: [PATCH 32/58] Review feedback: use tuple instead of pair, improve module map definition, use 'javascript' instead of undefined, fix indents. --- source | 101 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/source b/source index 17b3852611d..3c9db84e481 100644 --- a/source +++ b/source @@ -2187,7 +2187,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

            31. surrogate
            32. scalar value
            33. tuple
            34. -
            35. pair
            36. noncharacter
            37. string, code unit, @@ -2869,7 +2868,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

              Users agents that support JavaScript must also implement ECMAScript Internationalization API.

              -

              User agents that support JavaScript must also implement the import assertions +

              User agents that support JavaScript must also implement the Import Assertions proposal. The following term is defined there, and used in this specification:

              @@ -90191,13 +90190,13 @@ document.querySelector("button").addEventListener("click", bound);
              1. Let url be the result of resolving - a module specifier given referrer and - moduleRequst.[[Specifier]].

              2. + a module specifier given referrer and moduleRequest.[[Specifier]]. +

                -
              3. Assert: url is never failure, because resolving a module specifier must have been previously successful with these same two - arguments.

              4. +
              5. Assert: url is never failure, because resolving a module specifier must have been previously successful with these same two + arguments.

              6. Assert: visited set contains url.

              7. @@ -90234,17 +90233,17 @@ document.querySelector("button").addEventListener("click", bound);
              8. Let moduleMap be module map settings object's module map.

              9. -
              10. If moduleMap[url / undefined] is +

              11. If moduleMap[(url, "javascript")] 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.

              12. -
              13. If moduleMap[url / undefined] exists, - asynchronously complete this algorithm with moduleMap[url / undefined], and - return.

              14. +
              15. If moduleMap[(url, "javascript")] exists, asynchronously complete this algorithm with + moduleMap[(url, "javascript")], and return.

              16. -
              17. Set moduleMap[url / undefined] to - "fetching".

                +
              18. Set moduleMap[(url, "javascript")] to "fetching".

              19. Let request be a new request whose url is url, JavaScript MIME type,

              20. -

                then set moduleMap[url / undefined] to - null, asynchronously complete this algorithm with null, and return.

                +

                then set moduleMap[(url, "javascript")] to null, asynchronously complete this algorithm with null, and + return.

              21. Let source text be the result of UTF-8 @@ -90305,9 +90305,9 @@ document.querySelector("button").addEventListener("click", bound); data-x="concept-response-url">url, and options.

              22. -

                Set moduleMap[url / undefined] to - module script, and asynchronously complete this algorithm with module - script.

                +

                Set moduleMap[(url, "javascript")] to module script, and asynchronously complete this + algorithm with module script.

                It is intentional that the module map is keyed by the request URL, whereas the moduleScript would have been marked as itself having a parse error.)

              23. -
              24. Let childModule be moduleMap[childURL / undefined]. -

              25. +
              26. Let childModule be moduleMap[(childURL, "javascript")].

              27. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module @@ -91238,20 +91238,23 @@ dictionary PromiseRejectionEventInit : EventInit {

            38. -

              A module map is a map keyed by - URL record / module type string pairs whose values are - either a module script, null (used to represent failed fetches), or a placeholder - value "fetching". Module maps are - used to ensure that imported JavaScript modules are only fetched, parsed, and evaluated once per - Document or worker. Currently only JavaScript - module scripts are supported, so the module type will always - be null until additional module types are introduced.

              +

              A module map is a map keyed by tuples consisting of a URL record and a string. + The URL record is the request URL at which + the module was fetched, and the string indicates the type of the module (e.g. "javascript"). The module map's values are either a module + script, null (used to represent failed fetches), or a placeholder value "fetching". Module maps are used to ensure + that imported JavaScript modules are only fetched, parsed, and evaluated once per + Document or worker . Currently only JavaScript module scripts are supported, so the module type will always be + "javascript" until additional module types are introduced.

              -

              Since module maps are keyed by URL / module type, the +

              Since module maps are keyed by (URL, module type), the following code will create three separate entries in the module map, since it - results in three different URL/module type pairs (all with null type): -

              + results in three different (URL, module type) tuples (all with null + type):

              import "https://example.com/module.mjs";
               import "https://example.com/module.mjs#map-buster";
              @@ -91277,24 +91280,24 @@ import "https://example.com/foo/../module2.mjs";
              data-x="SharedWorker">shared workers are keyed by their parsed constructor url.

              -

              Once additional module types are introduced, it will be possible to have multiple map entries - for a single URL since module type is also part of the module map key. For - example, once JSON modules are introduced the following code will create two separate entries in - the module map (the type is undefined for the first, and - "json" for the second): +

              Once additional module types are introduced, it will be possible to have multiple map entries + for a single URL since module type is also part of the module map key. For + example, once JSON modules are introduced the following code will create two separate entries in + the module map (the type is "javascript" for the first, and + "json" for the second): -

              import "https://example.com/module";
              +   
              import "https://example.com/module";
               import "https://example.com/module" assert { type: "json" };
              -

              In theory, this means that two separate fetches and two separate module evaluations would be - performed. In practice, due to the memory cache the resource will only be fetched once. - Additionally, as long as all module types are mutually exclusive, the module type check in - fetch a single module script will fail for at least one of the imports, so at most - one module evaluation will occur.

              +

              In theory, this means that two separate fetches and two separate module evaluations would be + performed. In practice, due to the memory cache the resource will only be fetched once. + Additionally, as long as all module types are mutually exclusive, the module type check in + fetch a single module script will fail for at least one of the imports, so at most + one module evaluation will occur.

              -

              The purpose of including the type in the module map key is so that an import - with the wrong type assertion does not prevent a different import of the same specifier but with - the correct type from succeeding.

              +

              The purpose of including the type in the module map key is so that an import + with the wrong type assertion does not prevent a different import of the same specifier but with + the correct type from succeeding.

              @@ -91536,9 +91539,9 @@ import "https://example.com/module" assert { type: "json" }; same two arguments (either while creating the corresponding module script, or in fetch an import() module script graph).

            39. -
            40. Let resolved module script be moduleMap[url / undefined]. - (This entry must exist for us to have gotten to this point.) -

            41. +
            42. Let resolved module script be moduleMap[(url, "javascript")]. (This entry must exist for us to + have gotten to this point.)

            43. Assert: resolved module script is a module script (i.e., is not null or "fetching").

            44. From 9da92b56819d25d2c066adc98c1c699f43108559 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 13 Nov 2020 14:28:02 -0800 Subject: [PATCH 33/58] Review feedback: Link to memory cache issue, null --> 'javascript' type, misc whitespace issues. --- source | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/source b/source index 3c9db84e481..b6bc29bb4b0 100644 --- a/source +++ b/source @@ -89761,8 +89761,7 @@ document.querySelector("button").addEventListener("click", bound);
              1. Let url be the result of resolving a - module specifier given base URL and moduleRequest.[[Specifier]].

                -
              2. + module specifier given base URL and moduleRequest.[[Specifier]].

              3. If url is failure, then asynchronously complete this algorithm with null, and return.

              4. @@ -90129,8 +90128,7 @@ document.querySelector("button").addEventListener("click", bound);
                1. Let url be the result of resolving - data-x="concept-script-base-url">base URL and requested.[[Specifier]].

                  -
                2. + data-x="concept-script-base-url">base URL and requested.[[Specifier]].

                3. Assert: url is never failure, because resolving a module specifier must have been

                  the result of extracting a MIME type from response's header list is not a JavaScript MIME type,

                4. - +

                  then set moduleMap[(url, "javascript")] to null, asynchronously complete this algorithm with null, and @@ -91253,8 +91251,8 @@ dictionary PromiseRejectionEventInit : EventInit {

                  Since module maps are keyed by (URL, module type), the following code will create three separate entries in the module map, since it - results in three different (URL, module type) tuples (all with null - type):

                  + results in three different (URL, module type) tuples (all with "javascript" type):

                  import "https://example.com/module.mjs";
                   import "https://example.com/module.mjs#map-buster";
                  @@ -91290,8 +91288,9 @@ import "https://example.com/foo/../module2.mjs";
                  import "https://example.com/module" assert { type: "json" };

                  In theory, this means that two separate fetches and two separate module evaluations would be - performed. In practice, due to the memory cache the resource will only be fetched once. - Additionally, as long as all module types are mutually exclusive, the module type check in + performed. In practice, due to the due to the as-yet-unspecified memory cache (see issue #6110) the resource will only be fetched + once. Additionally, as long as all module types are mutually exclusive, the module type check in fetch a single module script will fail for at least one of the imports, so at most one module evaluation will occur.

                  @@ -91531,8 +91530,7 @@ import "https://example.com/module" assert { type: "json" }; data-x="concept-settings-object-module-map">module map.

                5. Let url be the result of resolving a - module specifier given base URL and moduleRequest.[[Specifier]].

                  -
                6. + module specifier given base URL and moduleRequest.[[Specifier]].

                7. Assert: url is never failure, because resolving a module specifier must have been previously successful with these @@ -91540,8 +91538,8 @@ import "https://example.com/module" assert { type: "json" }; corresponding module script, or in fetch an import() module script graph).

                8. Let resolved module script be moduleMap[(url, "javascript")]. (This entry must exist for us to - have gotten to this point.)

                9. + data-x="">"javascript")]. (This entry must exist for us + to have gotten to this point.)

                10. Assert: resolved module script is a module script (i.e., is not null or "fetching").

                11. From 26c2b813f30b404c2209f439fec219037935ffaf Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 13 Nov 2020 14:31:27 -0800 Subject: [PATCH 34/58] Remove duplicated words --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index b6bc29bb4b0..330254c2b6e 100644 --- a/source +++ b/source @@ -91288,7 +91288,7 @@ import "https://example.com/foo/../module2.mjs"; import "https://example.com/module" assert { type: "json" };

                  In theory, this means that two separate fetches and two separate module evaluations would be - performed. In practice, due to the due to the as-yet-unspecified memory cache (see issue #6110) the resource will only be fetched once. Additionally, as long as all module types are mutually exclusive, the module type check in fetch a single module script will fail for at least one of the imports, so at most From 4ad7d2d0a6a9678ec6f48fd2103427ded4f7ca13 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Mon, 16 Nov 2020 13:09:17 -0800 Subject: [PATCH 35/58] Move quotes outside of elements. --- source | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/source b/source index 330254c2b6e..b9761f489af 100644 --- a/source +++ b/source @@ -89768,13 +89768,13 @@ document.querySelector("button").addEventListener("click", bound);

                12. If moduleRequest.[[Assertions]] has a Record entry such - that entry.[[Key]] is "type" then asynchronously complete this + that entry.[[Key]] is "type" then asynchronously complete this algorithm with null, and return.

                  Currently no non-JS module types are supported, so we conservatively fail if any type - assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module matches the type expected by the importer.

                  Assertions with unknown keys are ignored.

                  @@ -90231,17 +90231,17 @@ document.querySelector("button").addEventListener("click", bound);
                13. Let moduleMap be module map settings object's module map.

                14. -
                15. If moduleMap[(url, "javascript")] is +

                16. If moduleMap[(url, "javascript")] 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.

                17. -
                18. If moduleMap[(url, "javascript")]

                  If moduleMap[(url, "javascript")] exists, asynchronously complete this algorithm with - moduleMap[(url, "javascript")], and return.

                19. + moduleMap[(url, "javascript")], and return.

                  -
                20. Set moduleMap[(url, "javascript")] to "fetching".

                  +
                21. Set moduleMap[(url, "javascript")] to "fetching".

                22. Let request be a new request whose url is url, JavaScript MIME type,

                23. -

                  then set moduleMap[(url, "javascript")] to null, asynchronously complete this algorithm with null, and +

                  then set moduleMap[(url, "javascript")] to null, asynchronously complete this algorithm with null, and return.

                  @@ -90303,8 +90303,8 @@ document.querySelector("button").addEventListener("click", bound); data-x="concept-response-url">url, and options.

                24. -

                  Set moduleMap[(url, "javascript")] to module script, and asynchronously complete this +

                  Set moduleMap[(url, "javascript")] to module script, and asynchronously complete this algorithm with module script.

                  It is intentional that the module map is keyed by the moduleScript would have been marked as itself having a parse error.)

                25. -
                26. Let childModule be moduleMap[(childURL, "javascript")].

                27. +
                28. Let childModule be moduleMap[(childURL, "javascript")].

                29. Assert: childModule is a module script (i.e., it is not "fetching" or null); by now all module @@ -90487,8 +90487,8 @@ document.querySelector("button").addEventListener("click", bound);

                30. If url is failure, or if requested.[[Assertions]] has a - Record entry such that entry.[[Key]] is "type" then:

                  + Record entry such that entry.[[Key]] is "type" then:

                  1. Let error be a new TypeError exception.

                  2. @@ -90508,8 +90508,8 @@ document.querySelector("button").addEventListener("click", bound); it impossible to ever contemplate linking the module later.

                    Currently no non-JS module types are supported, so we conservatively fail if any type - assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module matches the type expected by the importer.

                    Assertions with unknown keys are ignored.

                    @@ -91239,20 +91239,20 @@ dictionary PromiseRejectionEventInit : EventInit {

                    A module map is a map keyed by tuples consisting of a URL record and a string. The URL record is the request URL at which - the module was fetched, and the string indicates the type of the module (e.g. "javascript"). The module map's values are either a module + the module was fetched, and the string indicates the type of the module (e.g. "javascript"). The module map's values are either a module script, null (used to represent failed fetches), or a placeholder value "fetching". Module maps are used to ensure that imported JavaScript modules are only fetched, parsed, and evaluated once per Document or worker . Currently only JavaScript module scripts are supported, so the module type will always be - "javascript" until additional module types are introduced.

                    + "javascript" until additional module types are introduced.

                    Since module maps are keyed by (URL, module type), the following code will create three separate entries in the module map, since it - results in three different (URL, module type) tuples (all with "javascript" type):

                    + results in three different (URL, module type) tuples (all with "javascript" type):

                    import "https://example.com/module.mjs";
                     import "https://example.com/module.mjs#map-buster";
                    @@ -91281,8 +91281,8 @@ import "https://example.com/foo/../module2.mjs";

                    Once additional module types are introduced, it will be possible to have multiple map entries for a single URL since module type is also part of the module map key. For example, once JSON modules are introduced the following code will create two separate entries in - the module map (the type is "javascript" for the first, and - "json" for the second): + the module map (the type is "javascript" for the first, and + "json" for the second):

                    import "https://example.com/module";
                     import "https://example.com/module" assert { type: "json" };
                    @@ -91537,8 +91537,8 @@ import "https://example.com/module" assert { type: "json" };
                    same two arguments (either while creating the corresponding module script, or in fetch an import() module script graph).

                    -
                  3. Let resolved module script be moduleMap[(url, "javascript")]. (This entry must exist for us +

                  4. Let resolved module script be moduleMap[(url, "javascript")]. (This entry must exist for us to have gotten to this point.)

                  5. Assert: resolved module script is a module script (i.e., is not From 614a9f4b94dac773329b6ae9a153d35eeb7611e6 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Mon, 30 Nov 2020 13:06:55 -0800 Subject: [PATCH 36/58] Add HostGetSupportedAssertions integration --- source | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/source b/source index b9761f489af..d4c4b71d869 100644 --- a/source +++ b/source @@ -2869,11 +2869,12 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute Internationalization API.

                    User agents that support JavaScript must also implement the Import Assertions - proposal. The following term is defined there, and used in this specification:

                    • The ModuleRequest Record specification type
                    • +
                    • The HostGetSupportedAssertions abstract operation
                    @@ -89766,19 +89767,20 @@ document.querySelector("button").addEventListener("click", bound);
                  6. If url is failure, then asynchronously complete this algorithm with null, and return.

                  7. +
                  8. Assert: moduleRequest.[[Assertions]] does not contain any Record + entry such that entry.[[Key]] is not "type", because + we only asked for "type" assertions in + HostGetSupportedAssertions.

                  9. +
                  10. If moduleRequest.[[Assertions]] has a Record entry such that entry.[[Key]] is "type" then asynchronously complete this algorithm with null, and return.

                    -
                    -

                    Currently no non-JS module types are supported, so we conservatively fail if any type - assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module - matches the type expected by the importer.

                    - -

                    Assertions with unknown keys are ignored.

                    -
                    +

                    Currently no non-JS module types are supported, so we conservatively fail if any + type assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module + matches the type expected by the importer.

                  11. Fetch a single module script given url, settings @@ -90476,6 +90478,11 @@ document.querySelector("button").addEventListener("click", bound);

                31. +
                32. Assert: requested.[[Assertions]] does not contain any Record + entry such that entry.[[Key]] is not "type", because + we only asked for "type" assertions in + HostGetSupportedAssertions.

                33. +
                34. For each ModuleRequest record requested of result.[[RequestedModules]]:

                  @@ -90511,8 +90518,6 @@ document.querySelector("button").addEventListener("click", bound); assertion is provided. When support is added for other module types, the "type" assertion will be used to check that the type of the fetched module matches the type expected by the importer.

                  - -

                  Assertions with unknown keys are ignored.

                35. @@ -91551,6 +91556,17 @@ import "https://example.com/module" assert { type: "json" }; data-x="concept-script-record">record.

                +
                HostGetSupportedAssertions()
                + +

                The Import Assertions proposal contains an implementation-defined + HostGetSupportedAssertions abstract operation. + User agents must use the following implementation:

                + +
                  +
                1. Return a new List whose sole item is the string + "type".

                2. +
                +

                Event loops

                From 2fc3616a44156363f9abf7a297b60ea4dc15bd7c Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 1 Dec 2020 10:27:29 -0800 Subject: [PATCH 37/58] Fix indentation/spacing. Use short list notation. --- source | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source b/source index d4c4b71d869..8aedda4eb68 100644 --- a/source +++ b/source @@ -91558,14 +91558,13 @@ import "https://example.com/module" assert { type: "json" };
                HostGetSupportedAssertions()
                -

                The Import Assertions proposal contains an implementation-defined - HostGetSupportedAssertions abstract operation. - User agents must use the following implementation:

                +

                The Import Assertions proposal contains an implementation-defined + HostGetSupportedAssertions abstract operation. + User agents must use the following implementation:

                -
                  -
                1. Return a new List whose sole item is the string - "type".

                2. -
                +
                  +
                1. Return « "type" ».

                2. +
                From a9eed9bc2e2ddb868eeddc7d957bb611b70229f3 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 29 Dec 2020 15:03:05 -0800 Subject: [PATCH 38/58] Use two separate scripts in example so that at least one will actually evaluate --- source | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source b/source index 3f931e7d3c0..6dc73fef901 100644 --- a/source +++ b/source @@ -89808,8 +89808,12 @@ import "https://example.com/foo/../module2.mjs"; the module map (the type is "javascript" for the first, and "json" for the second): -
                import "https://example.com/module";
                -import "https://example.com/module" assert { type: "json" };
                +
                <script>
                +  import "https://example.com/module";
                +</script>
                +<script>
                +  import "https://example.com/module" assert { type: "json" };
                +</script>

                In theory, this means that two separate fetches and two separate module evaluations would be performed. In practice, due to the as-yet-unspecified memory cache (see issue Date: Tue, 29 Dec 2020 15:03:37 -0800 Subject: [PATCH 39/58] Add module type to visited set. --- source | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source b/source index 6dc73fef901..a20e1649dd2 100644 --- a/source +++ b/source @@ -88278,7 +88278,8 @@ document.querySelector("button").addEventListener("click", bound);

              5. If result is null, asynchronously complete this algorithm with null, and return.

              6. -
              7. Let visited set be « url ».

              8. +
              9. Let visited set be « (url, "javascript") + ».

              10. Fetch the descendants of and link result given settings object, @@ -88325,7 +88326,8 @@ document.querySelector("button").addEventListener("click", bound);

              11. If result is null, asynchronously complete this algorithm with null, and return.

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

              14. +
              15. Let visited set be « (url, "javascript") + ».

              16. Fetch the descendants of and link result given settings object, @@ -88352,7 +88354,8 @@ document.querySelector("button").addEventListener("click", bound);

                If result is not null, optionally perform the following steps:

                  -
                1. Let visited set be « url ».

                2. +
                3. Let visited set be « (url, "javascript") + ».

                4. Fetch the descendants of and link result given settings object, @@ -88580,7 +88583,8 @@ document.querySelector("button").addEventListener("click", bound);

                5. If result is null, asynchronously complete this algorithm with null, and return.

                6. -
                7. Let visited set be « url ».

                8. +
                9. Let visited set be « (url, "javascript") + ».

                10. Fetch the descendants of and link result given fetch client settings @@ -88671,14 +88675,14 @@ document.querySelector("button").addEventListener("click", bound);

                11. If visited set does not contain - url, then:

                  + (url, "javascript"), then:

                  1. Append requested to moduleRequests.

                  2. -
                  3. Append url to visited - set.

                  4. +
                  5. Append (url, "javascript") to visited set.

                @@ -88731,7 +88735,7 @@ document.querySelector("button").addEventListener("click", bound); arguments.

              17. Assert: visited set contains - url.

              18. + (url, "javascript").

              19. Fetch a single module script given url, fetch client settings object, destination, options, module map settings object, From fdc08f87501360b7c1b98d5027dd3129e64f62c5 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 31 Dec 2020 13:45:25 -0800 Subject: [PATCH 40/58] Clarify that memory cache mitigating violation of import assertions spec recommendation is not a sure thing. --- source | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/source b/source index a20e1649dd2..e93294b0b65 100644 --- a/source +++ b/source @@ -89819,12 +89819,18 @@ import "https://example.com/foo/../module2.mjs"; import "https://example.com/module" assert { type: "json" }; </script> -

                In theory, this means that two separate fetches and two separate module evaluations would be - performed. In practice, due to the as-yet-unspecified memory cache (see issue #6110) the resource will only be fetched - once. Additionally, as long as all module types are mutually exclusive, the module type check in - fetch a single module script will fail for at least one of the imports, so at most - one module evaluation will occur.

                +

                This can result in two separate fetches and two separate module evaluations being performed. + This is a willful violation of a constraint recommended (but not required) by the import + assertions specification stating that each call to HostResolveImportedModule with + the same referencingScriptOrModule, moduleRequest.[[Specifier]] pair must return the + same Module Record.

                + +

                In practice, due to the as-yet-unspecified memory cache (see issue #6110) the resource may only be fetched + once in WebKit and Blink-based browsers. Additionally, as long as all module types are mutually + exclusive, the module type check in fetch a single module script will fail for at + least one of the imports, so at most one module evaluation will occur.

                The purpose of including the type in the module map key is so that an import with the wrong type assertion does not prevent a different import of the same specifier but with From 9ec7c7ea0f28ee15ceffb6820122939a026214dd Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Wed, 10 Mar 2021 17:11:47 -0800 Subject: [PATCH 41/58] Add class='XXX' to note about the memory cache --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 29c86c39aae..b76416cec1d 100644 --- a/source +++ b/source @@ -90318,7 +90318,7 @@ import "https://example.com/foo/../module2.mjs"; same Module Record.

                -

                In practice, due to the as-yet-unspecified memory cache (see issue In practice, due to the as-yet-unspecified memory cache (see issue #6110) the resource may only be fetched once in WebKit and Blink-based browsers. Additionally, as long as all module types are mutually exclusive, the module type check in fetch a single module script will fail for at From f61b01e738ec381160289b36186cdf296d4a2ee6 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 24 Jun 2021 16:56:30 -0700 Subject: [PATCH 42/58] Fix merge issues --- source | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/source b/source index 33b645a4f2a..0232d6173f1 100644 --- a/source +++ b/source @@ -90767,7 +90767,7 @@ document.querySelector("button").addEventListener("click", bound); data-x="">error"; or

              20. response's status is not an - ok status; or

              21. + ok status.

                then set moduleMap[(url, module @@ -90780,9 +90780,10 @@ document.querySelector("button").addEventListener("click", bound);

              22. Let module script be null.

              23. If MIME type is a JavaScript MIME type and module type - is undefined, then set module script to the result of creating a JavaScript - module script given source text, module map settings object, - response's url, and options.

                + is "javascript", then set module script to the result of + creating a JavaScript module script given source text, module map + settings object, response's url, and + options.

              24. If MIME type is text/css and module type is @@ -92084,7 +92085,7 @@ import "https://example.com/foo/../module2.mjs"; TypeError, [[Target]]: empty }.

              25. Perform FinishDynamicImport(referencingScriptOrModule, - specifier, promiseCapability, completion).

              26. + moduleRequest, promiseCapability, completion).

              27. Return.

              From dc30b4c659689442ac12fbe7f0bec8689456d5ff Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 25 Jun 2021 09:54:55 -0700 Subject: [PATCH 43/58] Remove unneeded 'pair' definition --- source | 1 - 1 file changed, 1 deletion(-) diff --git a/source b/source index 0232d6173f1..392ea14559c 100644 --- a/source +++ b/source @@ -2163,7 +2163,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
            45. surrogate
            46. scalar value
            47. tuple
            48. -
            49. pair
            50. noncharacter
            51. string, code unit, From e6eaa6d407a5003375ab3781cb739a9bbe0f4040 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Fri, 25 Jun 2021 10:28:00 -0700 Subject: [PATCH 44/58] Update CSSStyleSheet links now that constructed stylesheets have been merged into CSSOM spec --- source | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/source b/source index 392ea14559c..94934f269cb 100644 --- a/source +++ b/source @@ -3666,6 +3666,15 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
            52. origin-clean flag
            53. +
            54. + CSSStyleSheet interface and its + methods: +
                +
              • CSSStyleSheet constructor
              • +
              • CSSStyleSheet.replaceSync
              • +
              +
            55. CSS style sheet set
            56. CSS style sheet set name
            57. preferred CSS style sheet set name
            58. @@ -3773,13 +3782,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
              • '::file-selector-button'
              - -

              The following features are defined in Constructable Stylesheet Objects:

              - -
                -
              • CSSStyleSheet constructor
              • -
              • CSSStyleSheet.replaceSync
              • -
              @@ -124466,9 +124468,6 @@ INSERT INTERFACES HERE
              [CSSCOLORADJUST]
              CSS Color Adjustment Module, E. Etemad, R. Atanassov, R. Lillesveen, T. Atkins. W3C.
              -
              [CSSCONSTRUCTORS]
              -
              Constructable Stylesheet Objects, T. Atkins, E. Willigers, R. Z. Amni.
              -
              [CSSDISPLAY]
              CSS Display, T. Atkins, E. Etemad. W3C.
              From 1459080a4fc9c519e68f55958dd1049b0197b0a2 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Thu, 8 Jul 2021 10:12:34 -0700 Subject: [PATCH 45/58] Link to spec steps for constructing CSSStyleSheet and replacing contents, instead of going through the interface methods --- source | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/source b/source index 94934f269cb..8b7ef1ebaba 100644 --- a/source +++ b/source @@ -3648,6 +3648,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
            59. create a CSS style sheet
            60. remove a CSS style sheet
            61. associated CSS style sheet
            62. +
            63. create a constructed CSSStyleSheet
            64. +
            65. synchronously replace the rules of a CSSStyleSheet
            66. CSS style sheets and their @@ -3666,15 +3668,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
            67. origin-clean flag
            68. -
            69. - CSSStyleSheet interface and its - methods: -
                -
              • CSSStyleSheet constructor
              • -
              • CSSStyleSheet.replaceSync
              • -
              -
            70. CSS style sheet set
            71. CSS style sheet set name
            72. preferred CSS style sheet set name
            73. @@ -91036,21 +91029,21 @@ document.querySelector("button").addEventListener("click", bound);
            74. Set script's parse error and error to rethrow to null.

            75. -
            76. Let sheet be the result of calling the CSSStyleSheet constructor - with no arguments.

            77. +
            78. Let sheet be the result of running the steps to create a constructed + CSSStyleSheet with no arguments.

            79. -

              Call sheet.replaceSync(source).

              +

              Run the steps to synchronously replace the rules of a CSSStyleSheet on + sheet given source.

              If this throws an exception, set script's parse error to that exception, and return script.

              -

              CSSStyleSheet.replaceSync will throw if source contains - any @import references. This is by-design for now because there is not - yet an agreement on how to handle these for CSS module scripts; therefore they are blocked altogether - until a consensus is reached.

              +

              The steps to synchronously replace the rules of a CSSStyleSheet + will throw if source contains any @import references. This is + by-design for now because there is not yet an agreement on how to handle these for CSS module + scripts; therefore they are blocked altogether until a consensus is reached.

            80. Set script's record to the result From aa7cce8c88c7487baf2f1aecc08e66490bc1e140 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 11:29:49 -0700 Subject: [PATCH 46/58] Link to JSON modules proposal for synthetic module record stuff. Fix instances of using udefined instead of 'javascript' for module type check. --- source | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/source b/source index 8b7ef1ebaba..323050b02b4 100644 --- a/source +++ b/source @@ -2645,9 +2645,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

            81. frozen array and creating a frozen array
            82. create a new object implementing the interface
            83. -
            84. CreateSyntheticModule
            85. -
            86. SetSyntheticModuleExport
            87. -
            88. Synthetic Module Record
            89. callback this value
            90. converting between Web IDL types and JS types
            91. invoking and @@ -2890,6 +2887,15 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
            92. The ModuleRequest Record specification type
            93. The HostGetSupportedAssertions abstract operation
            94. + +

              The following terms are defined in the JSON modules proposal and used in this + specification:

              + +
                +
              • CreateSyntheticModule
              • +
              • SetSyntheticModuleExport
              • +
              • Synthetic Module Record
              • +
              WebAssembly
              @@ -90695,9 +90701,9 @@ document.querySelector("button").addEventListener("click", bound);
            -
          7. Assert: module type is either undefined or "css". - Otherwise we would not have reached this point because a failure would have been raised when - inspecting moduleRequest.[[Assertions]] in

            Assert: module type is either "javascript" or "css". Otherwise we would not have reached this point because a failure would + have been raised when inspecting moduleRequest.[[Assertions]] in create a JavaScript module script or fetch an import() module script graph.

          8. @@ -90987,8 +90993,8 @@ document.querySelector("button").addEventListener("click", bound); data-x="">javascript".

          9. -

            If url is failure, or if module type is neither undefined nor - "css", then:

            +

            If url is failure, or if module type is neither "javascript" nor "css", then:

            1. Let error be a new TypeError exception.

            2. @@ -124649,6 +124655,9 @@ INSERT INTERFACES HERE
              [JSIMPORTASSERTIONS]
              Import Assertions. Ecma International.
              +
              [JSJSONMODULES]
              +
              JSON Modules. Ecma International.
              +
              [JSINTL]
              ECMAScript Internationalization API Specification. Ecma International.
              From 879907bcb44ab18892a9fa1dae9f34a26c1e4695 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 12:08:55 -0700 Subject: [PATCH 47/58] Check MIME type essence instead of the whole MIME type --- source | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source b/source index 323050b02b4..0926e6a08c8 100644 --- a/source +++ b/source @@ -2450,6 +2450,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
              • MIME type
              • +
              • MIME type essence
              • valid MIME type string
              • valid MIME type string with no parameters
              • HTML MIME type
              • @@ -90786,10 +90787,10 @@ document.querySelector("button").addEventListener("click", bound); options.

                -
              • If MIME type is text/css and module type is - "css", then set module script to the result of creating - a CSS module script given source text and module map settings - object.

              • +
              • If the MIME type essence of MIME type is text/css and + module type is "css", then set module script to the + result of creating a CSS module script given source text and module + map settings object.

              • Set moduleMap[(url, module From 65867f3d3f455e78349294b93e132ce11d102fb7 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 12:21:33 -0700 Subject: [PATCH 48/58] HostGetSupportedAssertions -> HostGetSupportedImportAssertions --- source | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source b/source index 0926e6a08c8..0458a94731e 100644 --- a/source +++ b/source @@ -2886,7 +2886,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

                • The ModuleRequest Record specification type
                • -
                • The HostGetSupportedAssertions abstract operation
                • +
                • The HostGetSupportedImportAssertions abstract operation

                The following terms are defined in the JSON modules proposal and used in this @@ -90219,7 +90219,7 @@ document.querySelector("button").addEventListener("click", bound);

              • Assert: moduleRequest.[[Assertions]] does not contain any Record entry such that entry.[[Key]] is not "type", because we only asked for "type" assertions in - HostGetSupportedAssertions.

              • + HostGetSupportedImportAssertions.

              • If moduleRequest.[[Assertions]] has a Record entry such that entry.[[Key]] is "type", then let module @@ -90977,7 +90977,7 @@ document.querySelector("button").addEventListener("click", bound);

              • Assert: requested.[[Assertions]] does not contain any Record entry such that entry.[[Key]] is not "type", because we only asked for "type" assertions in - HostGetSupportedAssertions.

              • + HostGetSupportedImportAssertions.

              • For each ModuleRequest record @@ -92216,11 +92216,12 @@ import "https://example.com/foo/../module2.mjs"; data-x="concept-script-record">record.

            -
            HostGetSupportedAssertions()
            +
            HostGetSupportedImportAssertions()

            The Import Assertions proposal contains an implementation-defined - HostGetSupportedAssertions abstract operation. - User agents must use the following implementation:

            + HostGetSupportedImportAssertions + abstract operation. User agents must use the following implementation:

            1. Return « "type" ».

            2. From 1992a635fe7622146641655392b10bf2304b2054 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 12:24:23 -0700 Subject: [PATCH 49/58] Fix ID of HostGetSupportedImportAssertions link --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 0458a94731e..e05a39f3c80 100644 --- a/source +++ b/source @@ -92216,7 +92216,7 @@ import "https://example.com/foo/../module2.mjs"; data-x="concept-script-record">record.

            -
            HostGetSupportedImportAssertions()
            +
            HostGetSupportedImportAssertions()

            The Import Assertions proposal contains an implementation-defined HostGetSupportedImportAssertions From b4b2e0db569d681d0b19bd321ee9d42fddfcbfc1 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 12:30:03 -0700 Subject: [PATCH 50/58] Pass empty dict to create a constructed stylesheet steps --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index e05a39f3c80..fff75438fb9 100644 --- a/source +++ b/source @@ -91037,7 +91037,7 @@ document.querySelector("button").addEventListener("click", bound); error to rethrow to null.

          10. Let sheet be the result of running the steps to create a constructed - CSSStyleSheet with no arguments.

          11. + CSSStyleSheet with an empty dictionary as the argument.

          12. Run the steps to synchronously replace the rules of a CSSStyleSheet on From 7b0e82083d86265297a6729d7d36ff35b420d498 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 12:34:38 -0700 Subject: [PATCH 51/58] Formatting for CreateSyntheticModule argument --- source | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source b/source index fff75438fb9..2f1d6ee37e0 100644 --- a/source +++ b/source @@ -91066,8 +91066,8 @@ document.querySelector("button").addEventListener("click", bound);

            1. -

              Return CreateSyntheticModule(« "default" », the following steps, - settings's Realm, +

              Return CreateSyntheticModule(« "default" », the following + steps, settings's Realm, value) with the following steps given module as an argument:

                From 64142645a82b544d3e1830e8ae6f7e26db9e36d8 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 12:40:26 -0700 Subject: [PATCH 52/58] 'javascript' instead of undefined --- source | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source b/source index 2f1d6ee37e0..50798462ff9 100644 --- a/source +++ b/source @@ -92200,7 +92200,8 @@ import "https://example.com/foo/../module2.mjs";
              1. If moduleRequest.[[Assertions]] has a Record entry such that entry.[[Key]] is "type", then let module type - be entry.[[Value]]. Otherwise let module type be undefined.

              2. + be entry.[[Value]]. Otherwise let module type be "javascript".

              3. Let resolved module script be moduleMap[(url, module type)]. (This entry must exist for us to have gotten to From 14971c005388ad17ff2919dc3a79551fceac3837 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 12:55:43 -0700 Subject: [PATCH 53/58] Split up code sample --- source | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source b/source index 50798462ff9..cda04933594 100644 --- a/source +++ b/source @@ -91939,8 +91939,7 @@ import "https://example.com/foo/../module2.mjs";

                <script>
                   import "https://example.com/module";
                -</script>
                -<script>
                +</script>
                <script>
                   import "https://example.com/module" assert { type: "css" };
                 </script>
                From 4b1f0a0da63ef372017f1c57c1c80fa5059d43c5 Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Sat, 10 Jul 2021 13:17:25 -0700 Subject: [PATCH 54/58] Fix misc nits/typos --- source | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source b/source index cda04933594..7ddf6c3e980 100644 --- a/source +++ b/source @@ -90239,7 +90239,7 @@ document.querySelector("button").addEventListener("click", bound);
              4. If result is null, asynchronously complete this algorithm with null, and return.

              5. -
              6. Let visited set be « (url, module type)».

              7. +
              8. Let visited set be « (url, module type )».

              9. Fetch the descendants of and link result given settings object, @@ -90592,13 +90592,13 @@ document.querySelector("button").addEventListener("click", bound);

              10. If visited set does not contain - (url, module type)), then:

                + (url, module type), then:

                1. Append requested to moduleRequests.

                2. -
                3. Append (url, module type)) to +

                4. Append (url, module type) to visited set.

              11. @@ -90822,7 +90822,7 @@ document.querySelector("button").addEventListener("click", bound); error.

              12. If moduleScript's record is not a - Cyclic Module Record, return null.

                + Cyclic Module Record, then return null.

              13. Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

              14. @@ -91900,8 +91900,8 @@ dictionary PromiseRejectionEventInit : EventInitjavascript"). The module map's values are either a module script, null (used to represent failed fetches), or a placeholder value "fetching". Module maps are used to ensure - that imported JavaScript modules are only fetched, parsed, and evaluated once per - Document or worker .

                + that imported module scripts are only fetched, parsed, and evaluated once per + Document or worker.

                Since module maps are keyed by (URL, module type), the @@ -91944,10 +91944,10 @@ import "https://example.com/foo/../module2.mjs"; </script>

                This can result in two separate fetches and two separate module evaluations being performed. - This is a willful violation of a constraint recommended (but not required) by the import - assertions specification stating that each call to HostResolveImportedModule with - the same referencingScriptOrModule, moduleRequest.[[Specifier]] pair must return the - same Module Record. willful violation of a constraint recommended (but not required) by the + import assertions specification stating that each call to HostResolveImportedModule + with the same referencingScriptOrModule, moduleRequest.[[Specifier]] pair must return + the same Module Record.

                In practice, due to the as-yet-unspecified memory cache (see issue Date: Mon, 12 Jul 2021 13:26:04 -0400 Subject: [PATCH 55/58] Minor fixes, mostly spacing and quotes --- source | 90 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/source b/source index 7ddf6c3e980..2c9d0f87101 100644 --- a/source +++ b/source @@ -2890,13 +2890,13 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

                The following terms are defined in the JSON modules proposal and used in this - specification:

                + specification:

                -
                  -
                • CreateSyntheticModule
                • -
                • SetSyntheticModuleExport
                • -
                • Synthetic Module Record
                • -
                +
                  +
                • CreateSyntheticModule
                • +
                • SetSyntheticModuleExport
                • +
                • Synthetic Module Record
                • +
                WebAssembly
                @@ -58266,7 +58266,6 @@ interface HTMLScriptElement : HTMLElement { Authors should omit the type attribute instead of redundantly setting it.

                -
              15. Setting the attribute to an ASCII case-insensitive match for the string "module" means that the script is a module script. If it has a JavaScript MIME type, or if the script is embedded inline, then it will be @@ -58578,7 +58577,7 @@ o............A....e data-x="attr-script-nomodule">nomodule attribute will be ignored, and the script element with a type of "module" will be fetched and evaluated (as a JavaScript module - script). Conversely, older user agents will ignore the script element with a + script). Conversely, older user agents will ignore the script element with a type of "module", as that is an unknown script type for them — but they will have no problem fetching and evaluating the other script element (as a classic script), since they do not implement the @@ -90222,7 +90221,7 @@ document.querySelector("button").addEventListener("click", bound); HostGetSupportedImportAssertions.

              16. If moduleRequest.[[Assertions]] has a Record entry - such that entry.[[Key]] is "type", then let module + such that entry.[[Key]] is "type", then let module type be entry.[[Value]]. Otherwise let module type be "javascript".

              17. @@ -90239,7 +90238,7 @@ document.querySelector("button").addEventListener("click", bound);
              18. If result is null, asynchronously complete this algorithm with null, and return.

              19. -
              20. Let visited set be « (url, module type )».

              21. +
              22. Let visited set be « (url, module type) ».

              23. Fetch the descendants of and link result given settings object, @@ -90578,7 +90577,9 @@ document.querySelector("button").addEventListener("click", bound);

                1. Let url be the result of resolving - data-x="concept-script-base-url">base URL and requested.[[Specifier]].

                2. + a module specifier given module script's base URL and + requested.[[Specifier]].

                3. Assert: url is never failure, because resolving a module specifier must have been

                4. If moduleRequest.[[Assertions]] has a Record entry - such that entry.[[Key]] is "type", then let module + such that entry.[[Key]] is "type", then let module type be entry.[[Value]]. Otherwise let module type be "javascript".

                5. @@ -90643,8 +90644,8 @@ document.querySelector("button").addEventListener("click", bound);
                  1. Let url be the result of resolving - a module specifier given referrer and moduleRequest.[[Specifier]]. -

                  2. + a module specifier given referrer and + moduleRequest.[[Specifier]].

                  3. Assert: url is never failure, because resolving a module specifier must have been

                  4. If moduleRequest.[[Assertions]] has a Record entry - such that entry.[[Key]] is "type", then let module + such that entry.[[Key]] is "type", then let module type be entry.[[Value]]. Otherwise let module type be "javascript".

                  5. @@ -90692,8 +90693,8 @@ document.querySelector("button").addEventListener("click", bound);
                  6. If moduleRequest was given and moduleRequest.[[Assertions]] has a - Record entry such that entry.[[Key]] is "type", then:

                    + Record entry such that entry.[[Key]] is "type", then:

                    1. Assert: No more than one such Record exists.

                    2. @@ -90702,8 +90703,8 @@ document.querySelector("button").addEventListener("click", bound);
                  7. -
                  8. Assert: module type is either "javascript" or "css". Otherwise we would not have reached this point because a failure would +

                  9. Assert: module type is either "javascript" or "css". Otherwise we would not have reached this point because a failure would have been raised when inspecting moduleRequest.[[Assertions]] in create a JavaScript module script or fetch an import() module script graph.

                  10. @@ -90721,7 +90722,7 @@ document.querySelector("button").addEventListener("click", bound); moduleMap[url / module type], and return.

                  11. Set moduleMap[(url, module - type)] to "fetching".

                    + type)] to "fetching".

                  12. Let request be a new request whose URL is url, javascript", then set module script to the result of creating a JavaScript module script given source text, module map settings object, response's url, and - options.

                    -
                  13. + options.

                  14. If the MIME type essence of MIME type is text/css and - module type is "css", then set module script to the + module type is "css", then set module script to the result of creating a CSS module script given source text and module map settings object.

                  15. @@ -90822,7 +90822,7 @@ document.querySelector("button").addEventListener("click", bound); error.

                  16. If moduleScript's record is not a - Cyclic Module Record, then return null.

                    + Cyclic Module Record, then return null.

                  17. Let moduleRequests be the value of moduleScript's record's [[RequestedModules]] internal slot.

                  18. @@ -90836,11 +90836,11 @@ document.querySelector("button").addEventListener("click", bound); specifier">resolving a module specifier given moduleScript's base URL and moduleRequest.[[Specifier]]. (This will never fail, as otherwise moduleScript would have been marked as itself having a parse error.)

                    - + href="#validate-requested-module-specifiers">marked as itself having a parse + error.)

                  19. If moduleRequest.[[Assertions]] has a Record entry - such that entry.[[Key]] is "type", then let module + such that entry.[[Key]] is "type", then let module type be entry.[[Value]]. Otherwise let module type be "javascript".

                  20. @@ -90986,16 +90986,16 @@ document.querySelector("button").addEventListener("click", bound);
                    1. Let url be the result of resolving a module specifier given script's base - URL and requested.[[Specifier]].

                    2. + URL and requested.[[Specifier]].

                    3. If requested.[[Assertions]] has a Record entry such - that entry.[[Key]] is "type", then let module type + that entry.[[Key]] is "type", then let module type be entry.[[Value]]. Otherwise let module type be "javascript".

                    4. -

                      If url is failure, or if module type is neither "javascript" nor "css", then:

                      +

                      If url is failure, or if module type is neither "javascript" nor "css", then:

                      1. Let error be a new TypeError exception.

                      2. @@ -91019,8 +91019,6 @@ document.querySelector("button").addEventListener("click", bound);
                      3. Return script.

                      - -

                      To create a CSS module script, given a string source and an environment settings object settings:

                      @@ -91071,8 +91069,8 @@ document.querySelector("button").addEventListener("click", bound); value) with the following steps given module as an argument:

                        -
                      1. SetSyntheticModuleExport(module, "default", - module.[[HostDefined]]).
                      2. +
                      3. Perform ! SetSyntheticModuleExport(module, "default", module.[[HostDefined]]).
                    @@ -91932,22 +91930,25 @@ import "https://example.com/foo/../module2.mjs";

                    Note that this behavior is the same as how shared workers are keyed by their parsed constructor url.

                    +
              24. +

                Since module type is also part of the module map key, the following code will create two separate entries in the module map (the type is "javascript" for the first, and "css" for the second):

                <script>
                   import "https://example.com/module";
                -</script>
                <script>
                +</script>
                +<script>
                   import "https://example.com/module" assert { type: "css" };
                 </script>

                This can result in two separate fetches and two separate module evaluations being performed. This is a willful violation of a constraint recommended (but not required) by the import assertions specification stating that each call to HostResolveImportedModule - with the same referencingScriptOrModule, moduleRequest.[[Specifier]] pair must return - the same Module Record. referencingScriptOrModule, moduleRequest.[[Specifier]]) pair + must return the same Module Record.

                In practice, due to the as-yet-unspecified memory cache (see issue

              25. Let module script be moduleRecord.[[HostDefined]].

              26. Assert: module script's base - URL is not null, as module script is a JavaScript module - script.

              27. + URL is not null, as module script is a JavaScript module + script.

              28. Let urlString be module script's base URL, data-x="concept-settings-object-module-map">module map.

              29. Let url be the result of resolving a - module specifier given base URL and moduleRequest.[[Specifier]].

              30. + module specifier given base URL and + moduleRequest.[[Specifier]].

              31. Assert: url is never failure, because resolving a module specifier must have been previously successful with these @@ -92198,9 +92200,9 @@ import "https://example.com/foo/../module2.mjs"; corresponding module script, or in fetch an import() module script graph).

              32. If moduleRequest.[[Assertions]] has a Record entry such - that entry.[[Key]] is "type", then let module type - be entry.[[Value]]. Otherwise let module type be "javascript".

              33. + that entry.[[Key]] is "type", then let module type + be entry.[[Value]]. Otherwise let module type be "javascript".

              34. Let resolved module script be moduleMap[(url, module type)]. (This entry must exist for us to have gotten to From 0f3b259c1ebd5e02957ba9d2e0227bc45c46d31b Mon Sep 17 00:00:00 2001 From: Daniel Clark Date: Tue, 13 Jul 2021 10:03:05 -0700 Subject: [PATCH 56/58] Update paragraph that incorrectly stated that