Import Maps

Draft Community Group Report, 28

This version:
https://wicg.github.io/import-maps/
Editor:
Domenic Denicola ( Google )
Participate:
GitHub WICG/import-maps ( new issue , open issues )
Commits:
GitHub spec.bs commits
Not Ready For Implementation

This spec is not yet ready for implementation. It exists in this repository to record the ideas and promote discussion.

Before attempting to implement this spec, please contact the editors.


Abstract

Import maps allow web pages to control the behavior of JavaScript imports, and introduce a new import: URL scheme to allow using this mapping in other URL-accepting contexts

Status of this document

This specification was published by the Web Platform Incubator Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .

1. Definitions

A specifier map is an ordered map from strings to lists of URLs strings .

A import map is a struct with two items :

An empty import map is an import map with its imports and scopes both being empty maps.

2. Parsing import specifiers

A specifier parse result is a struct with two items :

To update parse an import map specifier , given a string importMap specifier with and a second import map URL newImportMap baseURL :
  1. For each If specifier → addresses of newImportMap ’s imports , set is the empty string, then return a specifier parse result importMap ’s imports whose type [ is " invalid ".

  2. If specifier ] to addresses . starts with " / ", " ./ ", or " ../ ", then:

    1. For each Let url → specifierMap be the result of newImportMap ’s scopes , set parsing importMap specifier ’s scopes [ with url baseURL ] to specifierMap . as the base URL.

    2. Set If importMap url ’s imports to the is failure, then return a specifier parse result of sorting whose type is " invalid ".

      One way this could happen is if importMap ’s imports , with an entry a specifier being less than an entry is " ../foo " and b baseURL if is a ’s key data: URL.

    3. Return a specifier parse result whose type is longer or code unit less than "URL" and specifier is b ’s key url , serialized .

  3. Set Let importMap url ’s scopes to be the result of sorting parsing importMap ’s scopes , with an entry a specifier being less than an entry (with no base URL).

  4. If b url if is failure, then return a ’s key specifier parse result whose type is longer or code unit less than "non-URL" and specifier is b specifier .

  5. If url ’s key . Update an import map scheme merges the two import maps in is either a very simple way, not performing any deep merging beyond the top level of the fetch scheme or " imports std " and " ", then return a specifier parse result whose type is scopes " keys. For example, "URL" , whose specifier is equivalent to url , serialized .

  6. Notice how the definition for " /scope1/ " was completely overridden, so there is no longer Return a redirection for the " specifier parse result whose type is a "non-URL" " module and specifier within that scope. is specifier .

2. 3. Acquiring import maps

2.1. 3.1. New members of environment settings objects

Each environment settings object will get an import map algorithm, which returns an import map created by parsing and merging all <script type="importmap"> elements that are encountered (before the cutoff).

A Document has an import map import map . It is initially a new empty import map .

In set up a window environment settings object , settings object ’s import map returns the import map of window ’s associated Document .

A WorkerGlobalScope has an import map import map . It is initially a new empty import map .

Specify a way to set WorkerGlobalScope 's import map . We might want to inherit parent context’s import maps, or provide APIs on WorkerGlobalScope , but we are not sure. Currently it is always an empty import map . See #2 .

In set up a worker environment settings object , settings object ’s import map returns worker global scope ’s import map .

This infrastructure is very similar to the existing specification for module maps.

A Document has a list of pending import map scripts , which is a list of HTMLScriptElement s, initially empty.

HTMLScriptElement s are added to this list by § 2.3 § 3.3 Prepare a script .

Each Document has an acquiring import maps boolean. It is initially true.

These two pieces of state are used to achieve the following behavior:

2.2. 3.2. Script type

To process import maps in the prepare a script algorithm consistently with existing script types (i.e. classic or module), we make the following changes:

The following algorithms are updated accordingly:

Because we don’t make import map parse result the new subclass of script , other script execution-related specs are left unaffected.

2.3. 3.3. Prepare a script

Inside the prepare a script algorithm, we make the following changes:

CSP is applied to import maps just like JavaScript scripts. Is this sufficient? #105 .

This is specified similar to the list of scripts that will execute in order as soon as possible , to register import maps and fire error events in order ( list of scripts that will execute in order as soon as possible is rarely used in the wild though). There can be other alternatives, e.g. executing a similar loop inside wait for import maps .

To fetch an import map given url , settings object , and options , run the following steps. This algorithm asynchronously returns an import map or null.

This algorithm is specified consistently with fetch a single module script steps 5, 7, 8, 9, 10, and 12.1. Particularly, we enforce CORS to avoid leaking the import map contents that shouldn’t be accessed.

  1. Let request be a new request whose url is url , destination is " script ", mode is " cors ", referrer is " client ", and client is settings object .

    Here we use " script " as the destination , which means the script-src-elem CSP directive applies.

  2. Set up the module script request given request and options .

  3. Fetch request . Return from this algorithm, and run the remaining steps as part of the fetch’s process response for the response response .

    response is always CORS-same-origin .

  4. If any of the following conditions are met, asynchronously complete this algorithm with null, and abort these steps:

  5. Let source text be the result of UTF-8 decoding response’s body .

  6. Asynchronously complete this algorithm with the result of create an import map parse result , given source text , response ’s url , and settings object .

2.4. 3.4. Wait for import maps

To wait for import maps given settings object :
  1. If settings object ’s global object is a Window object:

    1. Let document be settings object ’s global object 's associated Document .

    2. Set document ’s acquiring import maps to false.

    3. Spin the event loop until document ’s list of pending import map scripts is empty.

  2. Asynchronously complete this algorithm.

No actions are specified for WorkerGlobalScope because for now there are no mechanisms for adding import maps to WorkerGlobalScope .

Insert a call to wait for import maps at the beginning of the following HTML spec concepts.

In this draft of the spec, which inserts itself into these HTML concepts, the settings object used here is the module map settings object , not fetch client settings object , because resolve a module specifier uses the import map of module map settings object . In a potential future version of the import maps infrastructure, which interjects itself at the layer of the Fetch spec in order to support import: URLs, we would instead use fetch client settings object .

This only affects fetch a module worker script graph , where these two settings objects are different. And, given that the import maps for WorkerGlobalScope s are currently always empty, the only fetch that could be impacted is that of the initial module. But even that would not be impacted, because that fetch is done using URLs, not specifiers. So this is not a future compatibility hazard, just something to keep in mind as we develop import maps in module workers.

Depending on the exact location of wait for import maps , import(unresolvableSpecifier) might behave differently between a HTML-spec- and Fetch-spec-based import maps. In particular, in the current draft, acquiring import maps is set to false after an import() -initiated failure to resolve a module specifier , thus causing any later-encountered import maps to cause an error event instead of being processed. Whereas, if wait for import maps was called as part of the Fetch spec, it’s possible it would be natural to specify things such that acquiring import maps remains true (as it does for cases like <script type="module" src="http://:invalidurl"> ).

This should not be much of a compatibility hazard, as it only makes esoteric error cases into successes. And we can always preserve the behavior as specced here if necessary, with some potential additional complexity.

2.5. 3.5. Registering an import map

To register an import map given an HTMLScriptElement element :
  1. If element ’s the script’s result is null, then fire an event named error at element , and return.

  2. Let import map parse result be element ’s the script’s result .

  3. Assert: element ’s the script’s type is " importmap ".

  4. Assert: import map parse result is an import map parse result .

  5. Let settings object be import map parse result ’s settings object .

  6. If element ’s node document ’s relevant settings object is not equal to settings object , then return.

    This is spec’ed consistently with whatwg/html#2673 .

    Currently we don’t fire error events in this case. If we change the decision at whatwg/html#2673 to fire error events, then we should change this step accordingly.

  7. If import map parse result ’s error to rethrow is not null, then:

    1. Report the exception given import map parse result ’s error to rethrow .

      There are no relevant script , because import map parse result isn’t a script . This needs to wait for whatwg/html#958 before it is fixable.

    2. Return.

  8. Update Set element ’s node document 's import map to the result of concatenating element ’s node document 's import map with the import map parse result ’s import map .

  9. If element is from an external file , then fire an event named load at element .

The timing of register an import map is observable by possible error and load events, or by the fact that after register an import map an import map script can be moved to another Document . On the other hand, the updated import map is not observable until wait for import maps completes.

3. 4. Parsing import maps

To create an import map parse result , given a string input , a URL baseURL , and an environment settings object settings object :
  1. Let import map be the result of parse an import map string given input and baseURL . If this throws an exception, let error to rethrow be the exception. Otherwise, let error to rethrow be null.

  2. Return an import map parse result with settings object is settings object , import map is import map , and error to rethrow is error to rethrow .

To parse an import map string , given a string input and a URL baseURL :
  1. Let parsed be the result of parsing JSON into Infra values given input .

  2. If parsed is not a map , then throw a TypeError indicating that the top-level value must be a JSON object.

  3. Let sortedAndNormalizedImports be an empty map .

  4. If parsed [" imports "] exists , then:

    1. If parsed [" imports "] is not a map , then throw a TypeError indicating that the " imports " top-level key must be a JSON object.

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

  5. Let sortedAndNormalizedScopes be an empty map .

  6. If parsed [" scopes "] exists , then:

    1. If parsed [" scopes "] is not a map , then throw a TypeError indicating that the " scopes " top-level key must be a JSON object.

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

  7. If parsed ’s keys contains any items besides " imports " or " scopes ", report a warning to the console that an invalid top-level key was present in the import map.

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

  8. Return the import map whose imports are sortedAndNormalizedImports and whose scopes scopes are sortedAndNormalizedScopes .

To create an import map parse result , given a string input , a URL baseURL , and an environment settings object settings object : Let import map be the result of parse an import map string given input and baseURL . If this throws an exception, let error to rethrow be the exception. Otherwise, let error to rethrow be null. Return an import map parse result with settings object is settings object , import map is import map , and error to rethrow is error to rethrow .
The import map is a highly normalized structure. For example, given a base URL of <https://example.com/base/page.html> , the input
{
  "imports": {
    "/app/helper": "node_modules/helper/index.mjs",
    "std:kv-storage": [
      "std:kv-storage",
      "node_modules/kv-storage-polyfill/index.mjs",
    ]
  }
}

will generate an import map with imports of

«[
  "https://example.com/app/helper" → «
    <https://example.com/base/node_modules/helper/index.mjs>

    "https://example.com/base/node_modules/helper/index.mjs"

  »,
  "std:kv-storage" → «
    <std:kv-storage>,
    <https://example.com/base/node_modules/kv-storage-polyfill/index.mjs>

    "std:kv-storage",
    "https://example.com/base/node_modules/kv-storage-polyfill/index.mjs"

  »
]»

and (despite nothing being present in the input) an empty map for its scopes .

To sort and normalize a specifier map , given a map originalMap and a URL baseURL :
  1. Let normalized be an empty map .

  2. First, normalize all entries so that their values are lists . For each specifierKey value of originalMap ,

    1. Let normalizedSpecifierKey parsedSpecifierKey be the result of normalizing a parsing an import specifier key given specifierKey and baseURL .

    2. If normalizedSpecifierKey parsedSpecifierKey ’s type is null, then " invalid ", then:

      1. Report a warning to the console that the specifier was invalid.

      2. continue Continue .

    3. Let normalizedSpecifierKey be parsedSpecifierKey ’s specifier .

    4. If value is a string , then set normalized [ normalizedSpecifierKey ] to « value ».

    5. Otherwise, if value is null, then set normalized [ normalizedSpecifierKey ] to a new empty list.

    6. Otherwise, if value is a list , then set normalized [ normalizedSpecifierKey ] to value .

    7. Otherwise, report a warning to the console that addresses must be strings, arrays, or null.

  3. Next, normalize and validate each potential address in the value lists . For each specifierKey potentialAddresses of normalized ,

    1. Assert: potentialAddresses is a list , because of the previous normalization pass.

    2. Let validNormalizedAddresses be an empty list .

    3. For each potentialAddress of potentialAddresses ,

      1. If potentialAddress is not a string , then:

        1. Report a warning to the console that the contents of address arrays must be strings.

        2. Continue .

      2. Let addressURL parsedSpecifierKey be the result of parsing a URL-like an import specifier given potentialAddress and baseURL .

      3. If addressURL parsedSpecifierKey ’s type is null, " invalid ", then:

        1. Report a warning to the console that the address specifier was invalid.

        2. Continue .

      4. If specifierKey ends with U+002F (/), and the serialization of addressURL parsedSpecifierKey ’s specifier does not end with U+002F (/), then:

        1. Report a warning to the console that an invalid address was given for the specifier key specifierKey ; since specifierKey ended in a slash, so must the address.

        2. Continue .

      5. Append addressURL parsedSpecifierKey ’s specifier to validNormalizedAddresses .

    4. Set normalized [ specifierKey ] to validNormalizedAddresses .

  4. Return the result of sorting normalized , with an entry a being less than an entry b if a ’s key is longer or code unit less than b ’s key .

To sort and normalize scopes , given a map originalMap and a URL baseURL :
  1. Let normalized be an empty map .

  2. For each scopePrefix potentialSpecifierMap of originalMap ,

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

    2. Let scopePrefixURL be the result of parsing scopePrefix with baseURL as the base URL.

    3. If scopePrefixURL is failure, then:

      1. Report a warning to the console that the scope prefix URL was not parseable.

      2. Continue .

    4. If scopePrefixURL ’s scheme is not a fetch scheme , then:

      1. Report a warning to the console that scope prefix URLs must have a fetch scheme.

      2. Continue .

    5. Let normalizedScopePrefix be the serialization of scopePrefixURL .

    6. Set normalized [ normalizedScopePrefix ] to the result of sorting and normalizing a specifier map given potentialSpecifierMap and baseURL .

  3. Return the result of sorting normalized , with an entry a being less than an entry b if a ’s key is longer or code unit less than b ’s key .

To normalize
A string a specifier key , given is longer or code unit less than b if a string ’s length is greater than specifierKey b and ’s length , or if a URL is code unit less than baseURL b .

5. Composing import maps

To concatenate an import map baseImportMap with a second import map newImportMap :
  1. If Let specifierKey concatenatedImportMap is the be a new empty string, then: import map .

  2. Report a warning to the console Let concatenatedImportMap ’s imports that specifier keys cannot be the empty string. concatenation of baseImportMap ’s imports and newImportMap ’s imports , given baseImportMap and null.

  3. Return null. Set concatenatedImportMap ’s scopes to a clone of baseImportMap ’s scopes .

  4. For each scopePrefix newScopeSpecifierMap of newImportMap ’s scopes :

    1. Let url baseScoperSpecifierMap be baseImportMap ’s scopes [ scopePrefix ], if it exists , or a new empty map otherwise.

    2. Set concatenatedImportMap ’s scopes [ scopePrefix ] to the result concatenation of parsing a URL-like import specifier , baseScoperSpecifierMap and newScopeSpecifierMap , given specifierKey baseImportMap and baseURL scopePrefix .

  5. If Set url concatenatedImportMap is not null, then return the serialization ’s scopes to the result of sorting url . concatenatedImportMap ’s scopes , with an entry a being less than an entry b if a ’s key is longer or code unit less than b ’s key .

  6. Return specifierKey concatenatedImportMap .

To parse concatenate a URL-like import specifier , given map baseSpecifierMap with a string second specifier map specifier newSpecifierMap , given an import map contextImportMap and a URL string baseURL scopePrefix :
  1. If Let specifier concatenatedSpecifierMap starts with be a clone " / ", " ./ ", or " ../ ", then: of baseSpecifierMap

  2. For each specifier addresses of newSpecifierMap :

    1. Let url newAddresses be the result of parsing a new empty list .

    2. For each specifier address with of baseURL as the base URL. addresses :

      1. If Let url fallbacks is failure, then return null. be the result of getting the fallbacks One way this could happen is if for specifier address , given contextImportMap is " ../foo " and baseURL is a data: URL. scopePrefix .

      2. Return For each url . fallback of fallbacks :

        1. Let url fallbackResult be the result of parsing an import specifier (with no base URL). If given url is failure, then return null. fallback .

        2. If url fallbackResult ’s scheme type is either a fetch scheme or not " std URL ", then return then:

          1. Report a warning to the console stating that url fallback , as a non-URL specifier, cannot be the ultimate target of an import mapping.

          2. Continue .

        3. Append fallback to newAddresses .

    3. Return null. Set concatenatedSpecifierMap [ specifier ] to newAddresses .

    A string
  3. Set concatenatedSpecifierMap to the result of sorting concatenatedSpecifierMap , with an entry a is longer or code unit being less than an entry b if a ’s length key is greater than b ’s length , longer or if a is code unit less than b ’s key .

  4. Return concatenatedSpecifierMap .

To clone ... TODO: delete when whatwg/infra#265 gets merged.
Concatenating an import map TODO explain the mental model, with a good example or three...

4. 6. Resolving module specifiers

4.1. 6.1. New "resolve a module specifier"

HTML already has a resolve a module specifier algorithm. We replace it with the following resolve a module specifier algorithm, given a script referringScript and a JavaScript string specifier :
  1. Let settingsObject be the current settings object .

  2. Let baseURL be settingsObject ’s API base URL .

  3. If referringScript is not null, then:

    1. Set settingsObject to referringScript ’s settings object .

    2. Set baseURL to referringScript ’s base URL .

  4. Let importMap be settingsObject ’s import map .

  5. Let moduleMap be settingsObject ’s module map . Let baseURLString be baseURL , serialized . Let asURL parsedSpecifier be the result of parsing a URL-like an import specifier given specifier and baseURL .

  6. Let If normalizedSpecifier parsedSpecifier be the serialization ’s type of asURL , if asURL is non-null; otherwise, specifier . " invalid ", then throw a TypeError indicating the reason for the invalidity.

  7. For each scopePrefix → Let scopeImports fallbacks be the result of getting the fallbacks given importMap parsedSpecifier ’s scopes specifier , If scopePrefix is baseURLString importMap , or if scopePrefix ends with U+002F (/) and baseURLString starts with baseURL , serialized .

  8. For each scopePrefix , then: address of fallbacks :

    1. Let scopeImportsMatch parsedFallback be the result of resolving parsing an imports match import specifier given normalizedSpecifier , scopeImports , address and moduleMap baseURL .

    2. If scopeImportsMatch parsedFallback ’s type is not null, then: Validate the module script " URL ", then throw a TypeError given scopeImportsMatch , settingsObject , and baseURL . Return scopeImportsMatch . indicating that the resolution ultimately did not resolve in a URL.

    3. Let topLevelImportsMatch url be the reuslt result of resolving an imports match parsing given normalizedSpecifier , importMap parsedFallback ’s imports , and moduleMap . specifier .

    4. If topLevelImportsMatch url is not null, then: Validate the module script URL given topLevelImportsMatch , settingsObject , and baseURL . Return topLevelImportsMatch . At this point, the specifier was able to be turned in to a URL, but it wasn’t remapped to anything by importMap . If asURL is not null, then: Validate the valid module script URL , given asURL , settingsObject , and baseURL . Return , then return asURL url .

  9. Throw a new TypeError indicating that the specifier was a bare specifier, but was could not remapped to anything by importMap . be resolved.

It seems possible that the return type could end up being a list of URLs , not just a single URL, to support HTTPS → HTTPS fallback. But, we haven’t gotten that far yet; for now let’s assume it stays a single URL.

To resolve an imports match , given get the fallbacks for a string normalizedSpecifier , a specifier given an import map specifierMap , importMap and a module map string or null moduleMap contextURLString :
  1. For Let applicableSpecifierMaps be a new empty list .

  2. If contextURLString is not null, then for each specifierKey scopePrefix addresses scopeSpecifierMap of specifierMap , importMap ’s scopes :

    1. If specifierKey scopePrefix is equals normalizedSpecifier contextURLString , then: If or addresses scopePrefix ’s size ends with U+002F (/) and contextURLString starts with is 0, scopePrefix , then throw a TypeError append indicating that normalizedSpecifier scopeSpecifierMap was mapped to no addresses. applicableSpecifierMaps .

  3. If Append addresses importMap ’s size imports is 1, then: to applicableSpecifierMaps .

  4. Let For each singleAddress specifierMap be of addresses [0]. applicableSpecifierMaps :

    1. If singleAddress ’s scheme For each is " std ", and moduleMap specifierKey [ singleAddress addresses ] does not exist , then throw a TypeError indicating that the requested built-in module is not implemented. Return of singleAddress . specifierMap :

      1. If addresses ’s size is 2, and addresses specifierKey [0]'s scheme is " std ", and equals addresses [1]'s scheme is not " std ", then: normalizedSpecifier :

        1. Return addresses [0], if moduleMap [ addresses [0]] exists ; otherwise, return addresses [1]. Otherwise, we have no specification for more complicated fallbacks yet; throw a TypeError indicating this is not yet supported . .

      2. If specifierKey ends with U+002F (/) and normalizedSpecifier starts with specifierKey , then: If addresses ’s size is 0, then throw a TypeError indicating that normalizedSpecifier was mapped to no addresses. If addresses ’s size is 1, then: :

        1. Let afterPrefix be the portion of normalizedSpecifier after the initial specifierKey prefix.

        2. Assert: afterPrefix ends with " / ", as enforced during parsing .

          Let url fallbacks be the result of parsing the concatenation of the serialization of addresses [0] with afterPrefix . We parse the concatenation, instead of parsing afterPrefix relative to addresses [0], due to cases such as an afterPrefix of " switch " and an addresses [0] of " std:elements/ ". Assert: url is not failure, since addresses [0] was a URL, and appending after the trailing " / " will not make it unparseable. Return url . new empty list .

        3. If addresses ’s size For each is 2, and addresses address [0]'s scheme is " std ", and of addresses [1]'s scheme is not " std ", then: :

          1. Let afterPrefix be the portion of normalizedSpecifier after the initial specifierKey prefix.

            Assert: afterPrefix address ends with " / ", as enforced during parsing .

          2. Let url0 parseResult be the result of parsing the concatenation of the serialization of addresses [0] with afterPrefix ; similarly, let url1 be the result of parsing import specifier given by the concatenation of the serialization of addresses address [1] with afterPrefix .

            As above, we parse the concatenation to deal with built-in module cases.
          3. Assert: neither url0 nor url1 are failure, since addresses [0] and addresses parseResult [1] were URLs, and appending after their trailing " / " will ’s specifier is not make them unparseable. null.

          4. Return url0 , if moduleMap [ Append url0 parseResult ] exists ’s specifier ; otherwise, return to url1 fallbacks .

        4. Otherwise, we have no specification for more complicated Return fallbacks yet; throw a TypeError indicating this is not yet supported . .

  5. Return null. « normalizedSpecifier ».

To validate
A URL url is a valid module script URL , given a URL url , an environment settings object settings object , and a URL base URL : baseURL , if the following steps return true:
  1. If url ’s scheme is " std ", then:

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

    2. If moduleMap [ url ] does not exist , then throw a TypeError indicating that the requested built-in module is not implemented. return false.

      This condition is added to ensure that moduleMap [ url ] does not exist for unimplemented built-ins. Without this condition, fetch a single module script might be called and moduleMap [ url ] can be set to null, which might complicates the spec around built-ins.

      Return.
  2. If url ’s scheme is not a fetch scheme , then throw a TypeError indicating that url is not a fetch scheme. return false.

This algorithm provides a convenient place for implementations to insert other useful behaviors, as long as they are not observable to web content. For example, Chromium might insert the following step at the beginning of the algorithm:
  1. If url ’s scheme is " std-internal " and base URL baseURL ’s scheme is " std-internal ", then return. return true.

This introduces a type of internal built-in module that is only accessible to other internal built-in modules. Similar steps could be used to, for example, change how extension scripts access modules.

Since validate is a valid module script URL is called before any module script fetches, such checks are reliable and can be used as a security mechanism.

4.2. 6.2. Updates to other algorithms

All call sites of HTML’s existing resolve a module specifier will need to be updated to pass the appropriate script , not just its base URL . Some particular interesting cases:

Call sites will also need to be updated to account for resolve a module specifier now throwing exceptions, instead of returning failure. (Previously most call sites just turned failures into TypeError s manually, so this is straightforward.)


In addition to the call sites for validate is a valid module script URL explicitly added within this spec, insert the following at the beginning of fetch a single module script :

  1. Validate the If url is not a valid module script URL given url , module map settings object , and module map settings object ’s API base URL . If this throws an error, , then asynchronously complete this algorithm with null, and abort these steps.

This will call validate the check is a valid module script URL twice for each non-toplevel script fetch, first in resolve a module specifier , and then in fetch a single module script . The behavior of the two calls is identical.

Alternatively, we can add the snippet at the beginning of the following HTML spec concepts (after wait for import maps ), so that the validation is not done twice:

Validate Is a valid module script URL is applied checked to all module URLs before they start loading, even in paths where resolve a module specifier and import maps are not applied (e.g. <script src="..." type="module"> ).

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CONSOLE]
Dominic Farolino; Terin Stock; Robert Kowalski. Console Standard . Living Standard. URL: https://console.spec.whatwg.org/
[DOM]
Anne van Kesteren. DOM Standard . Living Standard. URL: https://dom.spec.whatwg.org/
[ENCODING]
Anne van Kesteren. Encoding Standard . Living Standard. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch Standard . Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard . Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard . Living Standard. URL: https://infra.spec.whatwg.org/
[URL]
Anne van Kesteren. URL Standard . Living Standard. URL: https://url.spec.whatwg.org/
[WebIDL]
Boris Zbarsky. Web IDL . URL: https://heycam.github.io/webidl/

Issues Index

Specify a way to set WorkerGlobalScope 's import map . We might want to inherit parent context’s import maps, or provide APIs on WorkerGlobalScope , but we are not sure. Currently it is always an empty import map . See #2 .
CSP is applied to import maps just like JavaScript scripts. Is this sufficient? #105 .
There are no relevant script , because import map parse result isn’t a script . This needs to wait for whatwg/html#958 before it is fixable.