Skip to content

Commit 19e940d

Browse files
committed
module: fix silent failure for ESM syntax in explicit commonjs entry
When a main entry point contains ESM syntax but is in a package with "type": "commonjs" in package.json, the module would silently exit with code 0 without executing or showing any error. This fix ensures that when the file is in a package with explicit "type": "commonjs", shouldDetectModule is set to false in wrapSafe, so the native compiler throws the proper SyntaxError with source line information rather than detecting it as a module and deferring to ESM loading (which caused the silent failure). Fixes: #61104
1 parent 6218d14 commit 19e940d

File tree

4 files changed

+40
-7
lines changed

4 files changed

+40
-7
lines changed

lib/internal/modules/cjs/loader.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,13 +1722,20 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
17221722

17231723
let shouldDetectModule = false;
17241724
if (format !== 'commonjs') {
1725-
if (cjsModuleInstance?.[kIsMainSymbol]) {
1726-
// For entry points, format detection is used unless explicitly disabled.
1727-
shouldDetectModule = getOptionValue('--experimental-detect-module');
1728-
} else {
1729-
// For modules being loaded by `require()`, if require(esm) is disabled,
1730-
// don't try to reparse to detect format and just throw for ESM syntax.
1731-
shouldDetectModule = getOptionValue('--require-module');
1725+
// Also check if we're in an explicit commonjs package, even if format wasn't
1726+
// set (e.g., for extensionless files). In explicit commonjs packages, we should
1727+
// not detect module syntax and instead let the syntax error propagate.
1728+
const pkg = packageJsonReader.getNearestParentPackageJSON(filename);
1729+
const explicitCommonJS = pkg?.data.type === 'commonjs';
1730+
if (!explicitCommonJS) {
1731+
if (cjsModuleInstance?.[kIsMainSymbol]) {
1732+
// For entry points, format detection is used unless explicitly disabled.
1733+
shouldDetectModule = getOptionValue('--experimental-detect-module');
1734+
} else {
1735+
// For modules being loaded by `require()`, if require(esm) is disabled,
1736+
// don't try to reparse to detect format and just throw for ESM syntax.
1737+
shouldDetectModule = getOptionValue('--require-module');
1738+
}
17321739
}
17331740
}
17341741
const result = compileFunctionForCJSLoader(content, filename, false /* is_sea_main */, shouldDetectModule);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Flags: --no-warnings
2+
'use strict';
3+
4+
// Test that running a main entry point with ESM syntax in a "type": "commonjs"
5+
// package throws an error instead of silently failing with exit code 0.
6+
// Regression test for https://github.com/nodejs/node/issues/61104
7+
8+
require('../common');
9+
const { spawnSyncAndAssert } = require('../common/child_process');
10+
const fixtures = require('../common/fixtures.js');
11+
const { execPath } = require('node:process');
12+
13+
const mainScript = fixtures.path('es-modules/package-type-commonjs-esm-syntax/esm-script.js');
14+
15+
spawnSyncAndAssert(execPath, [mainScript], {
16+
status: 1,
17+
signal: null,
18+
stderr: /import { version } from 'node:process'/,
19+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This file has ESM syntax but is in a "type": "commonjs" package
2+
console.log('script STARTED');
3+
import { version } from 'node:process';
4+
console.log(version);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "commonjs"
3+
}

0 commit comments

Comments
 (0)