解析器算法规范


¥Resolver Algorithm Specification

ESM_RESOLVE(specifier, parentURL)

  1. 让 resolved 为未定义。

    ¥Let resolved be undefined.

  2. 如果说明符是有效的 URL,则

    ¥If specifier is a valid URL, then

    1. 将 resolved 设置为将说明符解析和重新序列化为 URL 的结果。

      ¥Set resolved to the result of parsing and reserializing specifier as a URL.

  3. 否则,如果说明符以 "/"、"./" 或 "../" 开头,则

    ¥Otherwise, if specifier starts with "/", "./", or "../", then

    1. 将 resolved 设置为说明符相对于 parentURL 的 URL 解析。

      ¥Set resolved to the URL resolution of specifier relative to parentURL.

  4. 否则,如果说明符以 "" 开头,则

    ¥Otherwise, if specifier starts with "#", then

    1. 将已解析设置为 PACKAGE_IMPORTS_RESOLVE(specifier,parentURL,defaultConditions) 结果的解构值。

      ¥Set resolved to the destructured value of the result of PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, defaultConditions).

  5. 否则,

    ¥Otherwise,

    1. 注意:说明符现在是一个裸说明符。

      ¥Note: specifier is now a bare specifier.

    2. 设置解析 PACKAGE_RESOLVE(specifier,parentURL) 的结果。

      ¥Set resolved the result of PACKAGE_RESOLVE(specifier, parentURL).

  6. 让格式未定义。

    ¥Let format be undefined.

  7. 如果解析的是 "file:" URL,则

    ¥If resolved is a "file:" URL, then

    1. 如果已解析包含 "/" 或 ""(分别为 "%2F" 和 "%5C")的任何百分比编码,则

      ¥If resolved contains any percent encodings of "/" or "" ("%2F" and "%5C" respectively), then

      1. 抛出无效的模块说明符错误。

        ¥Throw an Invalid Module Specifier error.

    2. 如果解析的文件是一个目录,那么

      ¥If the file at resolved is a directory, then

      1. 引发不支持的目录导入错误。

        ¥Throw an Unsupported Directory Import error.

    3. 如果已解析的文件不存在,则

      ¥If the file at resolved does not exist, then

      1. 抛出模块未找到错误。

        ¥Throw a Module Not Found error.

    4. 设置 resolved 为 resolved 的真实路径,保持相同的 URL querystring 和 fragment 组件。

      ¥Set resolved to the real path of resolved, maintaining the same URL querystring and fragment components.

    5. 将格式设置为 ESM_FILE_FORMAT(resolved) 的结果。

      ¥Set format to the result of ESM_FILE_FORMAT(resolved).

  8. 否则,

    ¥Otherwise,

    1. 设置格式与解析的 URL 关联的内容类型的模块格式。

      ¥Set format the module format of the content type associated with the URL resolved.

  9. 加载解析为模块格式,格式。

    ¥Load resolved as module format, format.

PACKAGE_RESOLVE(packageSpecifier, parentURL)

  1. 让 packageName 未定义。

    ¥Let packageName be undefined.

  2. 如果 packageSpecifier 是空字符串,则

    ¥If packageSpecifier is an empty string, then

    1. 抛出无效的模块说明符错误。

      ¥Throw an Invalid Module Specifier error.

  3. 如果 packageSpecifier 是 Node.js 内置模块名称,则

    ¥If packageSpecifier is a Node.js builtin module name, then

    1. 返回与 packageSpecifier 连接的字符串 "node:"。

      ¥Return the string "node:" concatenated with packageSpecifier.

  4. 如果 packageSpecifier 不以 "@" 开头,则

    ¥If packageSpecifier does not start with "@", then

    1. 将 packageName 设置为 packageSpecifier 的子字符串,直到第一个 "/" 分隔符或字符串的结尾。

      ¥Set packageName to the substring of packageSpecifier until the first "/" separator or the end of the string.

  5. 否则,

    ¥Otherwise,

    1. 如果 packageSpecifier 不包含 "/" 分隔符,则

      ¥If packageSpecifier does not contain a "/" separator, then

      1. 抛出无效的模块说明符错误。

        ¥Throw an Invalid Module Specifier error.

    2. 将 packageName 设置为 packageSpecifier 的子字符串,直到第二个 "/" 分隔符或字符串的末尾。

      ¥Set packageName to the substring of packageSpecifier until the second "/" separator or the end of the string.

  6. 如果 packageName 以 "." 开头或包含 "" 或 "%",则

    ¥If packageName starts with "." or contains "" or "%", then

    1. 抛出无效的模块说明符错误。

      ¥Throw an Invalid Module Specifier error.

  7. 让 packageSubpath "." 与 packageSpecifier 的子字符串从 packageName 长度的位置连接起来。

    ¥Let packageSubpath be "." concatenated with the substring of packageSpecifier from the position at the length of packageName.

  8. 如果 packageSubpath 以 "/" 结尾,则

    ¥If packageSubpath ends in "/", then

    1. 抛出无效的模块说明符错误。

      ¥Throw an Invalid Module Specifier error.

  9. 令 selfUrl 为 PACKAGE_SELF_RESOLVE(packageName, packageSubpath, ParentURL) 的结果。

    ¥Let selfUrl be the result of PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL).

  10. 如果 selfUrl 不是未定义,则返回 selfUrl。

    ¥If selfUrl is not undefined, return selfUrl.

  11. 虽然 parentURL 不是文件系统根目录,

    ¥While parentURL is not the file system root,

    1. 令 packageURL 为 "node_modules/" 的 URL 解析与 packageSpecifier 连接,相对于 parentURL。

      ¥Let packageURL be the URL resolution of "node_modules/" concatenated with packageSpecifier, relative to parentURL.

    2. 将 parentURL 设置为 parentURL 的父文件夹 URL。

      ¥Set parentURL to the parent folder URL of parentURL.

    3. 如果 packageURL 处的文件夹不存在,则

      ¥If the folder at packageURL does not exist, then

      1. 继续下一个循环迭代。

        ¥Continue the next loop iteration.

    4. 令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。

      ¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).

    5. 如果 pjson 不为 null 并且 pjson.exports 不为 null 或未定义,则

      ¥If pjson is not null and pjson.exports is not null or undefined, then

      1. 返回 PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions) 的结果。

        ¥Return the result of PACKAGE_EXPORTS_RESOLVE(packageURL, packageSubpath, pjson.exports, defaultConditions).

    6. 否则,如果 packageSubpath 等于 ".",则

      ¥Otherwise, if packageSubpath is equal to ".", then

      1. 如果 pjson.main 是一个字符串,那么

        ¥If pjson.main is a string, then

        1. 返回 packageURL 中 main 的 URL 解析。

          ¥Return the URL resolution of main in packageURL.

    7. 否则,

      ¥Otherwise,

      1. 返回 packageURL 中 packageSubpath 的 URL 解析。

        ¥Return the URL resolution of packageSubpath in packageURL.

  12. 抛出模块未找到错误。

    ¥Throw a Module Not Found error.

PACKAGE_SELF_RESOLVE(packageName, packageSubpath, parentURL)

  1. 令 packageURL 为 LOOKUP_PACKAGE_SCOPE(parentURL) 的结果。

    ¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(parentURL).

  2. 如果 packageURL 为 null,则

    ¥If packageURL is null, then

    1. 返回未定义。

      ¥Return undefined.

  3. 令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。

    ¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).

  4. 如果 pjson 为 null 或者 pjson.exports 为 null 或未定义,则

    ¥If pjson is null or if pjson.exports is null or undefined, then

    1. 返回未定义。

      ¥Return undefined.

  5. 如果 pjson.name 等于 packageName,则

    ¥If pjson.name is equal to packageName, then

    1. 返回 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).

  6. 否则,返回未定义。

    ¥Otherwise, return undefined.

PACKAGE_EXPORTS_RESOLVE(packageURL, subpath, exports, conditions)

  1. 如果 exports 是一个对象,其键值以 "." 开头,键值不以 "." 开头,则抛出无效包配置错误。

    ¥If exports is an Object with both a key starting with "." and a key not starting with ".", throw an Invalid Package Configuration error.

  2. 如果子路径等于 ".",则

    ¥If subpath is equal to ".", then

    1. 让 mainExport 未定义。

      ¥Let mainExport be undefined.

    2. 如果导出是字符串或数组,或者不包含以 "." 开头的键的对象,则

      ¥If exports is a String or Array, or an Object containing no keys starting with ".", then

      1. 将 mainExport 设置为导出。

        ¥Set mainExport to exports.

    3. 否则,如果导出是包含 "." 属性的对象,则

      ¥Otherwise if exports is an Object containing a "." property, then

      1. 将 mainExport 设置为导出 ["."]。

        ¥Set mainExport to exports["."].

    4. 如果 mainExport 不是未定义的,那么

      ¥If mainExport is not undefined, then

      1. 令已解析为 PACKAGE_TARGET_RESOLVE(packageURL, mainExport, "", false, false, criteria) 的结果。

        ¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, mainExport, "", false, false, conditions).

      2. 如果已解决不为空或未定义,则

        ¥If resolved is not null or undefined, then

        1. 返回解决。

          ¥Return resolved.

  3. 否则,如果 exports 是一个 Object 并且 exports 的所有 key 都以 "." 开头,那么

    ¥Otherwise, if exports is an Object and all keys of exports start with ".", then

    1. 令 matchKey 为与子路径连接的字符串 "./"。

      ¥Let matchKey be the string "./" concatenated with subpath.

    2. 让 resolvedMatch 成为 PACKAGE_IMPORTS_EXPORTS_RESOLVE(matchKey,exports,packageURL,false,conditions)的结果。

      ¥Let resolvedMatch be result of PACKAGE_IMPORTS_EXPORTS_RESOLVE( matchKey, exports, packageURL, false, conditions).

    3. 如果 resolvedMatch.resolve 不为 null 或未定义,则

      ¥If resolvedMatch.resolve is not null or undefined, then

      1. 返回解决匹配。

        ¥Return resolvedMatch.

  4. 抛出包路径未导出错误。

    ¥Throw a Package Path Not Exported error.

PACKAGE_IMPORTS_RESOLVE(specifier, parentURL, conditions)

  1. 断言:说明符以 "" 开头。

    ¥Assert: specifier begins with "#".

  2. 如果说明符完全等于 "" 或以 "#/" 开头,则

    ¥If specifier is exactly equal to "#" or starts with "#/", then

    1. 抛出无效的模块说明符错误。

      ¥Throw an Invalid Module Specifier error.

  3. 令 packageURL 为 LOOKUP_PACKAGE_SCOPE(parentURL) 的结果。

    ¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(parentURL).

  4. 如果 packageURL 不为 null,则

    ¥If packageURL is not null, then

    1. 令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。

      ¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).

    2. 如果 pjson.imports 是一个非空对象,那么

      ¥If pjson.imports is a non-null Object, then

      1. 让 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).

      2. 如果 resolvedMatch.resolve 不为 null 或未定义,则

        ¥If resolvedMatch.resolve is not null or undefined, then

        1. 返回解决匹配。

          ¥Return resolvedMatch.

  5. 抛出包导入未定义错误。

    ¥Throw a Package Import Not Defined error.

PACKAGE_IMPORTS_EXPORTS_RESOLVE(matchKey, matchObj, packageURL, isImports, conditions)

  1. 如果 matchKey 是 matchObj 的键并且不以 "/" 结尾或包含 "*",则

    ¥If matchKey is a key of matchObj and does not end in "/" or contain ""*, then

    1. 令 target 为 matchObj[matchKey] 的值。

      ¥Let target be the value of matchObj[matchKey].

    2. 令已解析为 PACKAGE_TARGET_RESOLVE(packageURL, target, "", false, isImports, Conditions) 的结果。

      ¥Let resolved be the result of PACKAGE_TARGET_RESOLVE( packageURL, target, "", false, isImports, conditions).

    3. 返回对象 { resolved, exact: true }

      ¥Return the object { resolved, exact: true }.

  2. 令 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.

  3. 对于 expansionKeys 中的每个密钥 expansionKey,执行

    ¥For each key expansionKey in expansionKeys, do

    1. 令 patternBase 为空。

      ¥Let patternBase be null.

    2. 如果 expansionKey 包含 "",则将 patternBase 设置为 expansionKey 的子字符串,但不包括第一个 "" 字符。

      ¥If expansionKey contains "", set patternBase to the substring of expansionKey up to but excluding the first "" character.

    3. 如果 patternBase 不为 null 并且 matchKey 以 patternBase 开头但不等于 patternBase,则

      ¥If patternBase is not null and matchKey starts with but is not equal to patternBase, then

      1. 如果 matchKey 以 "/" 结尾,则抛出 Invalid Module Specifier 错误。

        ¥If matchKey ends with "/", throw an Invalid Module Specifier error.

      2. 设 patternTrailer 是第一个 "*" 字符后索引中 expansionKey 的子串。

        ¥Let patternTrailer be the substring of expansionKey from the index after the first ""* character.

      3. 如果 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

        1. 令 target 为 matchObj[expansionKey] 的值。

          ¥Let target be the value of matchObj[expansionKey].

        2. 令 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.

        3. 令 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).

        4. 返回对象 { resolved, exact: true }

          ¥Return the object { resolved, exact: true }.

    4. 否则,如果 patternBase 为空并且 matchKey 以 expandationKey 开头,则

      ¥Otherwise if patternBase is null and matchKey starts with expansionKey, then

      1. 令 target 为 matchObj[expansionKey] 的值。

        ¥Let target be the value of matchObj[expansionKey].

      2. 设 subpath 是从 expansionKey 长度的索引开始的 matchKey 的子字符串。

        ¥Let subpath be the substring of matchKey starting at the index of the length of expansionKey.

      3. 令 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).

      4. 返回对象 { resolved, exact: false }

        ¥Return the object { resolved, exact: false }.

  4. 返回对象 { resolved: null, exact: true }

    ¥Return the object { resolved: null, exact: true }.

PATTERN_KEY_COMPARE(keyA, keyB)

  1. 断言:keyA 以 "/" 结尾或仅包含一个 "*"。

    ¥Assert: keyA ends with "/" or contains only a single ""*.

  2. 断言:keyB 以 "/" 结尾或仅包含一个 "*"。

    ¥Assert: keyB ends with "/" or contains only a single ""*.

  3. 令 baseLengthA 为 "" 在 keyA 中的索引加一,如果 keyA 包含 "",否则为 keyA 的长度。

    ¥Let baseLengthA be the index of ""* in keyA plus one, if keyA contains ""*, or the length of keyA otherwise.

  4. 令 baseLengthB 为 "" 在 keyB 中的索引加一,如果 keyB 包含 "",否则为 keyB 的长度。

    ¥Let baseLengthB be the index of ""* in keyB plus one, if keyB contains ""*, or the length of keyB otherwise.

  5. 如果 baseLengthA 大于 baseLengthB,则返回 -1。

    ¥If baseLengthA is greater than baseLengthB, return -1.

  6. 如果 baseLengthB 大于 baseLengthA,则返回 1。

    ¥If baseLengthB is greater than baseLengthA, return 1.

  7. 如果 keyA 不包含 "*",则返回 1。

    ¥If keyA does not contain ""*, return 1.

  8. 如果 keyB 不包含 "*",则返回 -1。

    ¥If keyB does not contain ""*, return -1.

  9. 如果 keyA 的长度大于 keyB 的长度,返回-1。

    ¥If the length of keyA is greater than the length of keyB, return -1.

  10. 如果 keyB 的长度大于 keyA 的长度,则返回 1。

    ¥If the length of keyB is greater than the length of keyA, return 1.

  11. 返回 0。

    ¥Return 0.

PACKAGE_TARGET_RESOLVE(packageURL, target, subpath, pattern, internal, conditions)

  1. 如果目标是一个字符串,那么

    ¥If target is a String, then

    1. 如果模式为 false,子路径具有非零长度并且目标不以 "/" 结尾,则抛出无效模块说明符错误。

      ¥If pattern is false, subpath has non-zero length and target does not end with "/", throw an Invalid Module Specifier error.

    2. 如果目标不是以 "./" 开头,则

      ¥If target does not start with "./", then

      1. 如果内部为 true 并且目标不以 "../" 或 "/" 开头并且不是有效的 URL,则

        ¥If internal is true and target does not start with "../" or "/" and is not a valid URL, then

        1. 如果模式为真,那么

          ¥If pattern is true, then

          1. 返回 PACKAGE_RESOLVE(目标,其中 "*" 的每个实例都替换为子路径,packageURL + "/")。

            ¥Return PACKAGE_RESOLVE(target with every instance of ""* replaced by subpath, packageURL + "/").

        2. 返回 PACKAGE_RESOLVE(目标 + 子路径, packageURL + "/")。

          ¥Return PACKAGE_RESOLVE(target + subpath, packageURL + "/").

      2. 否则,抛出一个 Invalid Package Target 错误。

        ¥Otherwise, throw an Invalid Package Target error.

    3. 如果 "/" 或 "" 上的目标拆分在第一个段之后包含任何 "."、".." 或 "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.

    4. 令 resolvedTarget 为 packageURL 和 target 串联的 URL 解析。

      ¥Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.

    5. 断言:solvedTarget 包含在 packageURL 中。

      ¥Assert: resolvedTarget is contained in packageURL.

    6. 如果 "/" 或 "" 上的子路径拆分包含任何 "."、".." 或 "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.

    7. 如果模式为真,那么

      ¥If pattern is true, then

      1. 返回 resolvedTarget 的 URL 解析,其中 "*" 的每个实例都替换为子路径。

        ¥Return the URL resolution of resolvedTarget with every instance of ""* replaced with subpath.

    8. 否则,

      ¥Otherwise,

      1. 返回 subpath 和 resolvedTarget 串联的 URL 解析。

        ¥Return the URL resolution of the concatenation of subpath and resolvedTarget.

  2. 否则,如果 target 是非空对象,则

    ¥Otherwise, if target is a non-null Object, then

    1. 如果导出包含任何索引属性键,如 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.

    2. 对于目标的每个属性 p,按对象插入顺序为:

      ¥For each property p of target, in object insertion order as,

      1. 如果 p 等于 "default" 或条件包含 p 的条目,则

        ¥If p equals "default" or conditions contains an entry for p, then

        1. 设 targetValue 为 target 中 p 属性的值。

          ¥Let targetValue be the value of the p property in target.

        2. 令 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).

        3. 如果 resolved 等于 undefined,则继续循环。

          ¥If resolved is equal to undefined, continue the loop.

        4. 返回解决。

          ¥Return resolved.

    3. 返回未定义。

      ¥Return undefined.

  3. 否则,如果 target 是一个数组,那么

    ¥Otherwise, if target is an Array, then

    1. 如果 _target.length 为零,则返回 null。

      ¥If _target.length is zero, return null.

    2. 对于目标中的每个项目 targetValue,执行

      ¥For each item targetValue in target, do

      1. 令 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.

      2. 如果 resolved 未定义,则继续循环。

        ¥If resolved is undefined, continue the loop.

      3. 返回解决。

        ¥Return resolved.

    3. 返回或抛出最后的后备解决方案 null 返回或错误。

      ¥Return or throw the last fallback resolution null return or error.

  4. 否则,如果 target 为 null,则返回 null。

    ¥Otherwise, if target is null, return null.

  5. 否则抛出一个 Invalid Package Target 错误。

    ¥Otherwise throw an Invalid Package Target error.

ESM_FILE_FORMAT(url)

  1. 断言:url 对应于现有文件。

    ¥Assert: url corresponds to an existing file.

  2. 如果 url 以 ".mjs" 结尾,则

    ¥If url ends in ".mjs", then

    1. 返回 "module"。

      ¥Return "module".

  3. 如果 url 以 ".cjs" 结尾,则

    ¥If url ends in ".cjs", then

    1. 返回 "commonjs"。

      ¥Return "commonjs".

  4. 如果 url 以 ".json" 结尾,则

    ¥If url ends in ".json", then

    1. 返回 "json"。

      ¥Return "json".

  5. 令 packageURL 为 LOOKUP_PACKAGE_SCOPE(url) 的结果。

    ¥Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(url).

  6. 令 pjson 为 READ_PACKAGE_JSON(packageURL) 的结果。

    ¥Let pjson be the result of READ_PACKAGE_JSON(packageURL).

  7. 如果 pjson?.type 存在且为 "module",则

    ¥If pjson?.type exists and is "module", then

    1. 如果 url 以 ".js" 结尾,则

      ¥If url ends in ".js", then

      1. 返回 "module"。

        ¥Return "module".

    2. 抛出不支持的文件扩展名错误。

      ¥Throw an Unsupported File Extension error.

  8. 否则,

    ¥Otherwise,

    1. 抛出不支持的文件扩展名错误。

      ¥Throw an Unsupported File Extension error.

LOOKUP_PACKAGE_SCOPE(url)

  1. 让 scopeURL 为 url。

    ¥Let scopeURL be url.

  2. 虽然 scopeURL 不是文件系统根目录,

    ¥While scopeURL is not the file system root,

    1. 将 scopeURL 设置为 scopeURL 的父 URL。

      ¥Set scopeURL to the parent URL of scopeURL.

    2. 如果 scopeURL 以 "node_modules" 路径段结束,则返回 null。

      ¥If scopeURL ends in a "node_modules" path segment, return null.

    3. 设 pjsonURL 为 scopeURL 中 "package.json" 的解析。

      ¥Let pjsonURL be the resolution of "package.json" within scopeURL.

    4. 如果 pjsonURL 处的文件存在,则

      ¥if the file at pjsonURL exists, then

      1. 返回范围 URL。

        ¥Return scopeURL.

  3. 返回空值。

    ¥Return null.

READ_PACKAGE_JSON(packageURL)

  1. 设 pjsonURL 为 packageURL 中 "package.json" 的解析。

    ¥Let pjsonURL be the resolution of "package.json" within packageURL.

  2. 如果 pjsonURL 处的文件不存在,则

    ¥If the file at pjsonURL does not exist, then

    1. 返回空值。

      ¥Return null.

  3. 如果 packageURL 处的文件未解析为有效的 JSON,则

    ¥If the file at packageURL does not parse as valid JSON, then

    1. 抛出一个无效的包配置错误。

      ¥Throw an Invalid Package Configuration error.

  4. 在 pjsonURL 返回文件的已解析 JSON 源。

    ¥Return the parsed JSON source of the file at pjsonURL.