Skip to content

Commit e98509b

Browse files
juanarbolBethGriggs
authored andcommitted
lib,test: improves ERR_REQUIRE_ESM message
PR-URL: #30694 Fixes: #30599 Reviewed-By: Guy Bedford <guybedford@gmail.com>
1 parent dc084f9 commit e98509b

File tree

4 files changed

+38
-31
lines changed

4 files changed

+38
-31
lines changed

lib/internal/errors.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,26 @@ E('ERR_OUT_OF_RANGE',
11121112
msg += ` It must be ${range}. Received ${received}`;
11131113
return msg;
11141114
}, RangeError);
1115-
E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s', Error);
1115+
E('ERR_REQUIRE_ESM',
1116+
(filename, parentPath = null, packageJsonPath = null) => {
1117+
let msg = `Must use import to load ES Module: ${filename}`;
1118+
if (parentPath && packageJsonPath) {
1119+
const path = require('path');
1120+
const basename = path.basename(filename) === path.basename(parentPath) ?
1121+
filename : path.basename(filename);
1122+
msg +=
1123+
'\nrequire() of ES modules is not supported.\nrequire() of ' +
1124+
`${filename} ${parentPath ? `from ${parentPath} ` : ''}` +
1125+
'is an ES module file as it is a .js file whose nearest parent ' +
1126+
'package.json contains "type": "module" which defines all .js ' +
1127+
'files in that package scope as ES modules.\nInstead rename ' +
1128+
`${basename} to end in .cjs, change the requiring code to use ` +
1129+
'import(), or remove "type": "module" from ' +
1130+
`${packageJsonPath}.\n`;
1131+
return msg;
1132+
}
1133+
return msg;
1134+
}, Error);
11161135
E('ERR_SCRIPT_EXECUTION_INTERRUPTED',
11171136
'Script execution was interrupted by `SIGINT`', Error);
11181137
E('ERR_SERVER_ALREADY_LISTEN',

lib/internal/modules/cjs/loader.js

+4-25
Original file line numberDiff line numberDiff line change
@@ -1135,35 +1135,14 @@ Module.prototype._compile = function(content, filename) {
11351135
};
11361136

11371137
// Native extension for .js
1138-
let warnRequireESM = true;
11391138
Module._extensions['.js'] = function(module, filename) {
11401139
if (filename.endsWith('.js')) {
11411140
const pkg = readPackageScope(filename);
1141+
// Function require shouldn't be used in ES modules.
11421142
if (pkg && pkg.data && pkg.data.type === 'module') {
1143-
if (warnRequireESM) {
1144-
const parentPath = module.parent && module.parent.filename;
1145-
const basename = parentPath &&
1146-
path.basename(filename) === path.basename(parentPath) ?
1147-
filename : path.basename(filename);
1148-
process.emitWarning(
1149-
'require() of ES modules is not supported.\nrequire() of ' +
1150-
`${filename} ${parentPath ? `from ${module.parent.filename} ` : ''}` +
1151-
'is an ES module file as it is a .js file whose nearest parent ' +
1152-
'package.json contains "type": "module" which defines all .js ' +
1153-
'files in that package scope as ES modules.\nInstead rename ' +
1154-
`${basename} to end in .cjs, change the requiring code to use ` +
1155-
'import(), or remove "type": "module" from ' +
1156-
`${path.resolve(pkg.path, 'package.json')}.`,
1157-
undefined,
1158-
undefined,
1159-
undefined,
1160-
true
1161-
);
1162-
warnRequireESM = false;
1163-
}
1164-
if (experimentalModules) {
1165-
throw new ERR_REQUIRE_ESM(filename);
1166-
}
1143+
const parentPath = module.parent && module.parent.filename;
1144+
const packageJsonPath = path.resolve(pkg.path, 'package.json');
1145+
throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
11671146
}
11681147
}
11691148
const content = fs.readFileSync(filename, 'utf8');

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

+10-4
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,22 @@ child.stderr.on('data', (data) => {
2323
stderr += data;
2424
});
2525
child.on('close', common.mustCall((code, signal) => {
26-
assert.strictEqual(code, 0);
26+
assert.strictEqual(code, 1);
2727
assert.strictEqual(signal, null);
2828

29-
assert.strictEqual(stderr, `(node:${child.pid}) Warning: ` +
30-
'require() of ES modules is not supported.\nrequire() of ' +
29+
assert.ok(stderr.indexOf(
30+
`Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ${required}` +
31+
'\nrequire() of ES modules is not supported.\nrequire() of ' +
3132
`${required} from ${requiring} ` +
3233
'is an ES module file as it is a .js file whose nearest parent ' +
3334
'package.json contains "type": "module" which defines all .js ' +
3435
'files in that package scope as ES modules.\nInstead rename ' +
3536
`${basename} to end in .cjs, change the requiring code to use ` +
3637
'import(), or remove "type": "module" from ' +
37-
`${pjson}.\n`);
38+
`${pjson}.\n`) !== -1);
39+
assert.ok(stderr.indexOf(
40+
'Error [ERR_REQUIRE_ESM]: Must use import to load ES Module') !== -1);
41+
42+
assert.strictEqual(
43+
stderr.match(/Must use import to load ES Module/g).length, 1);
3844
}));

test/es-module/test-esm-type-flag-errors.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ try {
2828
require('../fixtures/es-modules/package-type-module/index.js');
2929
assert.fail('Expected CJS to fail loading from type: module package.');
3030
} catch (e) {
31-
assert(e.toString().match(/Error \[ERR_REQUIRE_ESM\]: Must use import to load ES Module:/));
31+
assert.strictEqual(e.name, 'Error');
32+
assert.strictEqual(e.code, 'ERR_REQUIRE_ESM');
33+
assert(e.toString().match(/Must use import to load ES Module/g));
34+
assert(e.message.match(/Must use import to load ES Module/g));
3235
}
3336

3437
function expect(opt = '', inputFile, want, wantsError = false) {

0 commit comments

Comments
 (0)