Skip to content

Commit aca1c28

Browse files
committed
module: warn on require of .js inside type: module
PR-URL: #29909 Reviewed-By: Jan Krems <jan.krems@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent 7812a61 commit aca1c28

File tree

4 files changed

+67
-5
lines changed

4 files changed

+67
-5
lines changed

lib/internal/modules/cjs/loader.js

+27-5
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,10 @@ function readPackageScope(checkPath) {
259259
if (checkPath.endsWith(path.sep + 'node_modules'))
260260
return false;
261261
const pjson = readPackage(checkPath);
262-
if (pjson) return pjson;
262+
if (pjson) return {
263+
path: checkPath,
264+
data: pjson
265+
};
263266
}
264267
return false;
265268
}
@@ -959,13 +962,32 @@ Module.prototype._compile = function(content, filename) {
959962
return result;
960963
};
961964

962-
963965
// Native extension for .js
966+
let warnRequireESM = true;
964967
Module._extensions['.js'] = function(module, filename) {
965-
if (experimentalModules && filename.endsWith('.js')) {
968+
if (filename.endsWith('.js')) {
966969
const pkg = readPackageScope(filename);
967-
if (pkg && pkg.type === 'module') {
968-
throw new ERR_REQUIRE_ESM(filename);
970+
if (pkg && pkg.data && pkg.data.type === 'module') {
971+
if (warnRequireESM) {
972+
const parentPath = module.parent && module.parent.filename;
973+
const basename = parentPath &&
974+
path.basename(filename) === path.basename(parentPath) ?
975+
filename : path.basename(filename);
976+
process.emitWarning(
977+
'require() of ES modules is not supported.\nrequire() of ' +
978+
`${filename} ${parentPath ? `from ${module.parent.filename} ` : ''}` +
979+
'is an ES module file as it is a .js file whose nearest parent ' +
980+
'package.json contains "type": "module" which defines all .js ' +
981+
'files in that package scope as ES modules.\nInstead rename ' +
982+
`${basename} to end in .cjs, change the requiring code to use ` +
983+
'import(), or remove "type": "module" from ' +
984+
`${path.resolve(pkg.path, 'package.json')}.`
985+
);
986+
warnRequireESM = false;
987+
}
988+
if (experimentalModules) {
989+
throw new ERR_REQUIRE_ESM(filename);
990+
}
969991
}
970992
}
971993
const content = fs.readFileSync(filename, 'utf8');

test/es-module/test-cjs-esm-warn.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fixtures = require('../common/fixtures');
5+
const { spawn } = require('child_process');
6+
const assert = require('assert');
7+
const path = require('path');
8+
9+
const requiring = path.resolve(fixtures.path('/es-modules/cjs-esm.js'));
10+
const required = path.resolve(
11+
fixtures.path('/es-modules/package-type-module/cjs.js')
12+
);
13+
const pjson = path.resolve(
14+
fixtures.path('/es-modules/package-type-module/package.json')
15+
);
16+
17+
const basename = 'cjs.js';
18+
19+
const child = spawn(process.execPath, [requiring]);
20+
let stderr = '';
21+
child.stderr.setEncoding('utf8');
22+
child.stderr.on('data', (data) => {
23+
stderr += data;
24+
});
25+
child.on('close', common.mustCall((code, signal) => {
26+
assert.strictEqual(code, 0);
27+
assert.strictEqual(signal, null);
28+
29+
assert.strictEqual(stderr, `(node:${child.pid}) Warning: ` +
30+
'require() of ES modules is not supported.\nrequire() of ' +
31+
`${required} from ${requiring} ` +
32+
'is an ES module file as it is a .js file whose nearest parent ' +
33+
'package.json contains "type": "module" which defines all .js ' +
34+
'files in that package scope as ES modules.\nInstead rename ' +
35+
`${basename} to end in .cjs, change the requiring code to use ` +
36+
'import(), or remove "type": "module" from ' +
37+
`${pjson}.\n`);
38+
}));

test/fixtures/es-modules/cjs-esm.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('./package-type-module/cjs.js');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 'asdf';

0 commit comments

Comments
 (0)