Skip to content

Commit 81ac302

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

File tree

4 files changed

+35
-28
lines changed

4 files changed

+35
-28
lines changed

lib/internal/errors.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,26 @@ E('ERR_OUT_OF_RANGE',
11231123
msg += ` It must be ${range}. Received ${received}`;
11241124
return msg;
11251125
}, RangeError);
1126-
E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s', Error);
1126+
E('ERR_REQUIRE_ESM',
1127+
(filename, parentPath = null, packageJsonPath = null) => {
1128+
let msg = `Must use import to load ES Module: ${filename}`;
1129+
if (parentPath && packageJsonPath) {
1130+
const path = require('path');
1131+
const basename = path.basename(filename) === path.basename(parentPath) ?
1132+
filename : path.basename(filename);
1133+
msg +=
1134+
'\nrequire() of ES modules is not supported.\nrequire() of ' +
1135+
`${filename} ${parentPath ? `from ${parentPath} ` : ''}` +
1136+
'is an ES module file as it is a .js file whose nearest parent ' +
1137+
'package.json contains "type": "module" which defines all .js ' +
1138+
'files in that package scope as ES modules.\nInstead rename ' +
1139+
`${basename} to end in .cjs, change the requiring code to use ` +
1140+
'import(), or remove "type": "module" from ' +
1141+
`${packageJsonPath}.\n`;
1142+
return msg;
1143+
}
1144+
return msg;
1145+
}, Error);
11271146
E('ERR_SCRIPT_EXECUTION_INTERRUPTED',
11281147
'Script execution was interrupted by `SIGINT`', Error);
11291148
E('ERR_SERVER_ALREADY_LISTEN',

lib/internal/modules/cjs/loader.js

+4-23
Original file line numberDiff line numberDiff line change
@@ -1196,33 +1196,14 @@ Module.prototype._compile = function(content, filename) {
11961196
};
11971197

11981198
// Native extension for .js
1199-
let warnRequireESM = true;
12001199
Module._extensions['.js'] = function(module, filename) {
12011200
if (filename.endsWith('.js')) {
12021201
const pkg = readPackageScope(filename);
1202+
// Function require shouldn't be used in ES modules.
12031203
if (pkg && pkg.data && pkg.data.type === 'module') {
1204-
if (warnRequireESM) {
1205-
const parentPath = module.parent && module.parent.filename;
1206-
const basename = parentPath &&
1207-
path.basename(filename) === path.basename(parentPath) ?
1208-
filename : path.basename(filename);
1209-
process.emitWarning(
1210-
'require() of ES modules is not supported.\nrequire() of ' +
1211-
`${filename} ${parentPath ? `from ${module.parent.filename} ` : ''}` +
1212-
'is an ES module file as it is a .js file whose nearest parent ' +
1213-
'package.json contains "type": "module" which defines all .js ' +
1214-
'files in that package scope as ES modules.\nInstead rename ' +
1215-
`${basename} to end in .cjs, change the requiring code to use ` +
1216-
'import(), or remove "type": "module" from ' +
1217-
`${path.resolve(pkg.path, 'package.json')}.`,
1218-
undefined,
1219-
undefined,
1220-
undefined,
1221-
true
1222-
);
1223-
warnRequireESM = false;
1224-
}
1225-
throw new ERR_REQUIRE_ESM(filename);
1204+
const parentPath = module.parent && module.parent.filename;
1205+
const packageJsonPath = path.resolve(pkg.path, 'package.json');
1206+
throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
12261207
}
12271208
}
12281209
const content = fs.readFileSync(filename, 'utf8');

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@ child.on('close', common.mustCall((code, signal) => {
2626
assert.strictEqual(code, 1);
2727
assert.strictEqual(signal, null);
2828

29-
assert.ok(stderr.startsWith(`(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);
3839
assert.ok(stderr.indexOf(
3940
'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);
4044
}));

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

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

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

0 commit comments

Comments
 (0)