diff --git a/source b/source index ee75ede27f7..a0b9f6c2f7e 100644 --- a/source +++ b/source @@ -86487,6 +86487,10 @@ interface ApplicationCache : EventTarget {
  • Return record.[[HostDefined]].

  • +

    The active script concept is so far only used by the + import() feature, to determine the base + URL to use for resolving relative module specifiers.

    +

    An environment is an object that identifies the settings of a @@ -88288,14 +88292,54 @@ document.querySelector("button").addEventListener("click", bound);

  • Let active script be the active script.

  • -
  • Assert: active script is not null, as jobs are only enqueued by the JavaScript - specification while a script is active.

  • +
  • Let script execution context be null.

  • -
  • Let script execution context be a new JavaScript execution - context, with its Function field set to null, its Realm field set to active - script's settings object's Realm, and its ScriptOrModule set to active script's record.

  • +
  • +

    If active script is not null, set script execution context to a new + JavaScript execution context, with its Function field set to null, its Realm field + set to active script's settings object's Realm, and its ScriptOrModule set to active script's + record.

    + +

    As seen below, this is used in order to propagate the current active + script forward to the time when the job is executed.

    + +
    +

    A case where active script is non-null, and saving it in this way is useful, is + the following:

    + +
    Promise.resolve('import(`./example.mjs`)').then(eval);
    + +

    Without this step (and the steps below that use it), there would be no active + script when the import() expression is evaluated, since eval() + is a built-in function that does not originate from any particular script.

    + +

    With this step in place, the active script is propagated from the above code into the job, + allowing import() to use the original script's base URL appropriately.

    +
    + +
    +

    active script can be null if the user clicks on the following button, before any + script ever accesses the button's onclick property:

    + +
    <button onclick="Promise.resolve('import(`./example.mjs`)').then(eval)">Click me</button>
    + +

    In this case, the JavaScript function for the event + handler will be created by the get the current value of the event handler algorithm as a direct result of user + action, with no script on the stack (i.e. no active script). Thus, when the + promise machinery calls EnqueueJob, there will be no active script to + pass along.

    + +

    As a consequence, this means that when the import() expression is evaluated, + there will still be no active script. Fortunately that is handled by our + implementations of HostResolveImportedModule and + HostImportModuleDynamically, by falling back to using the current settings + object's API base URL.

    +
    +
  • Queue a microtask, on job settings's responsible event @@ -88320,20 +88364,20 @@ document.querySelector("button").addEventListener("click", bound);

  • -

    Push script execution context onto the - JavaScript execution context stack.

    +

    If script execution context is not null, then push script execution context onto the JavaScript execution + context stack.

    -

    This affects the active script while the job runs, in cases like - Promise.resolve("...").then(eval) where there would otherwise be no - active script since eval() is a built-in function that does not originate from - any particular script.

    +

    As explained above, this affects the active script while the job + runs.

  • Let result be the result of performing the abstract operation specified by job, using the elements of arguments as its arguments.

  • -
  • Pop script execution context from the - JavaScript execution context stack.

  • +
  • If script execution context is not null, then pop script execution context from the JavaScript execution context + stack.

  • Clean up after running a callback with incumbent settings.

  • @@ -88480,20 +88524,48 @@ import "https://example.com/foo/../module2.mjs"; implementation:

      -
    1. Let referencing script be - referencingScriptOrModule.[[HostDefined]].

    2. +
    3. Let settings object be the current settings object.

    4. -
    5. Let moduleMap be referencing script's settings object's - module map.

    6. +
    7. Let base URL be settings object's API base + URL.

    8. + +
    9. +

      If referencingScriptOrModule is not null, then:

      + +
        +
      1. Let referencing script be + referencingScriptOrModule.[[HostDefined]].

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

      4. + +
      5. Set base URL to referencing script's base URL.

      6. +
      + +
      +

      referencingScriptOrModule is not usually null. One case where it can be + null is if the user clicks the control in the following example:

      + +
      <button onclick="import('./foo.mjs')">Click me</button>
      + +

      In this case, at the time the import() expression runs, + GetActiveScriptOrModule will return null, which will be passed to this abstract + operation when HostResolveImportedModule is + called by FinishDynamicImport.

      +
      +
    10. + +
    11. Let moduleMap be settings object's module map.

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

    13. + module specifier given base URL and specifier.

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

    15. + specifier">resolving a module specifier must have been previously successful with these + same two arguments (either while creating the + corresponding module script, or in HostImportModuleDynamically).

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

    17. @@ -88516,12 +88588,38 @@ import "https://example.com/foo/../module2.mjs"; User agents must use the following implementation:

        -
      1. Let referencing script be - referencingScriptOrModule.[[HostDefined]].

      2. +
      3. Let settings object be the current settings object.

      4. + +
      5. Let base URL be settings object's API base + URL.

      6. + +
      7. Let fetch options be the default classic script fetch + options.

      8. + +
      9. +

        If referencingScriptOrModule is not null, then:

        + +
          +
        1. Let referencing script be + referencingScriptOrModule.[[HostDefined]].

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

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

        5. + +
        6. Set fetch options to the descendant script fetch options for + referencing script's fetch + options.

        7. +
        + +

        As explained above for HostResolveImportedModule, in the common + case, referencingScriptOrModule is non-null.

        +
      10. Let url be the result of resolving a - module specifier given referencing script's base URL and specifier.

      11. + module specifier given base URL and specifier.

      12. If url is failure, then:

        @@ -88537,14 +88635,9 @@ import "https://example.com/foo/../module2.mjs";
      -
    18. Let options be the descendant script fetch options for - referencing script's fetch - options.

    19. - -
    20. Fetch a module script graph given url, referencing - script's settings object, "script", and - options. Wait until the algorithm asynchronously completes with - result.

    21. +
    22. Fetch a module script graph given url, settings object, + "script", and fetch options. Wait until the algorithm + asynchronously completes with result.

    23. If result is null, then: