解析器算法规范
¥Resolver Algorithm Specification
ESM_RESOLVE(specifier, parentURL)
让 resolved 为未定义。
¥Let resolved be undefined.
如果说明符是有效的 URL,则
¥If specifier is a valid URL, then
将 resolved 设置为将说明符解析和重新序列化为 URL 的结果。
¥Set resolved to the result of parsing and reserializing specifier as a URL.
否则,如果说明符以 "/"、"./" 或 "../" 开头,则
¥Otherwise, if specifier starts with "/", "./", or "../", then
将 resolved 设置为说明符相对于 parentURL 的 URL 解析。
¥Set resolved to the URL resolution of specifier relative to parentURL.
否则,如果说明符以 "" 开头,则
¥Otherwise, if specifier starts with "#", then
将已解析设置为 PACKAGE_IMPORTS_RESOLVE(specifier,parentURL,defaultConditions) 结果的解构值。
¥Set resolved to the destructured value of the result of PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, defaultConditions).
否则,
¥Otherwise,
注意:说明符现在是一个裸说明符。
¥Note: specifier is now a bare specifier.
设置解析 PACKAGE_RESOLVE(specifier,parentURL) 的结果。
¥Set resolved the result of PACKAGE_RESOLVE(specifier, parentURL).
让格式未定义。
¥Let format be undefined.
如果解析的是 "file:" URL,则
¥If resolved is a "file:" URL, then
如果已解析包含 "/" 或 ""(分别为 "%2F" 和 "%5C")的任何百分比编码,则
¥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.
设置 resolved 为 resolved 的真实路径,保持相同的 URL querystring 和 fragment 组件。
¥Set resolved to the real path of resolved, maintaining the same URL querystring and fragment components.
将格式设置为 ESM_FILE_FORMAT(resolved) 的结果。
¥Set format to the result of ESM_FILE_FORMAT(resolved).
否则,
¥Otherwise,
设置格式与解析的 URL 关联的内容类型的模块格式。
¥Set format the module format of the content type associated with the URL resolved.
加载解析为模块格式,格式。
¥Load resolved as module format, format.
PACKAGE_RESOLVE(packageSpecifier, parentURL)
让 packageName 未定义。
¥Let packageName be undefined.
如果 packageSpecifier 是空字符串,则
¥If packageSpecifier is an empty string, then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
如果 packageSpecifier 是 Node.js 内置模块名称,则
¥If packageSpecifier is a Node.js builtin module name, then
返回与 packageSpecifier 连接的字符串 "node:"。
¥Return the string "node:" concatenated with packageSpecifier.
如果 packageSpecifier 不以 "@" 开头,则
¥If packageSpecifier does not start with "@", then
将 packageName 设置为 packageSpecifier 的子字符串,直到第一个 "/" 分隔符或字符串的结尾。
¥Set packageName to the substring of packageSpecifier until the first "/" separator or the end of the string.
否则,
¥Otherwise,
如果 packageSpecifier 不包含 "/" 分隔符,则
¥If packageSpecifier does not contain a "/" separator, then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
将 packageName 设置为 packageSpecifier 的子字符串,直到第二个 "/" 分隔符或字符串的末尾。
¥Set packageName to the substring of packageSpecifier until the second "/" separator or the end of the string.
如果 packageName 以 "." 开头或包含 "" 或 "%",则
¥If packageName starts with "." or contains "" or "%", then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
让 packageSubpath "." 与 packageSpecifier 的子字符串从 packageName 长度的位置连接起来。
¥Let packageSubpath be "." concatenated with the substring of packageSpecifier from the position at the length of packageName.
如果 packageSubpath 以 "/" 结尾,则
¥If packageSubpath ends in "/", then
抛出无效的模块说明符错误。
¥Throw an Invalid Module Specifier error.
令 selfUrl 为 PACKAGE_SELF_RESOLVE(packageName, packageSubpath, ParentURL) 的结果。
¥Let selfUrl be the result of PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL).
如果 selfUrl 不是未定义,则返回 selfUrl。
¥If selfUrl is not undefined, return selfUrl.
虽然 parentURL 不是文件系统根目录,
¥While parentURL is not the file system root,
令 packageURL 为 "node_modules/" 的 URL 解析与 packageSpecifier 连接,相对于 parentURL。
¥Let packageURL be the URL resolution of "node_modules/" concatenated with packageSpecifier, relative to parentURL.
将 parentURL 设置为 parentURL 的父文件夹 URL。
¥Set parentURL to the parent folder URL of parentURL.
如果 packageURL 处的文件夹不存在,则
¥If the folder at packageURL does not exist, then
继续下一个循环迭代。
¥Continue the next loop iteration.
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
如果 pjson 不为 null 并且 pjson.exports 不为 null 或未定义,则
¥If pjson is not null and pjson.exports is not null or undefined, then
返回 PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions) 的结果。
¥Return the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).
否则,如果 packageSubpath 等于 ".",则
¥Otherwise, if packageSubpath is equal to ".", then
如果 pjson.main 是一个字符串,那么
¥If pjson.main is a string, then
返回 packageURL 中 main 的 URL 解析。
¥Return the URL resolution of main in packageURL.
否则,
¥Otherwise,
返回 packageURL 中 packageSubpath 的 URL 解析。
¥Return the URL resolution of packageSubpath in packageURL.
抛出模块未找到错误。
¥Throw a Module Not Found error.
PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL)
令 packageURL 为 LOOKUP_PACKAGE_SCOPE(parentURL) 的结果。
¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(parentURL).
如果 packageURL 为 null,则
¥If packageURL is null, then
返回未定义。
¥Return undefined.
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
如果 pjson 为 null 或者 pjson.exports 为 null 或未定义,则
¥If pjson is null or if pjson.exports is null or undefined, then
返回未定义。
¥Return undefined.
如果 pjson.name 等于 packageName,则
¥If pjson.name is equal to packageName, then
返回 PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions) 结果的解析解构值。
¥Return the resolved destructured value of the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).
否则,返回未定义。
¥Otherwise, return undefined.
PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, exports, conditions)
如果 exports 是一个对象,其键值以 "." 开头,键值不以 "." 开头,则抛出无效包配置错误。
¥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
让 mainExport 未定义。
¥Let mainExport be undefined.
如果导出是字符串或数组,或者不包含以 "." 开头的键的对象,则
¥If exports is a String or Array, or an Object containing no keys starting with ".", then
将 mainExport 设置为导出。
¥Set mainExport to exports.
否则,如果导出是包含 "." 属性的对象,则
¥Otherwise if exports is an Object containing a "." property, then
将 mainExport 设置为导出 ["."]。
¥Set mainExport to exports["."].
如果 mainExport 不是未定义的,那么
¥If mainExport is not undefined, then
令已解析为 PACKAGE_TARGET_RESOLVE(packageURL, mainExport, "", false, false, criteria) 的结果。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, mainExport, "", false, false, conditions).
如果已解决不为空或未定义,则
¥If resolved is not null or undefined, then
返回解决。
¥Return resolved.
否则,如果 exports 是一个 Object 并且 exports 的所有 key 都以 "." 开头,那么
¥Otherwise, if exports is an Object and all keys of exports start with ".", then
令 matchKey 为与子路径连接的字符串 "./"。
¥Let matchKey be the string "./" concatenated with subpath.
让 resolvedMatch 成为 PACKAGE_IMPORTS_EXPORTS_RESOLVE(matchKey,exports,packageURL,false,conditions)的结果。
¥Let resolvedMatch be result of PACKAGE_IMPORTS_EXPORTS_RESOLVE( matchKey, exports, packageURL, false, conditions).
如果 resolvedMatch.resolve 不为 null 或未定义,则
¥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.
令 packageURL 为 LOOKUP_PACKAGE_SCOPE(parentURL) 的结果。
¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(parentURL).
如果 packageURL 不为 null,则
¥If packageURL is not null, then
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
如果 pjson.imports 是一个非空对象,那么
¥If pjson.imports is a non-null Object, then
让 resolvedMatch 成为 PACKAGE_IMPORTS_EXPORTS_RESOLVE(specifier, pjson.imports, packageURL, true, Conditions)的结果。
¥Let resolvedMatch be the result of PACKAGE_IMPORTS_EXPORTS_RESOLVE(specifier, pjson.imports, packageURL, true, conditions).
如果 resolvedMatch.resolve 不为 null 或未定义,则
¥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)
如果 matchKey 是 matchObj 的键并且不以 "/" 结尾或包含 "*",则
¥If matchKey is a key of matchObj and does not end in "/" or contain ""*, then
令 target 为 matchObj[matchKey] 的值。
¥Let target be the value of matchObj[matchKey].
令已解析为 PACKAGE_TARGET_RESOLVE(packageURL, target, "", false, isImports, Conditions) 的结果。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, "", false, isImports, conditions).
返回对象 { resolved, exact: true }。
¥Return the object { resolved, exact: true }.
令 expansionKeys 为 matchObj 的键列表,要么以 "/" 结尾,要么仅包含单个 "*",由排序函数 PATTERN_KEY_COMPARE 排序,该函数按特异性降序排列。
¥Let expansionKeys be the list of keys of matchObj either ending in "/" or containing only a single ""*, sorted by the sorting function PATTERN_KEY_COMPARE which orders in descending order of specificity.
对于 expansionKeys 中的每个密钥 expansionKey,执行
¥For each key expansionKey in expansionKeys, do
令 patternBase 为空。
¥Let patternBase be null.
如果 expansionKey 包含 "",则将 patternBase 设置为 expansionKey 的子字符串,但不包括第一个 "" 字符。
¥If expansionKey contains "", set patternBase to the substring of expansionKey up to but excluding the first "" character.
如果 patternBase 不为 null 并且 matchKey 以 patternBase 开头但不等于 patternBase,则
¥If patternBase is not null and matchKey starts with but is not equal to patternBase, then
如果 matchKey 以 "/" 结尾,则抛出 Invalid Module Specifier 错误。
¥If matchKey ends with "/", throw an Invalid Module Specifier error.
设 patternTrailer 是第一个 "*" 字符后索引中 expansionKey 的子串。
¥Let patternTrailer be the substring of expansionKey from the index after the first ""* character.
如果 patternTrailer 的长度为零,或者 matchKey 以 patternTrailer 结尾并且 matchKey 的长度大于或等于 expandationKey 的长度,则
¥If patternTrailer has zero length, or if matchKey ends with patternTrailer and the length of matchKey is greater than or equal to the length of expansionKey, then
令 target 为 matchObj[expansionKey] 的值。
¥Let target be the value of matchObj[expansionKey].
令 subpath 为 matchKey 的子字符串,从 patternBase 长度的索引开始,直到 matchKey 的长度减去 patternTrailer 的长度。
¥Let subpath be the substring of matchKey starting at the index of the length of patternBase up to the length of matchKey minus the length of patternTrailer.
令 resolved 为 PACKAGE_TARGET_RESOLVE(packageURL, target, subpath, true, isImports, Conditions) 的结果。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, true, isImports, conditions).
返回对象 { resolved, exact: true }。
¥Return the object { resolved, exact: true }.
否则,如果 patternBase 为空并且 matchKey 以 expandationKey 开头,则
¥Otherwise if patternBase is null and matchKey starts with expansionKey, then
令 target 为 matchObj[expansionKey] 的值。
¥Let target be the value of matchObj[expansionKey].
设 subpath 是从 expansionKey 长度的索引开始的 matchKey 的子字符串。
¥Let subpath be the substring of matchKey starting at the index of the length of expansionKey.
令 resolved 为 PACKAGE_TARGET_RESOLVE(packageURL, target, subpath, false, isImports, Conditions) 的结果。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, subpath, false, isImports, conditions).
返回对象 { resolved, exact: false }。
¥Return the object { resolved, exact: false }.
返回对象 { resolved: null, exact: true }。
¥Return the object { resolved: null, exact: true }.
PATTERN_KEY_COMPARE(keyA, keyB)
断言:keyA 以 "/" 结尾或仅包含一个 "*"。
¥Assert: keyA ends with "/" or contains only a single ""*.
断言:keyB 以 "/" 结尾或仅包含一个 "*"。
¥Assert: keyB ends with "/" or contains only a single ""*.
令 baseLengthA 为 "" 在 keyA 中的索引加一,如果 keyA 包含 "",否则为 keyA 的长度。
¥Let baseLengthA be the index of ""* in keyA plus one, if keyA contains ""*, or the length of keyA otherwise.
令 baseLengthB 为 "" 在 keyB 中的索引加一,如果 keyB 包含 "",否则为 keyB 的长度。
¥Let baseLengthB be the index of ""* in keyB plus one, if keyB contains ""*, or the length of keyB otherwise.
如果 baseLengthA 大于 baseLengthB,则返回 -1。
¥If baseLengthA is greater than baseLengthB, return -1.
如果 baseLengthB 大于 baseLengthA,则返回 1。
¥If baseLengthB is greater than baseLengthA, return 1.
如果 keyA 不包含 "*",则返回 1。
¥If keyA does not contain ""*, return 1.
如果 keyB 不包含 "*",则返回 -1。
¥If keyB does not contain ""*, return -1.
如果 keyA 的长度大于 keyB 的长度,返回-1。
¥If the length of keyA is greater than the length of keyB, return -1.
如果 keyB 的长度大于 keyA 的长度,则返回 1。
¥If the length of keyB is greater than the length of keyA, return 1.
返回 0。
¥Return 0.
PACKAGE_TARGET_RESOLVE(packageURL, target, subpath, pattern, internal, conditions)
如果目标是一个字符串,那么
¥If target is a String, then
如果模式为 false,子路径具有非零长度并且目标不以 "/" 结尾,则抛出无效模块说明符错误。
¥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
如果内部为 true 并且目标不以 "../" 或 "/" 开头并且不是有效的 URL,则
¥If internal is true and target does not start with "../" or "/" and is not a valid URL, then
如果模式为真,那么
¥If pattern is true, then
返回 PACKAGE_RESOLVE(目标,其中 "*" 的每个实例都替换为子路径,packageURL + "/")。
¥Return PACKAGE_RESOLVE(target with every instance of ""* replaced by subpath, packageURL + "/").
返回 PACKAGE_RESOLVE(目标 + 子路径, packageURL + "/")。
¥Return PACKAGE_RESOLVE(target + subpath, packageURL + "/").
否则,抛出一个 Invalid Package Target 错误。
¥Otherwise, throw an Invalid Package Target error.
如果 "/" 或 "" 上的目标拆分在第一个段之后包含任何 "."、".." 或 "node_modules" 段,不区分大小写并包括百分比编码变体,则抛出无效包目标错误。
¥If target split on "/" or "" contains any ".", "..", or "node_modules" segments after the first segment, case insensitive and including percent encoded variants, throw an Invalid Package Target error.
令 resolvedTarget 为 packageURL 和 target 串联的 URL 解析。
¥Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
断言:solvedTarget 包含在 packageURL 中。
¥Assert: resolvedTarget is contained in packageURL.
如果 "/" 或 "" 上的子路径拆分包含任何 "."、".." 或 "node_modules" 段,不区分大小写并包括百分比编码变体,则抛出无效模块说明符错误。
¥If subpath split on "/" or "" contains any ".", "..", or "node_modules" segments, case insensitive and including percent encoded variants, throw an Invalid Module Specifier error.
如果模式为真,那么
¥If pattern is true, then
返回 resolvedTarget 的 URL 解析,其中 "*" 的每个实例都替换为子路径。
¥Return the URL resolution of resolvedTarget with every instance of ""* replaced with subpath.
否则,
¥Otherwise,
返回 subpath 和 resolvedTarget 串联的 URL 解析。
¥Return the URL resolution of the concatenation of subpath and resolvedTarget.
否则,如果 target 是非空对象,则
¥Otherwise, if target is a non-null Object, then
如果导出包含任何索引属性键,如 ECMA-262 6.1.7 数组索引 中所定义,则抛出无效包配置错误。
¥If exports contains any index property keys, as defined in ECMA-262 6.1.7 Array Index, throw an Invalid Package Configuration error.
对于目标的每个属性 p,按对象插入顺序为:
¥For each property p of target, in object insertion order as,
如果 p 等于 "default" 或条件包含 p 的条目,则
¥If p equals "default" or conditions contains an entry for p, then
设 targetValue 为 target 中 p 属性的值。
¥Let targetValue be the value of the p property in target.
令 resolved 为 PACKAGE_TARGET_RESOLVE(packageURL, targetValue, subpath,pattern,internal,conditions)的结果。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions).
如果 resolved 等于 undefined,则继续循环。
¥If resolved is equal to undefined, continue the loop.
返回解决。
¥Return resolved.
返回未定义。
¥Return undefined.
否则,如果 target 是一个数组,那么
¥Otherwise, if target is an Array, then
如果 _target.length 为零,则返回 null。
¥If _target.length is zero, return null.
对于目标中的每个项目 targetValue,执行
¥For each item targetValue in target, do
令 resolved 为 PACKAGE_TARGET_RESOLVE(packageURL, targetValue, subpath,pattern,internal,conditions)的结果,在任何无效的包目标错误上继续循环。
¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, targetValue, subpath, pattern, internal, conditions), continuing the loop on any Invalid Package Target error.
如果 resolved 未定义,则继续循环。
¥If resolved is undefined, continue the loop.
返回解决。
¥Return resolved.
返回或抛出最后的后备解决方案 null 返回或错误。
¥Return or throw the last fallback resolution null return or error.
否则,如果 target 为 null,则返回 null。
¥Otherwise, if target is null, return null.
否则抛出一个 Invalid Package Target 错误。
¥Otherwise throw an Invalid Package Target error.
ESM_FILE_FORMAT(url)
断言:url 对应于现有文件。
¥Assert: url corresponds to an existing file.
如果 url 以 ".mjs" 结尾,则
¥If url ends in ".mjs", then
返回 "module"。
¥Return "module".
如果 url 以 ".cjs" 结尾,则
¥If url ends in ".cjs", then
返回 "commonjs"。
¥Return "commonjs".
如果 url 以 ".json" 结尾,则
¥If url ends in ".json", then
返回 "json"。
¥Return "json".
令 packageURL 为 LOOKUP_PACKAGE_SCOPE(url) 的结果。
¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(url).
令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。
¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).
如果 pjson?.type 存在且为 "module",则
¥If pjson?.type exists and is "module", then
如果 url 以 ".js" 结尾,则
¥If url ends in ".js", then
返回 "module"。
¥Return "module".
抛出不支持的文件扩展名错误。
¥Throw an Unsupported File Extension error.
否则,
¥Otherwise,
抛出不支持的文件扩展名错误。
¥Throw an Unsupported File Extension error.
LOOKUP_PACKAGE_SCOPE(url)
让 scopeURL 为 url。
¥Let scopeURL be url.
虽然 scopeURL 不是文件系统根目录,
¥While scopeURL is not the file system root,
将 scopeURL 设置为 scopeURL 的父 URL。
¥Set scopeURL to the parent URL of scopeURL.
如果 scopeURL 以 "node_modules" 路径段结束,则返回 null。
¥If scopeURL ends in a "node_modules" path segment, return null.
设 pjsonURL 为 scopeURL 中 "package.json" 的解析。
¥Let pjsonURL be the resolution of "package.json" within scopeURL.
如果 pjsonURL 处的文件存在,则
¥if the file at pjsonURL exists, then
返回范围 URL。
¥Return scopeURL.
返回空值。
¥Return null.
READ_PACKAGE_JSON(packageURL)
设 pjsonURL 为 packageURL 中 "package.json" 的解析。
¥Let pjsonURL be the resolution of "package.json" within packageURL.
如果 pjsonURL 处的文件不存在,则
¥If the file at pjsonURL does not exist, then
返回空值。
¥Return null.
如果 packageURL 处的文件未解析为有效的 JSON,则
¥If the file at packageURL does not parse as valid JSON, then
抛出一个无效的包配置错误。
¥Throw an Invalid Package Configuration error.
在 pjsonURL 返回文件的已解析 JSON 源。
¥Return the parsed JSON source of the file at pjsonURL.