Skip to content

Commit 549a58e

Browse files
guybedfordMylesBorins
authored andcommitted
esm: disable non-js exts outside package scopes
PR-URL: #30501 Reviewed-By: Jan Krems <[email protected]> Reviewed-By: Myles Borins <[email protected]>
1 parent d043692 commit 549a58e

File tree

3 files changed

+38
-22
lines changed

3 files changed

+38
-22
lines changed

doc/api/esm.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -1310,8 +1310,7 @@ _defaultEnv_ is the conditional environment name priority array,
13101310
> 1. Return _"module"_.
13111311
> 1. Throw an _Unsupported File Extension_ error.
13121312
> 1. Otherwise,
1313-
> 1. If _isMain_ is **true** or _url_ ends in _".js"_, _".json"_ or
1314-
> _".node"_, then
1313+
> 1. If _isMain_ is **true**, then
13151314
> 1. Return _"commonjs"_.
13161315
> 1. Throw an _Unsupported File Extension_ error.
13171316

lib/internal/modules/esm/default_resolve.js

+16-20
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,19 @@ function resolve(specifier, parentURL) {
7878
}
7979

8080
const isMain = parentURL === undefined;
81-
if (isMain)
81+
if (isMain) {
8282
parentURL = pathToFileURL(`${process.cwd()}/`).href;
8383

84+
// This is the initial entry point to the program, and --input-type has
85+
// been passed as an option; but --input-type can only be used with
86+
// --eval, --print or STDIN string input. It is not allowed with file
87+
// input, to avoid user confusion over how expansive the effect of the
88+
// flag should be (i.e. entry point only, package scope surrounding the
89+
// entry point, etc.).
90+
if (typeFlag)
91+
throw new ERR_INPUT_TYPE_NOT_ALLOWED();
92+
}
93+
8494
let url = moduleWrapResolve(specifier, parentURL);
8595

8696
if (isMain ? !preserveSymlinksMain : !preserveSymlinks) {
@@ -93,27 +103,13 @@ function resolve(specifier, parentURL) {
93103
url.hash = old.hash;
94104
}
95105

96-
const type = getPackageType(url.href);
97-
98106
const ext = extname(url.pathname);
99-
const extMap =
100-
type !== TYPE_MODULE ? legacyExtensionFormatMap : extensionFormatMap;
101-
let format = extMap[ext];
102-
103-
if (isMain && typeFlag) {
104-
// This is the initial entry point to the program, and --input-type has
105-
// been passed as an option; but --input-type can only be used with
106-
// --eval, --print or STDIN string input. It is not allowed with file
107-
// input, to avoid user confusion over how expansive the effect of the
108-
// flag should be (i.e. entry point only, package scope surrounding the
109-
// entry point, etc.).
110-
throw new ERR_INPUT_TYPE_NOT_ALLOWED();
111-
}
107+
let format = extensionFormatMap[ext];
108+
if (ext === '.js' || (!format && isMain))
109+
format = getPackageType(url.href) === TYPE_MODULE ? 'module' : 'commonjs';
112110
if (!format) {
113-
if (isMain)
114-
format = type === TYPE_MODULE ? 'module' : 'commonjs';
115-
else if (esModuleSpecifierResolution === 'node')
116-
format = 'commonjs';
111+
if (esModuleSpecifierResolution === 'node')
112+
format = legacyExtensionFormatMap[ext];
117113
else
118114
throw new ERR_UNKNOWN_FILE_EXTENSION(fileURLToPath(url));
119115
}

test/es-module/test-esm-non-js.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const { spawn } = require('child_process');
5+
const assert = require('assert');
6+
7+
const entry = require.resolve('./test-esm-json.mjs');
8+
9+
// Verify non-js extensions fail for ESM
10+
const child = spawn(process.execPath, ['--experimental-modules', entry]);
11+
12+
let stderr = '';
13+
child.stderr.setEncoding('utf8');
14+
child.stderr.on('data', (data) => {
15+
stderr += data;
16+
});
17+
child.on('close', common.mustCall((code, signal) => {
18+
assert.strictEqual(code, 1);
19+
assert.strictEqual(signal, null);
20+
assert.ok(stderr.indexOf('ERR_UNKNOWN_FILE_EXTENSION') !== -1);
21+
}));

0 commit comments

Comments
 (0)