ESM_RESOLVE(specifier, parentURL)
- Let resolved be undefined.
- If specifier is a valid URL, then
- Set resolved to the result of parsing and reserializing specifier as a URL.
- Otherwise, if specifier starts with “/“, “./“ or “../“, then
- Set resolved to the URL resolution of specifier relative to parentURL.
- Otherwise, if specifier starts with “#”, then
- Set resolved to the destructured value of the result of PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, defaultConditions).
- Otherwise,
- Note: specifier is now a bare specifier.
- Set resolved the result of PACKAGE_RESOLVE(specifier, parentURL).
- If resolved contains any percent encodings of “/“ or “\“ (“%2f” and “%5C” respectively), then
- Throw an Invalid Module Specifier error.
- If the file at resolved is a directory, then
- Throw an Unsupported Directory Import error.
- If the file at resolved does not exist, then
- Throw a Module Not Found error.
- Set resolved to the real path of resolved.
- Let format be the result of ESM_FORMAT(resolved).
- Load resolved as module format, format.
- Return resolved.
PACKAGE_RESOLVE(packageSpecifier, parentURL)
- Let packageName be undefined.
- If packageSpecifier is an empty string, then
- Throw an Invalid Module Specifier error.
- If packageSpecifier does not start with “@”, then
- Set packageName to the substring of packageSpecifier until the first “/“ separator or the end of the string.
- Otherwise,
- If packageSpecifier does not contain a “/“ separator, then
- Throw an Invalid Module Specifier error.
- Set packageName to the substring of packageSpecifier until the second “/“ separator or the end of the string.
- If packageName starts with “.” or contains “\“ or “%”, then
- Throw an Invalid Module Specifier error.
- Let packageSubpath be “.” concatenated with the substring of packageSpecifier from the position at the length of packageName.
- Let selfUrl be the result of PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL).
- If selfUrl is not undefined, return selfUrl.
- If packageSubpath is “.” and packageName is a Node.js builtin module, then
- Return the string “node:” concatenated with packageSpecifier.
- While parentURL is not the file system root,
- Let packageURL be the URL resolution of “node_modules/“ concatenated with packageSpecifier, relative to parentURL.
- Set parentURL to the parent folder URL of parentURL.
- If the folder at packageURL does not exist, then
- Set parentURL to the parent URL path of parentURL.
- Continue the next loop iteration.
- Let pjson be the result of READ_PACKAGE_JSON(packageURL).
- If pjson is not null and pjson.exports is not null or undefined, then
- Let exports be pjson.exports.
- Return the resolved destructured value of the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).
- Otherwise, if packageSubpath is equal to “.”, then
- Return the result applying the legacy LOAD_AS_DIRECTORY CommonJS resolver to packageURL, throwing a Module Not Found error for no resolution.
- Otherwise,
- Return the URL resolution of packageSubpath in packageURL.
- Throw a Module Not Found error.
PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL)
- Let packageURL be the result of READ_PACKAGE_SCOPE(parentURL).
- If packageURL is null, then
- Return undefined.
- Let pjson be the result of READ_PACKAGE_JSON(packageURL).
- If pjson is null or if pjson.exports is null or undefined, then
- Return undefined.
- If pjson.name is equal to packageName, then
- Return the resolved destructured value of the result of PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, pjson.exports, defaultConditions).
- Otherwise, return undefined.
PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, exports, conditions)
- If exports is an Object with both a key starting with “.” and a key not starting with “.”, throw an Invalid Package Configuration error.
- If subpath is equal to “.”, then
- Let mainExport be undefined.
- If exports is a String or Array, or an Object containing no keys starting with “.”, then
- Set mainExport to exports.
- Otherwise if exports is an Object containing a “.” property, then
- Set mainExport to exports[“.”].
- If mainExport is not undefined, then
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, mainExport, “”, false, false, conditions).
- If resolved is not null or undefined, then
- Return resolved.
- Otherwise, if exports is an Object and all keys of exports start with “.”, then
- Let matchKey be the string “./“ concatenated with subpath.
- Let resolvedMatch be result of PACKAGE_IMPORTS_EXPORTS_RESOLVE( matchKey, exports, packageURL, false, conditions).
- If resolvedMatch.resolve is not null or undefined, then
- Return resolvedMatch.
- Throw a Package Path Not Exported error.
PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, conditions)
- Assert: specifier begins with “#”.
- If specifier is exactly equal to “#” or starts with “#/“, then
- Throw an Invalid Module Specifier error.
- Let packageURL be the result of READ_PACKAGE_SCOPE(parentURL).
- If packageURL is not null, then
- Let pjson be the result of READ_PACKAGE_JSON(packageURL).
- If pjson.imports is a non-null Object, then
- Let resolvedMatch be the result of PACKAGE_IMPORTS_EXPORTS_RESOLVE(specifier, pjson.imports, packageURL, true, conditions).
- If resolvedMatch.resolve is not null or undefined, then
- Return resolvedMatch.
- Throw a Package Import Not Defined error.
PACKAGE_IMPORTS_EXPORTS_RESOLVE(matchKey, matchObj, packageURL, isImports, conditions)
- If matchKey is a key of matchObj, and does not end in “*”, then
- Let target be the value of matchObj[matchKey].
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, “”, false, isImports, conditions).
- Return the object { resolved, exact: true }.
- Let expansionKeys be the list of keys of matchObj ending in “/“ or “*”, sorted by length descending.
- For each key expansionKey in expansionKeys, do
- If expansionKey ends in “*” and matchKey starts with but is not equal to the substring of expansionKey excluding the last “*” character, then
- Let target be the value of matchObj[expansionKey].
- Let subpath be the substring of matchKey starting at the index of the length of expansionKey minus one.
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, true, isImports, conditions).
- Return the object { resolved, exact: true }.
- If matchKey starts with expansionKey, then
- Let target be the value of matchObj[expansionKey].
- Let subpath be the substring of matchKey starting at the index of the length of expansionKey.
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, false, isImports, conditions).
- Return the object { resolved, exact: false }.
- Return the object { resolved: null, exact: true }.
PACKAGE_TARGET_RESOLVE(packageURL, target, subpath, pattern, internal, conditions)
- If target is a String, then
- If pattern is false, subpath has non-zero length and target does not end with “/“, throw an Invalid Module Specifier error.
- If target does not start with “./“, then
- If internal is true and target does not start with “../“ or “/“ and is not a valid URL, then
- If pattern is true, then
- Return PACKAGE_RESOLVE(target with every instance of “*” replaced by subpath, packageURL + “/“)_.
- Return PACKAGE_RESOLVE(target + subpath, packageURL + “/“)_.
- Otherwise, throw an Invalid Package Target error.
- If target split on “/“ or “\“ contains any “.”, “..” or “node_modules” segments after the first segment, throw an Invalid Package Target error.
- Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
- Assert: resolvedTarget is contained in packageURL.
- If subpath split on “/“ or “\“ contains any “.”, “..” or “node_modules” segments, throw an Invalid Module Specifier error.
- If pattern is true, then
- Return the URL resolution of resolvedTarget with every instance of “*” replaced with subpath.
- Otherwise,
- Return the URL resolution of the concatenation of subpath and resolvedTarget.
- Otherwise, if target is a non-null Object, then
- If exports contains any index property keys, as defined in ECMA-262 [6.1.7 Array Index][], throw an Invalid Package Configuration error.
- For each property p of target, in object insertion order as,
- If p equals “default” or conditions contains an entry for p, then
- Let targetValue be the value of the p property in target.
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions).
- If resolved is equal to undefined, continue the loop.
- Return resolved.
- Return undefined.
- Otherwise, if target is an Array, then
- If _target.length is zero, return null.
- For each item targetValue in target, do
- Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions), continuing the loop on any Invalid Package Target error.
- If resolved is undefined, continue the loop.
- Return resolved.
- Return or throw the last fallback resolution null return or error.
- Otherwise, if target is null, return null.
- Otherwise throw an Invalid Package Target error.
ESM_FORMAT(url)
- Assert: url corresponds to an existing file.
- Let pjson be the result of READ_PACKAGE_SCOPE(url).
- If url ends in “.mjs”, then
- Return “module”.
- If url ends in “.cjs”, then
- Return “commonjs”.
- If pjson?.type exists and is “module”, then
- If url ends in “.js”, then
- Return “module”.
- Throw an Unsupported File Extension error.
- Otherwise,
- Throw an Unsupported File Extension error.
READ_PACKAGE_SCOPE(url)
- Let scopeURL be url.
- While scopeURL is not the file system root,
- Set scopeURL to the parent URL of scopeURL.
- If scopeURL ends in a “node_modules” path segment, return null.
- Let pjson be the result of READ_PACKAGE_JSON(scopeURL).
- If pjson is not null, then
- Return pjson.
- Return null.
READ_PACKAGE_JSON(packageURL)
- Let pjsonURL be the resolution of “package.json” within packageURL.
- If the file at pjsonURL does not exist, then
- Return null.
- If the file at packageURL does not parse as valid JSON, then
- Throw an Invalid Package Configuration error.
- Return the parsed JSON source of the file at pjsonURL.