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 :
-
imports , a specifier map , and
-
scopes , an ordered map of URLs to specifier maps .
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 :
a type , one of "
invalid
", "URL
", or "non-URL
", anda specifier , a string or null (defaults to null).
-
For eachIf specifier→ addresses of newImportMap ’s imports , setis the empty string, then return a specifier parse resultimportMap ’s importswhose type[is "invalid
". If specifier
] to addresses .starts with "/
", "./
", or "../
", then:-
For eachLet url→ specifierMapbe the result ofnewImportMap ’s scopes , setparsingimportMapspecifier’s scopes [withurlbaseURL] to specifierMap .as the base URL. -
SetIfimportMapurl’s imports to theis failure, then return a specifier parse resultof sortingwhose type is "invalid
".One way this could happen is if
importMap ’s imports , with an entry aspecifierbeing less than an entryis "../foo
" andbbaseURLifis a’s keydata:
URL. Return a specifier parse result whose type is
longer or code unit less than"URL"
and specifier isb ’s keyurl , serialized .
-
-
SetLetimportMapurl’s scopes tobe the result ofsortingparsingimportMap ’s scopes , with an entry aspecifierbeing less than an entry(with no base URL). If
burlifis failure, then return a’s keyspecifier parse result whose type islonger or code unit less than"non-URL"
and specifier isbspecifier .If url ’s
key . Update an import mapschememerges the two import maps inis either avery simple way, not performing any deep merging beyond the top level of thefetch scheme or "importsstd" and "", then return a specifier parse result whose type isscopes " keys. For example,"URL"equivalent tourl , serialized .-
Notice how the definition for " /scope1/ " was completely overridden, so there is no longerReturn aredirection for the "specifier parse result whose type isa"non-URL"" moduleand specifierwithin 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.
-
Import
maps
are
accepted
if
and
only
if
they
are
added
(i.e.,
their
corresponding
script
elements are added) before the first module load is started, even if the loading of the import map files don’t finish before the first module load is started. - Module loading waits for any import maps that have already started loading, if any.
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:
-
Introduce import map parse result , which is a struct with three items :
-
a settings object , an environment settings object ;
-
an import map , an import map ; and
-
an error to rethrow , a JavaScript value representing a parse error when non-null.
-
-
the script’s type should be either "
classic
", "module
", or "importmap
". -
Rename the script’s script to the script’s result , which can be either a script or an import map parse result .
The following algorithms are updated accordingly:
-
execute a script block Step 4: add the following case.
-
"
importmap
" -
-
Assert: Never reached.
Import maps are processed by register an import map instead of execute a script block .
-
-
"
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:
-
Insert the following step to prepare a script step 7, under "Determine the script’s type as follows:":
-
If the script block’s type string is an ASCII case-insensitive match for the string "
importmap
", the script’s type is "importmap
".
-
-
Insert the following step before prepare a script step 24:
-
If the script’s type is "
importmap
" and the element’s node document ’s acquiring import maps is false, then queue a task to fire an event namederror
at the element, and return.Alternative considered: We can proceed to import map loading unless the script is ready for all
HTMLScriptElement
in list of pending import map scripts , even when acquiring import maps is false, because at that time subsequent module loading is blocked and new import map loads could be still added. This would allow a few more opportinities for adding import maps, but this would highly depend on the timing of network loading. For example, if the preceding import map load finishes earlier than expected, then subsequent import maps depending on this behavior might fail. To avoid this kind of nondeterminism, we didn’t choose this option, at least for now.
-
-
Insert the following case to prepare a script step 24.6:
-
"
importmap
" - Fetch an import map given url , settings object , and options .
-
"
-
Insert the following case to prepare a script step 25.2:
-
"
importmap
" -
-
Let import map parse result be the result of create an import map parse result , given source text , base URL and settings object .
-
Set the script’s result to import map parse result .
-
-
"
-
Insert the following case to prepare a script step 26:
-
If
the
script’s
type
is
"
importmap
" -
Append
the
element
to
the
element’s
node
document
’s
list
of
pending
import
map
scripts
.
When
the
script
is
ready
,
run
the
following
steps:
-
Repeat while the list of pending import map scripts is not empty and the first entry’s the script is ready :
-
Register an import map given the first element of list of pending import map scripts .
-
Remove the first element of list of pending import map scripts .
If this makes the list of pending import map scripts empty, it will (asynchronously) unblock any wait for import maps algorithm instances.
-
-
-
If
the
script’s
type
is
"
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
.
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.
-
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 thescript-src-elem
CSP directive applies. -
Set up the module script request given request and options .
-
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 .
-
If any of the following conditions are met, asynchronously complete this algorithm with null, and abort these steps:
-
response ’s type is "
error
" -
The result of extracting a MIME type from response ’s header list is not
"application/importmap+json"
-
-
Let source text be the result of UTF-8 decoding response’s body .
-
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
-
If settings object ’s global object is a
Window
object:-
Let document be settings object ’s global object 's associated
Document
. -
Set document ’s acquiring import maps to false.
-
Spin the event loop until document ’s list of pending import map scripts is empty.
-
-
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.
-
fetch a module worker script graph (using module map settings object )
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.
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
HTMLScriptElement
element
:
-
If element ’s the script’s result is null, then fire an event named
error
at element , and return. -
Let import map parse result be element ’s the script’s result .
-
Assert: element ’s the script’s type is "
importmap
". -
Assert: import map parse result is an import map parse result .
-
Let settings object be import map parse result ’s settings object .
-
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 fireerror
events, then we should change this step accordingly. -
If import map parse result ’s error to rethrow is not null, then:
-
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.
-
Return.
-
-
UpdateSet 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 . -
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
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 .
-
Let parsed be the result of parsing JSON into Infra values given input .
-
If parsed is not a map , then throw a
TypeError
indicating that the top-level value must be a JSON object. -
Let sortedAndNormalizedImports be an empty map .
-
If parsed ["
imports
"] exists , then:-
If parsed ["
imports
"] is not a map , then throw aTypeError
indicating that the "imports
" top-level key must be a JSON object. -
Set sortedAndNormalizedImports to the result of sorting and normalizing a specifier map given parsed ["
imports
"] and baseURL .
-
-
Let sortedAndNormalizedScopes be an empty map .
-
If parsed ["
scopes
"] exists , then:-
If parsed ["
scopes
"] is not a map , then throw aTypeError
indicating that the "scopes
" top-level key must be a JSON object. -
Set sortedAndNormalizedScopes to the result of sorting and normalizing scopes given parsed ["
scopes
"] and baseURL .
-
-
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.
-
Return the import map whose imports are sortedAndNormalizedImports and whose scopes scopes are sortedAndNormalizedScopes .
<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 .
-
Let normalized be an empty map .
-
First, normalize all entries so that their values are lists . For each specifierKey → value of originalMap ,
-
Let
normalizedSpecifierKeyparsedSpecifierKey be the result ofnormalizing aparsing an import specifierkeygiven specifierKey and baseURL . -
If
normalizedSpecifierKeyparsedSpecifierKey ’s type isnull, then"invalid
", then:Report a warning to the console that the specifier was invalid.
Let normalizedSpecifierKey be parsedSpecifierKey ’s specifier .
-
If value is a string , then set normalized [ normalizedSpecifierKey ] to « value ».
-
Otherwise, if value is null, then set normalized [ normalizedSpecifierKey ] to a new empty list.
-
Otherwise, if value is a list , then set normalized [ normalizedSpecifierKey ] to value .
-
Otherwise, report a warning to the console that addresses must be strings, arrays, or null.
-
-
Next, normalize and validate each potential address in the value lists . For each specifierKey → potentialAddresses of normalized ,
-
Assert: potentialAddresses is a list , because of the previous normalization pass.
-
Let validNormalizedAddresses be an empty list .
-
For each potentialAddress of potentialAddresses ,
-
If potentialAddress is not a string , then:
-
Report a warning to the console that the contents of address arrays must be strings.
-
Continue .
-
-
Let
addressURLparsedSpecifierKey be the result of parsinga URL-likean import specifier given potentialAddress and baseURL . -
If
addressURLparsedSpecifierKey ’s type isnull,"invalid
", then:-
Report a warning to the console that the
addressspecifier was invalid. -
Continue .
-
-
If specifierKey ends with U+002F (/), and
the serialization ofaddressURLparsedSpecifierKey ’s specifier does not end with U+002F (/), then:-
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.
-
Continue .
-
-
Append
addressURLparsedSpecifierKey ’s specifier to validNormalizedAddresses .
-
-
Set normalized [ specifierKey ] to validNormalizedAddresses .
-
-
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 .
-
Let normalized be an empty map .
-
For each scopePrefix → potentialSpecifierMap of originalMap ,
-
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. -
Let scopePrefixURL be the result of parsing scopePrefix with baseURL as the base URL.
-
If scopePrefixURL is failure, then:
-
Report a warning to the console that the scope prefix URL was not parseable.
-
Continue .
-
-
If scopePrefixURL ’s scheme is not a fetch scheme , then:
-
Report a warning to the console that scope prefix URLs must have a fetch scheme.
-
Continue .
-
-
Let normalizedScopePrefix be the serialization of scopePrefixURL .
-
Set normalized [ normalizedScopePrefix ] to the result of sorting and normalizing a specifier map given potentialSpecifierMap and baseURL .
-
-
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 .
5. Composing import maps
-
IfLetspecifierKeyconcatenatedImportMapis thebe a new emptystring, then:import map . -
Report a warning to the consoleLet concatenatedImportMap ’s importsthat specifier keys cannotbe theempty string.concatenation of baseImportMap ’s imports and newImportMap ’s imports , given baseImportMap and null. -
Return null.Set concatenatedImportMap ’s scopes to a clone of baseImportMap ’s scopes . -
For each scopePrefix → newScopeSpecifierMap of newImportMap ’s scopes :
-
Let
urlbaseScoperSpecifierMap be baseImportMap ’s scopes [ scopePrefix ], if it exists , or a new empty map otherwise. Set concatenatedImportMap ’s scopes [ scopePrefix ] to the
resultconcatenation ofparsing a URL-like import specifier ,baseScoperSpecifierMap and newScopeSpecifierMap , givenspecifierKeybaseImportMap andbaseURLscopePrefix .
-
-
IfSeturlconcatenatedImportMapis not null, then return the serialization’s scopes to the result of sortingurl .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 . -
Return
specifierKeyconcatenatedImportMap .
-
IfLetspecifierconcatenatedSpecifierMapstarts withbe a clone" / ", " ./ ", or " ../ ", then:of baseSpecifierMap For each specifier → addresses of newSpecifierMap :
-
Let
urlnewAddresses bethe result of parsinga new empty list . For each
specifieraddresswithofbaseURL as the base URL.addresses :-
IfLeturlfallbacksis failure, then return null.be the result of getting the fallbacksOne way this could happen is ifforspecifieraddress , given contextImportMapis " ../foo "andbaseURL is a data: URL.scopePrefix . -
ReturnFor eachurl .fallback of fallbacks :-
Let
urlfallbackResult be the result of parsing an import specifier(with no base URL). Ifgivenurl is failure, then return null.fallback . -
If
urlfallbackResult ’sschemetype iseither a fetch scheme ornot "stdURLthen returnthen:Report a warning to the console stating that
urlfallback , as a non-URL specifier, cannot be the ultimate target of an import mapping.Continue .
Append fallback to newAddresses .
-
-
-
Return null.Set concatenatedSpecifierMap [ specifier ] to newAddresses .
A string-
-
Set concatenatedSpecifierMap to the result of sorting concatenatedSpecifierMap , with an entry a
is longer or code unitbeing less than an entry b if a ’slengthkey isgreater than b ’s length ,longer orif a iscode unit less than b ’s key . Return concatenatedSpecifierMap .
4.
6.
Resolving
module
specifiers
4.1.
6.1.
New
"resolve
a
module
specifier"
-
Let settingsObject be the current settings object .
-
Let baseURL be settingsObject ’s API base URL .
-
If referringScript is not null, then:
-
Set settingsObject to referringScript ’s settings object .
-
Set baseURL to referringScript ’s base URL .
-
-
Let importMap be settingsObject ’s import map .
-
Let
moduleMap be settingsObject ’s module map . Let baseURLString be baseURL , serialized . Let asURLparsedSpecifier be the result of parsinga URL-likean import specifier given specifier and baseURL . -
LetIfnormalizedSpecifierparsedSpecifierbe the serialization’s typeof asURL , if asURLisnon-null; otherwise, specifier ."invalid
", then throw aTypeError
indicating the reason for the invalidity. -
For each scopePrefix →LetscopeImportsfallbacks be the result of getting the fallbacks givenimportMapparsedSpecifier ’sscopesspecifier ,IfscopePrefix is baseURLStringimportMap ,or if scopePrefix ends with U+002F (/)andbaseURLString starts withbaseURL , serialized . For each
scopePrefix , then:address of fallbacks :-
Let
scopeImportsMatchparsedFallback be the result ofresolvingparsing animports matchimport specifier givennormalizedSpecifier , scopeImports ,address andmoduleMapbaseURL . -
If
scopeImportsMatchparsedFallback ’s type is notnull, then: Validate the module script"URL
", then throw aTypeError
indicating that the resolution ultimately did not resolve in a URL.given scopeImportsMatch , settingsObject , and baseURL . Return scopeImportsMatch . -
Let
topLevelImportsMatchurl be thereusltresult ofresolving an imports matchparsinggivennormalizedSpecifier , importMapparsedFallback ’simports , and moduleMap .specifier . -
If
topLevelImportsMatchurl isnot 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 toaURL, but it wasn’t remapped to anything by importMap . If asURL is not null, then: Validate thevalid module script URL , givenasURL ,settingsObject,and baseURL. Return, then returnasURLurl .
-
-
Throw a new
TypeError
indicating that the specifierwas a bare specifier, but wascould notremapped 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.
-
ForLet applicableSpecifierMaps be a new empty list . If contextURLString is not null, then for each
specifierKeyscopePrefix →addressesscopeSpecifierMap ofspecifierMap ,importMap ’s scopes :-
If
specifierKeyscopePrefixisequalsnormalizedSpecifiercontextURLString ,then: IforaddressesscopePrefix’s sizeends with U+002F (/) and contextURLString starts withis 0,scopePrefix , thenthrow a TypeErrorappendindicating thatnormalizedSpecifierscopeSpecifierMapwas mappedtono addresses.applicableSpecifierMaps .
-
-
IfAppendaddressesimportMap ’ssizeimportsis 1, then:to applicableSpecifierMaps . -
LetFor eachsingleAddressspecifierMapbeofaddresses [0].applicableSpecifierMaps :-
If singleAddress ’s schemeFor eachis " std ", andmoduleMapspecifierKey[→singleAddressaddresses] does not exist , then throw a TypeError indicating that the requested built-in module is not implemented. ReturnofsingleAddress .specifierMap :-
If
addresses ’s size is 2, and addressesspecifierKey[0]'s scheme is " std ", andequalsaddresses [1]'s scheme is not " std ", then:normalizedSpecifier :-
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 ..
-
-
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::-
Let afterPrefix be the portion of normalizedSpecifier after the initial specifierKey prefix.
-
Assert: afterPrefix ends with " / ", as enforced during parsing .Let
urlfallbacks bethe 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] wasaURL, and appending after the trailing " / " will not make it unparseable. Return url .new empty list . -
If addresses ’s sizeFor eachis 2, andaddressesaddress[0]'s scheme is " std ", andof addresses[1]'s scheme is not " std ", then::-
Let afterPrefix be the portion of normalizedSpecifier after the initial specifierKey prefix.Assert:
afterPrefixaddress ends with "/
", as enforced during parsing . -
Let
url0parseResult be the result of parsing theconcatenation of the serialization of addresses [0] with afterPrefix ; similarly, let url1 be the result of parsingimport specifier given by the concatenation ofthe serialization ofaddressesaddress[1]with afterPrefix .As above, we parse the concatenation to deal with built-in module cases. -
Assert:
neither url0 norurl1 are failure, since addresses [0] and addressesparseResult[1] were URLs, and appending after their trailing " / " will’s specifier is notmake them unparseable.null. -
Return url0 , if moduleMap [Appendurl0parseResult] exists’s specifier; otherwise, returntourl1fallbacks .
-
-
Otherwise, we have no specification for more complicatedReturn fallbacksyet; throw a TypeError indicating this is not yet supported ..
-
-
-
-
Return
null.« normalizedSpecifier ».
-
If url ’s scheme is "
std
", then:-
Let moduleMap be settings object ’s module map .
-
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.
-
-
If url ’s scheme is not a fetch scheme , then
throw a TypeError indicating that url is not a fetch scheme.return false.
-
If url ’s scheme is "
std-internal
" andbase URLbaseURL ’s scheme is "std-internal
", thenreturn.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:
-
HostResolveImportedModule and HostImportModuleDynamically no longer need to compute the base URL themselves, as resolve a module specifier now handles that.
-
Fetch an import() module script graph will also need to take a script instead of a base URL.
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
:
-
Validate theIf url is not a valid module script URL givenurl ,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.
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:
-
fetch an external module script graph (using settings object )
-
fetch a modulepreload module script graph (using settings object )
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">
).