Skip to content

Commit

Permalink
module: do not warn for typeless package.json when there isn't one
Browse files Browse the repository at this point in the history
It was intended that warnings should only be emitted for an
existing package.json without a type. This fixes a confusing
warning telling users to update /package.json when there are
no package.json on the lookup path at all, like this:

[MODULE_TYPELESS_PACKAGE_JSON] Warning: ... parsed as an ES module
because module syntax was detected; to avoid the performance penalty
of syntax detection, add "type": "module" to /package.json

Drive-by: update the warning message to be clear about
reparsing and make it clear what's actionable.

PR-URL: nodejs#54045
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
joyeecheung authored and marco-ippolito committed Sep 2, 2024
1 parent c74f2ae commit ff308cd
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
13 changes: 7 additions & 6 deletions lib/internal/modules/esm/get_format.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ let typelessPackageJsonFilesWarnedAbout;
function warnTypelessPackageJsonFile(pjsonPath, url) {
typelessPackageJsonFilesWarnedAbout ??= new SafeSet();
if (!typelessPackageJsonFilesWarnedAbout.has(pjsonPath)) {
const warning = `${url} parsed as an ES module because module syntax was detected;` +
` to avoid the performance penalty of syntax detection, add "type": "module" to ${pjsonPath}`;
const warning = `Module type of ${url} is not specified and it doesn't parse as CommonJS.\n` +
'Reparsing as ES module because module syntax was detected. This incurs a performance overhead.\n' +
`To eliminate this warning, add "type": "module" to ${pjsonPath}.`;
process.emitWarning(warning, {
code: 'MODULE_TYPELESS_PACKAGE_JSON',
});
Expand All @@ -112,7 +113,7 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE
const ext = extname(url);

if (ext === '.js') {
const { type: packageType, pjsonPath } = getPackageScopeConfig(url);
const { type: packageType, pjsonPath, exists: foundPackageJson } = getPackageScopeConfig(url);
if (packageType !== 'none') {
return packageType;
}
Expand All @@ -133,7 +134,7 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE
// For ambiguous files (no type field, .js extension) we return
// undefined from `resolve` and re-run the check in `load`.
const format = detectModuleFormat(source, url);
if (format === 'module') {
if (format === 'module' && foundPackageJson) {
// This module has a .js extension, a package.json with no `type` field, and ESM syntax.
// Warn about the missing `type` field so that the user can avoid the performance penalty of detection.
warnTypelessPackageJsonFile(pjsonPath, url);
Expand All @@ -143,7 +144,7 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE
}
}
if (ext === '.ts' && getOptionValue('--experimental-strip-types')) {
const { type: packageType, pjsonPath } = getPackageScopeConfig(url);
const { type: packageType, pjsonPath, exists: foundPackageJson } = getPackageScopeConfig(url);
if (packageType !== 'none') {
return `${packageType}-typescript`;
}
Expand All @@ -168,7 +169,7 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE
const detectedFormat = detectModuleFormat(parsedSource, url);
// When source is undefined, default to module-typescript.
const format = detectedFormat ? `${detectedFormat}-typescript` : 'module-typescript';
if (format === 'module-typescript') {
if (format === 'module-typescript' && foundPackageJson) {
// This module has a .js extension, a package.json with no `type` field, and ESM syntax.
// Warn about the missing `type` field so that the user can avoid the performance penalty of detection.
warnTypelessPackageJsonFile(pjsonPath, url);
Expand Down
12 changes: 12 additions & 0 deletions test/es-module/test-esm-detect-ambiguous.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,18 @@ describe('Module syntax detection', { concurrency: !process.env.TEST_PARALLEL },
});
}

it('does not warn when there are no package.json', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
fixtures.path('es-modules/loose.js'),
]);

strictEqual(stderr, '');
strictEqual(stdout, 'executed\n');
strictEqual(code, 0);
strictEqual(signal, null);
});


it('warns only once for a package.json that affects multiple files', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
fixtures.path('es-modules/package-without-type/detected-as-esm.js'),
Expand Down

0 comments on commit ff308cd

Please sign in to comment.