Skip to content

Commit

Permalink
lib,test: improves ERR_REQUIRE_ESM message
Browse files Browse the repository at this point in the history
PR-URL: #30694
Fixes: #30599
Reviewed-By: Guy Bedford <[email protected]>
  • Loading branch information
juanarbol authored and targos committed Dec 9, 2019
1 parent 30756e3 commit 94f237e
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 28 deletions.
21 changes: 20 additions & 1 deletion lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,26 @@ E('ERR_OUT_OF_RANGE',
msg += ` It must be ${range}. Received ${received}`;
return msg;
}, RangeError);
E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s', Error);
E('ERR_REQUIRE_ESM',
(filename, parentPath = null, packageJsonPath = null) => {
let msg = `Must use import to load ES Module: ${filename}`;
if (parentPath && packageJsonPath) {
const path = require('path');
const basename = path.basename(filename) === path.basename(parentPath) ?
filename : path.basename(filename);
msg +=
'\nrequire() of ES modules is not supported.\nrequire() of ' +
`${filename} ${parentPath ? `from ${parentPath} ` : ''}` +
'is an ES module file as it is a .js file whose nearest parent ' +
'package.json contains "type": "module" which defines all .js ' +
'files in that package scope as ES modules.\nInstead rename ' +
`${basename} to end in .cjs, change the requiring code to use ` +
'import(), or remove "type": "module" from ' +
`${packageJsonPath}.\n`;
return msg;
}
return msg;
}, Error);
E('ERR_SCRIPT_EXECUTION_INTERRUPTED',
'Script execution was interrupted by `SIGINT`', Error);
E('ERR_SERVER_ALREADY_LISTEN',
Expand Down
27 changes: 4 additions & 23 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1139,33 +1139,14 @@ Module.prototype._compile = function(content, filename) {
};

// Native extension for .js
let warnRequireESM = true;
Module._extensions['.js'] = function(module, filename) {
if (filename.endsWith('.js')) {
const pkg = readPackageScope(filename);
// Function require shouldn't be used in ES modules.
if (pkg && pkg.data && pkg.data.type === 'module') {
if (warnRequireESM) {
const parentPath = module.parent && module.parent.filename;
const basename = parentPath &&
path.basename(filename) === path.basename(parentPath) ?
filename : path.basename(filename);
process.emitWarning(
'require() of ES modules is not supported.\nrequire() of ' +
`${filename} ${parentPath ? `from ${module.parent.filename} ` : ''}` +
'is an ES module file as it is a .js file whose nearest parent ' +
'package.json contains "type": "module" which defines all .js ' +
'files in that package scope as ES modules.\nInstead rename ' +
`${basename} to end in .cjs, change the requiring code to use ` +
'import(), or remove "type": "module" from ' +
`${path.resolve(pkg.path, 'package.json')}.`,
undefined,
undefined,
undefined,
true
);
warnRequireESM = false;
}
throw new ERR_REQUIRE_ESM(filename);
const parentPath = module.parent && module.parent.filename;
const packageJsonPath = path.resolve(pkg.path, 'package.json');
throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
}
}
const content = fs.readFileSync(filename, 'utf8');
Expand Down
10 changes: 7 additions & 3 deletions test/es-module/test-cjs-esm-warn.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,19 @@ child.on('close', common.mustCall((code, signal) => {
assert.strictEqual(code, 1);
assert.strictEqual(signal, null);

assert.ok(stderr.startsWith(`(node:${child.pid}) Warning: ` +
'require() of ES modules is not supported.\nrequire() of ' +
assert.ok(stderr.indexOf(
`Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ${required}` +
'\nrequire() of ES modules is not supported.\nrequire() of ' +
`${required} from ${requiring} ` +
'is an ES module file as it is a .js file whose nearest parent ' +
'package.json contains "type": "module" which defines all .js ' +
'files in that package scope as ES modules.\nInstead rename ' +
`${basename} to end in .cjs, change the requiring code to use ` +
'import(), or remove "type": "module" from ' +
`${pjson}.\n`));
`${pjson}.\n`) !== -1);
assert.ok(stderr.indexOf(
'Error [ERR_REQUIRE_ESM]: Must use import to load ES Module') !== -1);

assert.strictEqual(
stderr.match(/Must use import to load ES Module/g).length, 1);
}));
5 changes: 4 additions & 1 deletion test/es-module/test-esm-type-flag-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ try {
require('../fixtures/es-modules/package-type-module/index.js');
assert.fail('Expected CJS to fail loading from type: module package.');
} catch (e) {
assert(e.toString().match(/Error \[ERR_REQUIRE_ESM\]: Must use import to load ES Module:/));
assert.strictEqual(e.name, 'Error');
assert.strictEqual(e.code, 'ERR_REQUIRE_ESM');
assert(e.toString().match(/Must use import to load ES Module/g));
assert(e.message.match(/Must use import to load ES Module/g));
}

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

0 comments on commit 94f237e

Please sign in to comment.