Skip to content

Commit 79cdbd0

Browse files
committed
test: cover extensionless ESM with explicit module type
1 parent 98a519b commit 79cdbd0

2 files changed

Lines changed: 42 additions & 12 deletions

File tree

lib/internal/modules/cjs/loader.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,12 +1930,13 @@ Module._extensions['.js'] = function(module, filename) {
19301930
format = 'typescript';
19311931
}
19321932
} else if (path.extname(filename) === '') {
1933-
// Extensionless files skip the .js suffix check above. When type: commonjs
1934-
// is explicit, force commonjs format so ESM syntax surfaces as SyntaxError
1935-
// instead of silently delegating to ESM.
1933+
// Extensionless files skip the .js suffix check above. When type is explicit,
1934+
// follow it so ESM syntax surfaces as SyntaxError for commonjs instead of
1935+
// silently delegating to ESM.
19361936
pkg = packageJsonReader.getNearestParentPackageJSON(filename);
1937-
if (pkg?.data?.type === 'commonjs') {
1938-
format = 'commonjs';
1937+
const typeFromPjson = pkg?.data?.type;
1938+
if (typeFromPjson === 'commonjs' || typeFromPjson === 'module') {
1939+
format = typeFromPjson;
19391940
}
19401941
}
19411942
const { source, format: loadedFormat } = loadSource(module, filename, format);

test/es-module/test-extensionless-esm-type-commonjs.js

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,63 @@ const tmpdir = require('../common/tmpdir');
77

88
tmpdir.refresh();
99

10-
const dir = tmpdir.resolve('extensionless-esm-commonjs');
11-
fs.mkdirSync(dir, { recursive: true });
10+
const commonjsDir = tmpdir.resolve('extensionless-esm-commonjs');
11+
fs.mkdirSync(commonjsDir, { recursive: true });
1212

1313
// package.json with type: commonjs
1414
fs.writeFileSync(
15-
path.join(dir, 'package.json'),
15+
path.join(commonjsDir, 'package.json'),
1616
'{\n "type": "commonjs"\n}\n',
1717
'utf8'
1818
);
1919

2020
// Extensionless executable with shebang + ESM syntax.
2121
// NOTE: Execute via process.execPath to avoid PATH/env differences.
22-
const scriptPath = path.join(dir, 'script'); // no extension
22+
const commonjsScriptPath = path.join(commonjsDir, 'script'); // no extension
2323
fs.writeFileSync(
24-
scriptPath,
24+
commonjsScriptPath,
2525
'#!/usr/bin/env node\n' +
2626
"console.log('script STARTED')\n" +
2727
"import { version } from 'node:process'\n" +
2828
'console.log(version)\n',
2929
'utf8'
3030
);
31-
fs.chmodSync(scriptPath, 0o755);
31+
fs.chmodSync(commonjsScriptPath, 0o755);
3232

3333
spawnSyncAndAssert(process.execPath, ['./script'], {
34-
cwd: dir,
34+
cwd: commonjsDir,
3535
encoding: 'utf8',
3636
}, {
3737
status: 1,
3838
stderr: /.+/,
3939
trim: true,
4040
});
41+
42+
const moduleDir = tmpdir.resolve('extensionless-esm-module');
43+
fs.mkdirSync(moduleDir, { recursive: true });
44+
45+
// package.json with type: module
46+
fs.writeFileSync(
47+
path.join(moduleDir, 'package.json'),
48+
'{\n "type": "module"\n}\n',
49+
'utf8'
50+
);
51+
52+
const moduleScriptPath = path.join(moduleDir, 'script'); // no extension
53+
fs.writeFileSync(
54+
moduleScriptPath,
55+
'#!/usr/bin/env node\n' +
56+
"console.log('script STARTED')\n" +
57+
"import { version } from 'node:process'\n" +
58+
'console.log(version)\n',
59+
'utf8'
60+
);
61+
fs.chmodSync(moduleScriptPath, 0o755);
62+
63+
spawnSyncAndAssert(process.execPath, ['./script'], {
64+
cwd: moduleDir,
65+
encoding: 'utf8',
66+
}, {
67+
stdout: /script STARTED[\s\S]*v\d+\./,
68+
trim: true,
69+
});

0 commit comments

Comments
 (0)