diff options
Diffstat (limited to 'lib/internal/modules/esm/resolve.js')
-rw-r--r-- | lib/internal/modules/esm/resolve.js | 93 |
1 files changed, 31 insertions, 62 deletions
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index dcb7d10a479..1a28f994ec6 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -19,6 +19,7 @@ const { StringPrototypeIncludes, StringPrototypeIndexOf, StringPrototypeLastIndexOf, + StringPrototypeReplace, StringPrototypeSlice, StringPrototypeSplit, StringPrototypeStartsWith, @@ -82,38 +83,15 @@ const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); const emittedPackageWarnings = new SafeSet(); -/** - * @param {string} match - * @param {URL} pjsonUrl - * @param {boolean} isExports - * @param {string | URL | undefined} base - * @returns {void} - */ -function emitFolderMapDeprecation(match, pjsonUrl, isExports, base) { +function emitTrailingSlashPatternDeprecation(match, pjsonUrl, base) { const pjsonPath = fileURLToPath(pjsonUrl); - if (emittedPackageWarnings.has(pjsonPath + '|' + match)) return; emittedPackageWarnings.add(pjsonPath + '|' + match); process.emitWarning( - `Use of deprecated folder mapping "${match}" in the ${isExports ? - '"exports"' : '"imports"'} field module resolution of the package at ${ - pjsonPath}${base ? ` imported from ${fileURLToPath(base)}` : ''}.\n` + - `Update this package.json to use a subpath pattern like "${match}*".`, - 'DeprecationWarning', - 'DEP0148' - ); -} - -function emitTrailingSlashPatternDeprecation(match, pjsonUrl, isExports, base) { - const pjsonPath = fileURLToPath(pjsonUrl); - if (emittedPackageWarnings.has(pjsonPath + '|' + match)) - return; - emittedPackageWarnings.add(pjsonPath + '|' + match); - process.emitWarning( - `Use of deprecated trailing slash pattern mapping "${match}" in the ${ - isExports ? '"exports"' : '"imports"'} field module resolution of the ` + - `package at ${pjsonPath}${base ? ` imported from ${fileURLToPath(base)}` : + `Use of deprecated trailing slash pattern mapping "${match}" in the ` + + `"exports" field module resolution of the package at ${pjsonPath}${ + base ? ` imported from ${fileURLToPath(base)}` : ''}. Mapping specifiers ending in "/" is no longer supported.`, 'DeprecationWarning', 'DEP0155' @@ -504,8 +482,11 @@ function resolvePackageTargetString( if (subpath === '') return resolved; - if (RegExpPrototypeTest(invalidSegmentRegEx, subpath)) - throwInvalidSubpath(match + subpath, packageJSONUrl, internal, base); + if (RegExpPrototypeTest(invalidSegmentRegEx, subpath)) { + const request = pattern ? + StringPrototypeReplace(match, '*', () => subpath) : match + subpath; + throwInvalidSubpath(request, packageJSONUrl, internal, base); + } if (pattern) return new URL(RegExpPrototypeSymbolReplace(patternRegEx, resolved.href, @@ -641,7 +622,7 @@ function packageExportsResolve( ); if (resolved === null || resolved === undefined) throwExportsNotFound(packageSubpath, packageJSONUrl, base); - return { resolved, exact: true }; + return resolved; } let bestMatch = ''; @@ -653,9 +634,15 @@ function packageExportsResolve( if (patternIndex !== -1 && StringPrototypeStartsWith(packageSubpath, StringPrototypeSlice(key, 0, patternIndex))) { + // When this reaches EOL, this can throw at the top of the whole function: + // + // if (StringPrototypeEndsWith(packageSubpath, '/')) + // throwInvalidSubpath(packageSubpath) + // + // To match "imports" and the spec. if (StringPrototypeEndsWith(packageSubpath, '/')) emitTrailingSlashPatternDeprecation(packageSubpath, packageJSONUrl, - true, base); + base); const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); if (packageSubpath.length >= key.length && StringPrototypeEndsWith(packageSubpath, patternTrailer) && @@ -666,25 +653,17 @@ function packageExportsResolve( packageSubpath, patternIndex, packageSubpath.length - patternTrailer.length); } - } else if (key[key.length - 1] === '/' && - StringPrototypeStartsWith(packageSubpath, key) && - patternKeyCompare(bestMatch, key) === 1) { - bestMatch = key; - bestMatchSubpath = StringPrototypeSlice(packageSubpath, key.length); } } if (bestMatch) { const target = exports[bestMatch]; - const pattern = StringPrototypeIncludes(bestMatch, '*'); const resolved = resolvePackageTarget(packageJSONUrl, target, bestMatchSubpath, bestMatch, base, - pattern, false, conditions); + true, false, conditions); if (resolved === null || resolved === undefined) throwExportsNotFound(packageSubpath, packageJSONUrl, base); - if (!pattern) - emitFolderMapDeprecation(bestMatch, packageJSONUrl, true, base); - return { resolved, exact: pattern }; + return resolved; } throwExportsNotFound(packageSubpath, packageJSONUrl, base); @@ -711,7 +690,8 @@ function patternKeyCompare(a, b) { * @returns */ function packageImportsResolve(name, base, conditions) { - if (name === '#' || StringPrototypeStartsWith(name, '#/')) { + if (name === '#' || StringPrototypeStartsWith(name, '#/') || + StringPrototypeEndsWith(name, '/')) { const reason = 'is not a valid internal imports specifier name'; throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base)); } @@ -722,13 +702,12 @@ function packageImportsResolve(name, base, conditions) { const imports = packageConfig.imports; if (imports) { if (ObjectPrototypeHasOwnProperty(imports, name) && - !StringPrototypeIncludes(name, '*') && - !StringPrototypeEndsWith(name, '/')) { + !StringPrototypeIncludes(name, '*')) { const resolved = resolvePackageTarget( packageJSONUrl, imports[name], '', name, base, false, true, conditions ); - if (resolved !== null) - return { resolved, exact: true }; + if (resolved !== null && resolved !== undefined) + return resolved; } else { let bestMatch = ''; let bestMatchSubpath; @@ -749,26 +728,16 @@ function packageImportsResolve(name, base, conditions) { bestMatchSubpath = StringPrototypeSlice( name, patternIndex, name.length - patternTrailer.length); } - } else if (key[key.length - 1] === '/' && - StringPrototypeStartsWith(name, key) && - patternKeyCompare(bestMatch, key) === 1) { - bestMatch = key; - bestMatchSubpath = StringPrototypeSlice(name, key.length); } } if (bestMatch) { const target = imports[bestMatch]; - const pattern = StringPrototypeIncludes(bestMatch, '*'); const resolved = resolvePackageTarget(packageJSONUrl, target, bestMatchSubpath, bestMatch, - base, pattern, true, - conditions); - if (resolved !== null) { - if (!pattern) - emitFolderMapDeprecation(bestMatch, packageJSONUrl, false, base); - return { resolved, exact: pattern }; - } + base, true, true, conditions); + if (resolved !== null && resolved !== undefined) + return resolved; } } } @@ -845,7 +814,7 @@ function packageResolve(specifier, base, conditions) { packageConfig.exports !== undefined && packageConfig.exports !== null) { return packageExportsResolve( packageJSONUrl, packageSubpath, packageConfig, base, conditions - ).resolved; + ); } } @@ -870,7 +839,7 @@ function packageResolve(specifier, base, conditions) { if (packageConfig.exports !== undefined && packageConfig.exports !== null) return packageExportsResolve( packageJSONUrl, packageSubpath, packageConfig, base, conditions - ).resolved; + ); if (packageSubpath === '.') return legacyMainResolve(packageJSONUrl, packageConfig, base); return new URL(packageSubpath, packageJSONUrl); @@ -919,7 +888,7 @@ function moduleResolve(specifier, base, conditions) { if (shouldBeTreatedAsRelativeOrAbsolutePath(specifier)) { resolved = new URL(specifier, base); } else if (specifier[0] === '#') { - ({ resolved } = packageImportsResolve(specifier, base, conditions)); + resolved = packageImportsResolve(specifier, base, conditions); } else { try { resolved = new URL(specifier); |