diff --git a/source b/source index 2ffe100e3bc..ca7bf8c76fd 100644 --- a/source +++ b/source @@ -2272,6 +2272,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
module
"Let map be settings object's global object's import map.
+If el does not have an integrity
attribute, then set options's integrity metadata to the result of
@@ -62867,15 +62875,6 @@ document.body.append(script1, script2);
importmap
"If el's relevant global object's import maps
- allowed is false, then queue an element task on the DOM
- manipulation task source given el to fire an event named error
at el, and return.
Set el's relevant global object's import maps - allowed to false.
Let result be the result of creating an import map parse result given source text and base URL.
A global object has an about-to-be-notified rejected promises list, a
list of Promise
objects, initially empty.
A global object has an import map, + initially an empty import map.
+ +For now, only Window
global
+ objects have their import map modified
+ from the initial empty one. The import map is
+ only accessed for the resolution of a root module script. Modules further down the
+ tree will be resolved using a copied import map that will be threaded through. That
+ is done to guarantee that once we started parsing a module graph, the entire graph would be
+ resolved using the same import map.
A specifier resolution record is a struct. It has the following items:
+A global object has a resolved module set, a set + of specifier resolution records, initially + empty.
+ +The resolved module set ensures that module specifier resolution
+ returns the same result when called multiple times with the same (referrer, specifier) pair. It
+ does that by ensuring that import map rules that impact the specifier in its
+ referrer's scope cannot be defined after its initial resolution. For now, only Window
+ global objects have their module set data structures modified
+ from the initial empty one.
There is always a 1-to-1-to-1 mapping between realms, Let integrity be the empty string. If settingsObject's global object is a Set integrity to the result of resolving a module integrity
+ metadata with url and settingsObject. Set newOptions's integrity metadata to
@@ -106643,13 +106677,9 @@ document.querySelector("button").addEventListener("click", bound);
settings objectWindow
object,
- then set integrity to the result of resolving a module integrity metadata
- with url and settingsObject.
Assert: settingsObject's global object is a Window
- object.
Let map be settingsObject's global object's import map.
If map's integrity[url] does not module script (on success).
Disallow further import maps given settingsObject.
Fetch a single module script given url, settingsObject,
"script
", options, settingsObject, " (on success).
Disallow further import maps given settingsObject.
Fetch a single module script given url, settingsObject,
destination, options, settingsObject, " Run onComplete given result. Assert: settingsObject's global object implements
+ If result is not null, optionally fetch the descendants of and link result given
@@ -107010,8 +107040,6 @@ document.querySelector("button").addEventListener("click", bound);
algorithm accepting null (on failure) or a module script (on success). Disallow further import maps given settingsObject. Let script be the result of creating a JavaScript module script
using sourceText, settingsObject, baseURL, and
options. To create a JavaScript module script,
given a string source, an environment settings
object settings, a URL baseURL, and a script fetch
- options options: If scripting is disabled for
@@ -108341,11 +108369,9 @@ dictionary PromiseRejectionEventInit : EventIniterror to rethrow for global and
return. Assert: global's import
- map is an empty import map. Set global's import map to
- result's import map. Merge existing and new import
+ maps, given global and result's import map. To resolve a module specifier given a script-or-null
- referringScript and a string specifier: Let settingsObject and baseURL be null. If settingsObject's global
object implements
Window
.
-
@@ -108385,7 +108411,7 @@ dictionary PromiseRejectionEventInit : EventInit
Window
, then set importMap to
settingsObject's global object's
- import map.
Let baseURLString be baseURL, serialized.
Add module to resolved module set given settingsObject, + baseURLString, normalizedSpecifier, and asURL.
For each scopePrefix → scopeImports of importMap's scopes:
@@ -108620,16 +108649,12 @@ dictionary PromiseRejectionEventInit : EventInitchild text content containing a JSON representation of the import map. -Only one import map is processed per Document
. After the first import map is
- seen, others will be ignored, with their corresponding script
elements generating
- error
events. Similarly, once any modules have been imported,
- e.g., via import()
expressions or script
elements with their type
attribute set to "module
", further
- import maps will be ignored.
These restrictions, as well as the lack of support for external import maps, are - in place to keep the initial version of the feature simple. They might be lifted over time as - implementer bandwidth allows.
+A Document
can have multiple import maps processed, which can happen either
+ before or after any modules have been imported, e.g., via import()
expressions or
+ script
elements with their type
attribute set
+ to "module
". The merge existing and new import maps algorithm
+ ensures that new import maps cannot define the module resolution for modules that were already
+ defined by past import maps, or for ones that were already resolved.
The simplest use of import maps is to globally remap a bare module specifier:
@@ -108898,13 +108923,9 @@ dictionary PromiseRejectionEventInit : EventInit -Each Window
has an import map,
- initially an empty import map.
Each Window
has an import maps allowed boolean, initially true.
To disallow further import maps given an environment settings object - settingsObject:
+To add module to resolved module set given an environment settings + object settingsObject, a string baseURLString, a + string specifier, and a URL-or-null asURL:
Let global be settingsObject's PromiseRejectionEventInit : EventInit If global does not implement Window
, then return.
Set global's import maps allowed to false.
Import maps are currently disallowed once any module loading has started, or once - a single import map is loaded. These restrictions might be lifted in future specification - revisions.
+Let record be a new specifier resolution record, with base URL set to + baseURLString, specifier + set to specifier, and asURL + set to asURL.
Append record to global's + resolved module set.
To parse an import map string, given a string input and a @@ -109025,6 +109048,348 @@ dictionary PromiseRejectionEventInit : EventInitscopes.
To merge module specifier maps, given a module specifier map + newMap and a module specifier map oldMap:
+ +Let mergedMap be a deep copy of oldMap.
For each specifier → + url of newMap:
+ +If specifier exists in + oldMap, then:
+ +The user agent may report the ignored rule as a warning to the developer + console. They may choose to avoid reporting if the rule is identical to an existing + one.
Continue.
Set mergedMap[specifier] to url.
Return mergedMap.
To merge existing and new import maps, + given a global object global and + an import map newImportMap:
+ +Let newImportMapScopes be a deep copy of newImportMap's scopes.
+ +We're mutating these copies and removing items from them when they are used to + ignore scope-specific rules. This is true for newImportMapScopes, as well as to + newImportMapImports below.
+Let newImportMapImports be a deep copy of newImportMap's imports.
For each scopePrefix → + scopeImports of newImportMapScopes:
+ +For each record of global's + resolved module set:
+ +If scopePrefix is record's base URL, or if scopePrefix + ends with U+002F (/) and scopePrefix is a code unit prefix of + record's base URL, + then:
+ +For each specifierKey → + resolutionResult of scopeImports:
+ +If specifierKey is record's specifier, or if the following + conditions are all true:
+ +specifierKey ends with U+002F (/).
specifierKey is a code unit prefix of + record's specifier.
Either record's asURL is null or is + special
then:
+ +The user agent may report the ignored rule as a warning to the developer + console. They may choose to avoid reporting if the rule is identical to an existing + one.
Remove scopeImports[specifier].
Implementers are encouraged to implement a more efficient matching + algorithm when working with the resolved module set. As guidance, the number of + resolved/mapped modules in a large application can be in the order of thousands.
+If scopePrefix exists in + oldImportMap's scopes, then + set oldImportMap's scopes[scopePrefix] to the result of + merging module specifier maps, given + scopeImports and oldImportMap's scopes[scopePrefix].
Otherwise, set oldImportMap's scopes[scopePrefix] to + scopeImports.
For each url → + integrity of newImportMap's integrity:
+ +If url exists in oldImportMap's + integrity, then:
+ +The user agent may report the ignored rule as a warning to the developer + console. They may choose to avoid reporting if the rule is identical to an existing + one.
Continue.
Set oldImportMap's integrity[url] to + integrity.
For each record of global's + resolved module set:
+ +For each specifier → url of + newImportMapImports:
+ +If specifier starts with record's specifier, then:
+ +The user agent may report the ignored rule as a warning to the developer + console. They may choose to avoid reporting if the rule is identical to an existing + one.
Remove newImportMapImports[specifier].
Set oldImportMap's imports to + the result of merge module specifier maps, + given newImportMapImports and oldImportMap's imports.
The above algorithm merges a new import map into the given environment + settings object's global object's import map. Let's examine a + few examples:
+ + + +When the new import map impacts an already resolved module, that rule gets dropped from the + import map.
+ +So, if the resolved module set already contains the "/app/helper
", the following new import map:
{
+ "imports": {
+ "/app/helper": "./helper/index.mjs",
+ "lodash": "/node_modules/lodash-es/lodash.js"
+ }
+}
+ Would be equivalent to the following one:
+{
+ "imports": {
+ "lodash": "/node_modules/lodash-es/lodash.js"
+ }
+}
+ The same is true for rules that impact already resolved modules defined in specific scopes.
+ If we already resolved "/app/helper
" from "/app/main.mjs
" the following new import map:
{
+ "scopes": {
+ "/app/": {
+ "/app/helper": "./helper/index.mjs"
+ }
+ },
+ "imports": {
+ "lodash": "/node_modules/lodash-es/lodash.js"
+ }
+}
+ Would similarly be equivalent to:
+{
+ "imports": {
+ "lodash": "/node_modules/lodash-es/lodash.js"
+ }
+}
+ We could also have cases where a single already-resolved module specifier has multiple rules + for its resolution, depending on the referring script. In such cases, only the relevant rules + would not be added to the map.
+For example, if we already resolved "/app/helper
" from "/app/vendor/main.mjs
", the following new import map:
{
+ "scopes": {
+ "/app/": {
+ "/app/helper": "./helper/index.mjs"
+ },
+ "/app/vendor/": {
+ "/app/": "./vendor_helper/"
+ },
+ "/vendor/": {
+ "/app/helper": "./helper/vendor_index.mjs"
+ }
+ },
+ "imports": {
+ "lodash": "/node_modules/lodash-es/lodash.js"
+ "/app/": "./general_app_path/"
+ "/app/helper": "./other_path/helper/index.mjs"
+ }
+}
+ Would be equivalent to:
+{
+ "scopes": {
+ "/vendor/": {
+ "/app/helper": "./helper/vendor_index.mjs"
+ }
+ },
+ "imports": {
+ "lodash": "/node_modules/lodash-es/lodash.js"
+ }
+}
+
+ This is achieved by the fact that the merge algorithm tracks already resolved modules + and removes rules affecting them from new import maps before they are merged into the existing + one.
+When the new import map has conflicting rules to the existing import map, with no impacted + already resolved modules, the existing import map rules persist.
+ +For example, the following existing and new import maps:
++{ + "imports": { + "/app/helper": "./helper/index.mjs", + "lodash": "/node_modules/lodash-es/lodash.js" + } +}
+{ + "imports": { + "/app/helper": "./main/helper/index.mjs" + } +}
Would be equivalent to the following single import map:
+{
+ "imports": {
+ "/app/helper": "./helper/index.mjs",
+ "lodash": "/node_modules/lodash-es/lodash.js",
+ }
+}
+ To sort and normalize a module specifier map, given an ordered map originalMap and a URL baseURL:
@@ -110003,8 +110368,6 @@ import "https://example.com/foo/../module2.mjs";Disallow further import maps given settingsObject.
Let url be the result of resolving a module specifier given referencingScript and moduleRequest.[[Specifier]], catching any exceptions. If they throw an exception, let