Skip to content

Commit 7216fb1

Browse files
committed
module: deprecate trailing slash pattern mappings
PR-URL: #40039 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
1 parent 798c0cb commit 7216fb1

File tree

9 files changed

+57
-1
lines changed

9 files changed

+57
-1
lines changed

doc/api/deprecations.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,20 @@ Type: Documentation-only (supports [`--pending-deprecation`][])
28142814
The `'hash'` and `'mgf1Hash'` options are replaced with `'hashAlgorithm'`
28152815
and `'mgf1HashAlgorithm'`.
28162816

2817+
### DEP0155: Trailing slashes in pattern specifier resolutions
2818+
<!-- YAML
2819+
changes:
2820+
- version: REPLACEME
2821+
pr-url: https://github.com/nodejs/node/pull/40039
2822+
description: Documentation-only deprecation
2823+
with `--pending-deprecation` support.
2824+
-->
2825+
2826+
Type: Documentation-only (supports [`--pending-deprecation`][])
2827+
2828+
The remapping of specifiers ending in `"/"` like `import 'pkg/x/'` is deprecated
2829+
for package `"exports"` and `"imports"` pattern resolutions.
2830+
28172831
[Legacy URL API]: url.md#legacy-url-api
28182832
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
28192833
[RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3

doc/api/esm.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,8 @@ _isImports_, _conditions_)
12051205
> _expansionKey_ up to but excluding the first _"*"_ character.
12061206
> 1. If _patternBase_ is not **null** and _matchKey_ starts with but is not
12071207
> equal to _patternBase_, then
1208+
> 1. If _matchKey_ ends with _"/"_, throw an _Invalid Module Specifier_
1209+
> error.
12081210
> 1. Let _patternTrailer_ be the substring of _expansionKey_ from the
12091211
> index after the first _"*"_ character.
12101212
> 1. If _patternTrailer_ has zero length, or if _matchKey_ ends with

lib/internal/modules/esm/resolve.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const { sep, relative, resolve } = require('path');
4040
const preserveSymlinks = getOptionValue('--preserve-symlinks');
4141
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
4242
const typeFlag = getOptionValue('--input-type');
43+
const pendingDeprecation = getOptionValue('--pending-deprecation');
4344
const { URL, pathToFileURL, fileURLToPath } = require('internal/url');
4445
const {
4546
ERR_INPUT_TYPE_NOT_ALLOWED,
@@ -106,6 +107,22 @@ function emitFolderMapDeprecation(match, pjsonUrl, isExports, base) {
106107
);
107108
}
108109

110+
function emitTrailingSlashPatternDeprecation(match, pjsonUrl, isExports, base) {
111+
if (!pendingDeprecation) return;
112+
const pjsonPath = fileURLToPath(pjsonUrl);
113+
if (emittedPackageWarnings.has(pjsonPath + '|' + match))
114+
return;
115+
emittedPackageWarnings.add(pjsonPath + '|' + match);
116+
process.emitWarning(
117+
`Use of deprecated trailing slash pattern mapping "${match}" in the ${
118+
isExports ? '"exports"' : '"imports"'} field module resolution of the ` +
119+
`package at ${pjsonPath}${base ? ` imported from ${fileURLToPath(base)}` :
120+
''}. Mapping specifiers ending in "/" is no longer supported.`,
121+
'DeprecationWarning',
122+
'DEP0155'
123+
);
124+
}
125+
109126
/**
110127
* @param {URL} url
111128
* @param {URL} packageJSONUrl
@@ -639,6 +656,9 @@ function packageExportsResolve(
639656
if (patternIndex !== -1 &&
640657
StringPrototypeStartsWith(packageSubpath,
641658
StringPrototypeSlice(key, 0, patternIndex))) {
659+
if (StringPrototypeEndsWith(packageSubpath, '/'))
660+
emitTrailingSlashPatternDeprecation(packageSubpath, packageJSONUrl,
661+
true, base);
642662
const patternTrailer = StringPrototypeSlice(key, patternIndex + 1);
643663
if (packageSubpath.length >= key.length &&
644664
StringPrototypeEndsWith(packageSubpath, patternTrailer) &&

test/es-module/test-esm-exports-deprecations.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
// Flags: --pending-deprecation
12
import { mustCall } from '../common/index.mjs';
23
import assert from 'assert';
34

45
let curWarning = 0;
56
const expectedWarnings = [
67
'"./sub/"',
78
'"./fallbackdir/"',
9+
'"./trailing-pattern-slash/"',
810
'"./subpath/"',
11+
'"./subpath/dir1/"',
12+
'"./subpath/dir2/"',
913
'no_exports',
1014
'default_index',
1115
];

test/es-module/test-esm-exports.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,19 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
4141
['pkgexports/dir2/dir2/trailer', { default: 'index' }],
4242
['pkgexports/a/dir1/dir1', { default: 'main' }],
4343
['pkgexports/a/b/dir1/dir1', { default: 'main' }],
44+
45+
// Deprecated:
46+
['pkgexports/trailing-pattern-slash/',
47+
{ default: 'trailing-pattern-slash' }],
4448
]);
4549

4650
if (isRequire) {
4751
validSpecifiers.set('pkgexports/subpath/file', { default: 'file' });
4852
validSpecifiers.set('pkgexports/subpath/dir1', { default: 'main' });
53+
// Deprecated:
4954
validSpecifiers.set('pkgexports/subpath/dir1/', { default: 'main' });
5055
validSpecifiers.set('pkgexports/subpath/dir2', { default: 'index' });
56+
// Deprecated:
5157
validSpecifiers.set('pkgexports/subpath/dir2/', { default: 'index' });
5258
} else {
5359
// No exports or main field

test/es-module/test-esm-local-deprecations.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Flags: --pending-deprecation
2+
13
import '../common/index.mjs';
24
import assert from 'assert';
35
import fixtures from '../common/fixtures.js';
@@ -9,10 +11,14 @@ const selfDeprecatedFolders =
911
const deprecatedFoldersIgnore =
1012
fixtures.path('/es-modules/deprecated-folders-ignore/main.js');
1113

14+
const deprecatedTrailingSlashPattern =
15+
fixtures.path('/es-modules/pattern-trailing-slash.mjs');
16+
1217
const expectedWarnings = [
1318
'"./" in the "exports" field',
1419
'"#self/" in the "imports" field',
1520
'"./folder/" in the "exports" field',
21+
'"./trailing-pattern-slash/" in the "exports" field',
1622
];
1723

1824
process.addListener('warning', (warning) => {
@@ -28,5 +34,6 @@ process.on('exit', () => {
2834
(async () => {
2935
await import(pathToFileURL(selfDeprecatedFolders));
3036
await import(pathToFileURL(deprecatedFoldersIgnore));
37+
await import(pathToFileURL(deprecatedTrailingSlashPattern));
3138
})()
3239
.catch((err) => console.error(err));
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import 'pkgexports/trailing-pattern-slash/';

test/fixtures/node_modules/pkgexports/package.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/fixtures/node_modules/pkgexports/trailing-pattern-slash/index.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)