esm: deprecate legacy main lookup for modules
PR-URL: https://github.com/nodejs/node/pull/36918 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
fd02dace6f
commit
255d6337cd
@ -2726,10 +2726,28 @@ settings set when the Node.js binary was compiled. However, the property has
|
||||
been mutable by user code making it impossible to rely on. The ability to
|
||||
change the value has been deprecated and will be disabled in the future.
|
||||
|
||||
### DEP0XXX: Main index lookup and extension searching
|
||||
<!-- YAML
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/36918
|
||||
description: Documentation-only deprecation
|
||||
with `--pending-deprecation` support.
|
||||
-->
|
||||
|
||||
Type: Documentation-only (supports [`--pending-deprecation`][])
|
||||
|
||||
Previously, `index.js` and extension searching lookups would apply to
|
||||
`import 'pkg'` main entry point resolution, even when resolving ES modules.
|
||||
|
||||
With this deprecation, all ES module main entry point resolutions require
|
||||
an explicit [`"exports"` or `"main"` entry][] with the exact file extension.
|
||||
|
||||
[Legacy URL API]: url.md#url_legacy_url_api
|
||||
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
|
||||
[RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3
|
||||
[WHATWG URL API]: url.md#url_the_whatwg_url_api
|
||||
[`"exports"` or `"main"` entry]: packages.md#packages_main_entry_point_export
|
||||
[`--pending-deprecation`]: cli.md#cli_pending_deprecation
|
||||
[`--throw-deprecation`]: cli.md#cli_throw_deprecation
|
||||
[`--unhandled-rejections`]: cli.md#cli_unhandled_rejections_mode
|
||||
@ -2852,7 +2870,7 @@ change the value has been deprecated and will be disabled in the future.
|
||||
[from_string_encoding]: buffer.md#buffer_static_method_buffer_from_string_encoding
|
||||
[legacy `urlObject`]: url.md#url_legacy_urlobject
|
||||
[static methods of `crypto.Certificate()`]: crypto.md#crypto_class_certificate
|
||||
[subpath exports]: #packages_subpath_exports
|
||||
[subpath folder mappings]: #packages_subpath_folder_mappings
|
||||
[subpath imports]: #packages_subpath_imports
|
||||
[subpath patterns]: #packages_subpath_patterns
|
||||
[subpath exports]: packages.md#packages_subpath_exports
|
||||
[subpath folder mappings]: packages.md#packages_subpath_folder_mappings
|
||||
[subpath imports]: packages.md#packages_subpath_imports
|
||||
[subpath patterns]: packages.md#packages_subpath_patterns
|
||||
|
@ -90,6 +90,36 @@ function emitFolderMapDeprecation(match, pjsonUrl, isExports, base) {
|
||||
);
|
||||
}
|
||||
|
||||
function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
|
||||
if (!pendingDeprecation)
|
||||
return;
|
||||
const { format } = defaultGetFormat(url);
|
||||
if (format !== 'module')
|
||||
return;
|
||||
const path = fileURLToPath(url);
|
||||
const pkgPath = fileURLToPath(new URL('.', packageJSONUrl));
|
||||
const basePath = fileURLToPath(base);
|
||||
if (main)
|
||||
process.emitWarning(
|
||||
`Package ${pkgPath} has a "main" field set to ${JSONStringify(main)}, ` +
|
||||
`excluding the full filename and extension to the resolved file at "${
|
||||
StringPrototypeSlice(path, pkgPath.length)}", imported from ${
|
||||
basePath}.\n Automatic extension resolution of the "main" field is` +
|
||||
'deprecated for ES modules.',
|
||||
'DeprecationWarning',
|
||||
'DEP0150'
|
||||
);
|
||||
else
|
||||
process.emitWarning(
|
||||
`No "main" or "exports" field defined in the package.json for ${pkgPath
|
||||
} resolving the main entry point "${
|
||||
StringPrototypeSlice(path, pkgPath.length)}", imported from ${basePath
|
||||
}.\nDefault "index" lookups for the main are deprecated for ES modules.`,
|
||||
'DeprecationWarning',
|
||||
'DEP0150'
|
||||
);
|
||||
}
|
||||
|
||||
function getConditionsSet(conditions) {
|
||||
if (conditions !== undefined && conditions !== DEFAULT_CONDITIONS) {
|
||||
if (!ArrayIsArray(conditions)) {
|
||||
@ -209,41 +239,33 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
if (fileExists(guess = new URL(`./${packageConfig.main}`,
|
||||
packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL(`./${packageConfig.main}.js`,
|
||||
packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL(`./${packageConfig.main}.json`,
|
||||
packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL(`./${packageConfig.main}.node`,
|
||||
packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL(`./${packageConfig.main}/index.js`,
|
||||
packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL(`./${packageConfig.main}/index.json`,
|
||||
packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL(`./${packageConfig.main}/index.node`,
|
||||
packageJSONUrl))) {
|
||||
} else if (fileExists(guess = new URL(`./${packageConfig.main}.js`,
|
||||
packageJSONUrl)));
|
||||
else if (fileExists(guess = new URL(`./${packageConfig.main}.json`,
|
||||
packageJSONUrl)));
|
||||
else if (fileExists(guess = new URL(`./${packageConfig.main}.node`,
|
||||
packageJSONUrl)));
|
||||
else if (fileExists(guess = new URL(`./${packageConfig.main}/index.js`,
|
||||
packageJSONUrl)));
|
||||
else if (fileExists(guess = new URL(`./${packageConfig.main}/index.json`,
|
||||
packageJSONUrl)));
|
||||
else if (fileExists(guess = new URL(`./${packageConfig.main}/index.node`,
|
||||
packageJSONUrl)));
|
||||
else guess = undefined;
|
||||
if (guess) {
|
||||
emitLegacyIndexDeprecation(guess, packageJSONUrl, base,
|
||||
packageConfig.main);
|
||||
return guess;
|
||||
}
|
||||
// Fallthrough.
|
||||
}
|
||||
if (fileExists(guess = new URL('./index.js', packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL('./index.js', packageJSONUrl)));
|
||||
// So fs.
|
||||
if (fileExists(guess = new URL('./index.json', packageJSONUrl))) {
|
||||
return guess;
|
||||
}
|
||||
if (fileExists(guess = new URL('./index.node', packageJSONUrl))) {
|
||||
else if (fileExists(guess = new URL('./index.json', packageJSONUrl)));
|
||||
else if (fileExists(guess = new URL('./index.node', packageJSONUrl)));
|
||||
else guess = undefined;
|
||||
if (guess) {
|
||||
emitLegacyIndexDeprecation(guess, packageJSONUrl, base, packageConfig.main);
|
||||
return guess;
|
||||
}
|
||||
// Not found.
|
||||
@ -891,3 +913,6 @@ module.exports = {
|
||||
packageExportsResolve,
|
||||
packageImportsResolve
|
||||
};
|
||||
|
||||
// cycle
|
||||
const { defaultGetFormat } = require('internal/modules/esm/get_format');
|
||||
|
@ -6,7 +6,9 @@ let curWarning = 0;
|
||||
const expectedWarnings = [
|
||||
'"./sub/"',
|
||||
'"./fallbackdir/"',
|
||||
'"./subpath/"'
|
||||
'"./subpath/"',
|
||||
'no_exports',
|
||||
'default_index'
|
||||
];
|
||||
|
||||
process.addListener('warning', mustCall((warning) => {
|
||||
|
@ -35,7 +35,7 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
|
||||
['pkgexports-sugar', { default: 'main' }],
|
||||
// Path patterns
|
||||
['pkgexports/subpath/sub-dir1', { default: 'main' }],
|
||||
['pkgexports/features/dir1', { default: 'main' }]
|
||||
['pkgexports/features/dir1', { default: 'main' }],
|
||||
]);
|
||||
|
||||
if (isRequire) {
|
||||
@ -44,6 +44,11 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
|
||||
validSpecifiers.set('pkgexports/subpath/dir1/', { default: 'main' });
|
||||
validSpecifiers.set('pkgexports/subpath/dir2', { default: 'index' });
|
||||
validSpecifiers.set('pkgexports/subpath/dir2/', { default: 'index' });
|
||||
} else {
|
||||
// No exports or main field
|
||||
validSpecifiers.set('no_exports', { default: 'index' });
|
||||
// Main field without extension
|
||||
validSpecifiers.set('default_index', { default: 'main' });
|
||||
}
|
||||
|
||||
for (const [validSpecifier, expected] of validSpecifiers) {
|
||||
|
1
test/fixtures/node_modules/default_index/index.js
generated
vendored
Normal file
1
test/fixtures/node_modules/default_index/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
export default 'main'
|
4
test/fixtures/node_modules/default_index/package.json
generated
vendored
Normal file
4
test/fixtures/node_modules/default_index/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "index",
|
||||
"type": "module"
|
||||
}
|
1
test/fixtures/node_modules/no_exports/index.js
generated
vendored
Normal file
1
test/fixtures/node_modules/no_exports/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
export default 'index'
|
3
test/fixtures/node_modules/no_exports/package.json
generated
vendored
Normal file
3
test/fixtures/node_modules/no_exports/package.json
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user