Skip to content

Commit 02f1d2f

Browse files
guybedfordtargos
authored andcommitted
esm: deprecate legacy main lookup for modules
PR-URL: #36918 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent b79b82d commit 02f1d2f

8 files changed

Lines changed: 95 additions & 36 deletions

File tree

‎doc/api/deprecations.md‎

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2699,10 +2699,28 @@ resolutions not in `node_modules`. This means there will not be deprecation
26992699
warnings for `"exports"` in dependencies. With `--pending-deprecation`, a
27002700
runtime warning results no matter where the `"exports"` usage occurs.
27012701

2702+
### DEP0XXX: Main index lookup and extension searching
2703+
<!-- YAML
2704+
changes:
2705+
- version: REPLACEME
2706+
pr-url: https://github.com/nodejs/node/pull/36918
2707+
description: Documentation-only deprecation
2708+
with `--pending-deprecation` support.
2709+
-->
2710+
2711+
Type: Documentation-only (supports [`--pending-deprecation`][])
2712+
2713+
Previously, `index.js` and extension searching lookups would apply to
2714+
`import 'pkg'` main entry point resolution, even when resolving ES modules.
2715+
2716+
With this deprecation, all ES module main entry point resolutions require
2717+
an explicit [`"exports"` or `"main"` entry][] with the exact file extension.
2718+
27022719
[Legacy URL API]: url.md#url_legacy_url_api
27032720
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
27042721
[RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3
27052722
[WHATWG URL API]: url.md#url_the_whatwg_url_api
2723+
[`"exports"` or `"main"` entry]: packages.md#packages_main_entry_point_export
27062724
[`--pending-deprecation`]: cli.md#cli_pending_deprecation
27072725
[`--throw-deprecation`]: cli.md#cli_throw_deprecation
27082726
[`--unhandled-rejections`]: cli.md#cli_unhandled_rejections_mode
@@ -2823,7 +2841,7 @@ runtime warning results no matter where the `"exports"` usage occurs.
28232841
[from_string_encoding]: buffer.md#buffer_static_method_buffer_from_string_encoding
28242842
[legacy `urlObject`]: url.md#url_legacy_urlobject
28252843
[static methods of `crypto.Certificate()`]: crypto.md#crypto_class_certificate
2826-
[subpath exports]: #packages_subpath_exports
2827-
[subpath folder mappings]: #packages_subpath_folder_mappings
2828-
[subpath imports]: #packages_subpath_imports
2829-
[subpath patterns]: #packages_subpath_patterns
2844+
[subpath exports]: packages.md#packages_subpath_exports
2845+
[subpath folder mappings]: packages.md#packages_subpath_folder_mappings
2846+
[subpath imports]: packages.md#packages_subpath_imports
2847+
[subpath patterns]: packages.md#packages_subpath_patterns

‎lib/internal/modules/esm/resolve.js‎

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,36 @@ function emitFolderMapDeprecation(match, pjsonUrl, isExports, base) {
9090
);
9191
}
9292

93+
functionemitLegacyIndexDeprecation(url,packageJSONUrl,base,main){
94+
if(!pendingDeprecation)
95+
return;
96+
const{ format }=defaultGetFormat(url);
97+
if(format!=='module')
98+
return;
99+
constpath=fileURLToPath(url);
100+
constpkgPath=fileURLToPath(newURL('.',packageJSONUrl));
101+
constbasePath=fileURLToPath(base);
102+
if(main)
103+
process.emitWarning(
104+
`Package ${pkgPath} has a "main" field set to ${JSONStringify(main)}, `+
105+
`excluding the full filename and extension to the resolved file at "${
106+
StringPrototypeSlice(path,pkgPath.length)}", imported from ${
107+
basePath}.\n Automatic extension resolution of the "main" field is`+
108+
'deprecated for ES modules.',
109+
'DeprecationWarning',
110+
'DEP0150'
111+
);
112+
else
113+
process.emitWarning(
114+
`No "main" or "exports" field defined in the package.json for ${pkgPath
115+
} resolving the main entry point "${
116+
StringPrototypeSlice(path,pkgPath.length)}", imported from ${basePath
117+
}.\nDefault "index" lookups for the main are deprecated for ES modules.`,
118+
'DeprecationWarning',
119+
'DEP0150'
120+
);
121+
}
122+
93123
functiongetConditionsSet(conditions){
94124
if(conditions!==undefined&&conditions!==DEFAULT_CONDITIONS){
95125
if(!ArrayIsArray(conditions)){
@@ -209,41 +239,33 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
209239
if(fileExists(guess=newURL(`./${packageConfig.main}`,
210240
packageJSONUrl))){
211241
returnguess;
212-
}
213-
if(fileExists(guess=newURL(`./${packageConfig.main}.js`,
214-
packageJSONUrl))){
215-
returnguess;
216-
}
217-
if(fileExists(guess=newURL(`./${packageConfig.main}.json`,
218-
packageJSONUrl))){
219-
returnguess;
220-
}
221-
if(fileExists(guess=newURL(`./${packageConfig.main}.node`,
222-
packageJSONUrl))){
223-
returnguess;
224-
}
225-
if(fileExists(guess=newURL(`./${packageConfig.main}/index.js`,
226-
packageJSONUrl))){
227-
returnguess;
228-
}
229-
if(fileExists(guess=newURL(`./${packageConfig.main}/index.json`,
230-
packageJSONUrl))){
231-
returnguess;
232-
}
233-
if(fileExists(guess=newURL(`./${packageConfig.main}/index.node`,
234-
packageJSONUrl))){
242+
}elseif(fileExists(guess=newURL(`./${packageConfig.main}.js`,
243+
packageJSONUrl)));
244+
elseif(fileExists(guess=newURL(`./${packageConfig.main}.json`,
245+
packageJSONUrl)));
246+
elseif(fileExists(guess=newURL(`./${packageConfig.main}.node`,
247+
packageJSONUrl)));
248+
elseif(fileExists(guess=newURL(`./${packageConfig.main}/index.js`,
249+
packageJSONUrl)));
250+
elseif(fileExists(guess=newURL(`./${packageConfig.main}/index.json`,
251+
packageJSONUrl)));
252+
elseif(fileExists(guess=newURL(`./${packageConfig.main}/index.node`,
253+
packageJSONUrl)));
254+
elseguess=undefined;
255+
if(guess){
256+
emitLegacyIndexDeprecation(guess,packageJSONUrl,base,
257+
packageConfig.main);
235258
returnguess;
236259
}
237260
// Fallthrough.
238261
}
239-
if(fileExists(guess=newURL('./index.js',packageJSONUrl))){
240-
returnguess;
241-
}
262+
if(fileExists(guess=newURL('./index.js',packageJSONUrl)));
242263
// So fs.
243-
if(fileExists(guess=newURL('./index.json',packageJSONUrl))){
244-
returnguess;
245-
}
246-
if(fileExists(guess=newURL('./index.node',packageJSONUrl))){
264+
elseif(fileExists(guess=newURL('./index.json',packageJSONUrl)));
265+
elseif(fileExists(guess=newURL('./index.node',packageJSONUrl)));
266+
elseguess=undefined;
267+
if(guess){
268+
emitLegacyIndexDeprecation(guess,packageJSONUrl,base,packageConfig.main);
247269
returnguess;
248270
}
249271
// Not found.
@@ -891,3 +913,6 @@ module.exports = {
891913
packageExportsResolve,
892914
packageImportsResolve
893915
};
916+
917+
// cycle
918+
const{ defaultGetFormat }=require('internal/modules/esm/get_format');

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ let curWarning = 0;
66
constexpectedWarnings=[
77
'"./sub/"',
88
'"./fallbackdir/"',
9-
'"./subpath/"'
9+
'"./subpath/"',
10+
'no_exports',
11+
'default_index'
1012
];
1113

1214
process.addListener('warning',mustCall((warning)=>{

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
3535
['pkgexports-sugar',{default: 'main'}],
3636
// Path patterns
3737
['pkgexports/subpath/sub-dir1',{default: 'main'}],
38-
['pkgexports/features/dir1',{default: 'main'}]
38+
['pkgexports/features/dir1',{default: 'main'}],
3939
]);
4040

4141
if(isRequire){
@@ -44,6 +44,11 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
4444
validSpecifiers.set('pkgexports/subpath/dir1/',{default: 'main'});
4545
validSpecifiers.set('pkgexports/subpath/dir2',{default: 'index'});
4646
validSpecifiers.set('pkgexports/subpath/dir2/',{default: 'index'});
47+
}else{
48+
// No exports or main field
49+
validSpecifiers.set('no_exports',{default: 'index'});
50+
// Main field without extension
51+
validSpecifiers.set('default_index',{default: 'main'});
4752
}
4853

4954
for(const[validSpecifier,expected]ofvalidSpecifiers){

‎test/fixtures/node_modules/default_index/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.

‎test/fixtures/node_modules/default_index/package.json‎

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

‎test/fixtures/node_modules/no_exports/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.

‎test/fixtures/node_modules/no_exports/package.json‎

Lines changed: 3 additions & 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)