esm: refine ERR_REQUIRE_ESM errors
PR-URL: https://github.com/nodejs/node/pull/39175 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
499f693b20
commit
e2a6399be7
@ -14,6 +14,7 @@ const {
|
|||||||
AggregateError,
|
AggregateError,
|
||||||
ArrayFrom,
|
ArrayFrom,
|
||||||
ArrayIsArray,
|
ArrayIsArray,
|
||||||
|
ArrayPrototypeFilter,
|
||||||
ArrayPrototypeIncludes,
|
ArrayPrototypeIncludes,
|
||||||
ArrayPrototypeIndexOf,
|
ArrayPrototypeIndexOf,
|
||||||
ArrayPrototypeJoin,
|
ArrayPrototypeJoin,
|
||||||
@ -788,6 +789,34 @@ const fatalExceptionStackEnhancers = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ensures the printed error line is from user code.
|
||||||
|
let _kArrowMessagePrivateSymbol, _setHiddenValue;
|
||||||
|
function setArrowMessage(err, arrowMessage) {
|
||||||
|
if (!_kArrowMessagePrivateSymbol) {
|
||||||
|
({
|
||||||
|
arrow_message_private_symbol: _kArrowMessagePrivateSymbol,
|
||||||
|
setHiddenValue: _setHiddenValue,
|
||||||
|
} = internalBinding('util'));
|
||||||
|
}
|
||||||
|
_setHiddenValue(err, _kArrowMessagePrivateSymbol, arrowMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide stack lines before the first user code line.
|
||||||
|
function hideInternalStackFrames(error) {
|
||||||
|
overrideStackTrace.set(error, (error, stackFrames) => {
|
||||||
|
let frames = stackFrames;
|
||||||
|
if (typeof stackFrames === 'object') {
|
||||||
|
frames = ArrayPrototypeFilter(
|
||||||
|
stackFrames,
|
||||||
|
(frm) => !StringPrototypeStartsWith(frm.getFileName(),
|
||||||
|
'node:internal')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ArrayPrototypeUnshift(frames, error);
|
||||||
|
return ArrayPrototypeJoin(frames, '\n at ');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Node uses an AbortError that isn't exactly the same as the DOMException
|
// Node uses an AbortError that isn't exactly the same as the DOMException
|
||||||
// to make usage of the error in userland and readable-stream easier.
|
// to make usage of the error in userland and readable-stream easier.
|
||||||
// It is a regular error with `.code` and `.name`.
|
// It is a regular error with `.code` and `.name`.
|
||||||
@ -806,8 +835,10 @@ module.exports = {
|
|||||||
exceptionWithHostPort,
|
exceptionWithHostPort,
|
||||||
getMessage,
|
getMessage,
|
||||||
hideStackFrames,
|
hideStackFrames,
|
||||||
|
hideInternalStackFrames,
|
||||||
isErrorStackTraceLimitWritable,
|
isErrorStackTraceLimitWritable,
|
||||||
isStackOverflowError,
|
isStackOverflowError,
|
||||||
|
setArrowMessage,
|
||||||
connResetException,
|
connResetException,
|
||||||
uvErrmapGet,
|
uvErrmapGet,
|
||||||
uvException,
|
uvException,
|
||||||
@ -842,6 +873,7 @@ module.exports = {
|
|||||||
// Note: Please try to keep these in alphabetical order
|
// Note: Please try to keep these in alphabetical order
|
||||||
//
|
//
|
||||||
// Note: Node.js specific errors must begin with the prefix ERR_
|
// Note: Node.js specific errors must begin with the prefix ERR_
|
||||||
|
|
||||||
E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
|
E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
|
||||||
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
|
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
|
||||||
E('ERR_ASSERTION', '%s', Error);
|
E('ERR_ASSERTION', '%s', Error);
|
||||||
@ -1406,23 +1438,32 @@ E('ERR_PERFORMANCE_INVALID_TIMESTAMP',
|
|||||||
'%d is not a valid timestamp', TypeError);
|
'%d is not a valid timestamp', TypeError);
|
||||||
E('ERR_PERFORMANCE_MEASURE_INVALID_OPTIONS', '%s', TypeError);
|
E('ERR_PERFORMANCE_MEASURE_INVALID_OPTIONS', '%s', TypeError);
|
||||||
E('ERR_REQUIRE_ESM',
|
E('ERR_REQUIRE_ESM',
|
||||||
(filename, parentPath = null, packageJsonPath = null) => {
|
function(filename, hasEsmSyntax, parentPath = null, packageJsonPath = null) {
|
||||||
let msg = `Must use import to load ES Module: ${filename}`;
|
hideInternalStackFrames(this);
|
||||||
if (parentPath && packageJsonPath) {
|
let msg = `require() of ES Module ${filename}${parentPath ? ` from ${
|
||||||
|
parentPath}` : ''} not supported.`;
|
||||||
|
if (!packageJsonPath) {
|
||||||
|
if (StringPrototypeEndsWith(filename, '.mjs'))
|
||||||
|
msg += `\nInstead change the require of ${filename} to a dynamic ` +
|
||||||
|
'import() which is available in all CommonJS modules.';
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const basename = path.basename(filename) === path.basename(parentPath) ?
|
const basename = path.basename(filename) === path.basename(parentPath) ?
|
||||||
filename : path.basename(filename);
|
filename : path.basename(filename);
|
||||||
msg +=
|
if (hasEsmSyntax) {
|
||||||
'\nrequire() of ES modules is not supported.\nrequire() of ' +
|
msg += `\nInstead change the require of ${basename} in ${parentPath} to` +
|
||||||
`${filename} from ${parentPath} ` +
|
' a dynamic import() which is available in all CommonJS modules.';
|
||||||
'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;
|
||||||
}
|
}
|
||||||
|
msg += `\n${basename} is treated as an ES module file as it is a .js ` +
|
||||||
|
'file whose nearest parent package.json contains "type": "module" ' +
|
||||||
|
'which declares all .js files in that package scope as ES modules.' +
|
||||||
|
`\nInstead rename ${basename} to end in .cjs, change the requiring ` +
|
||||||
|
'code to use dynamic import() which is available in all CommonJS ' +
|
||||||
|
'modules, or change "type": "module" to "type": "commonjs" in ' +
|
||||||
|
`${packageJsonPath} to treat all .js files as CommonJS (using .mjs for ` +
|
||||||
|
'all ES modules instead).\n';
|
||||||
return msg;
|
return msg;
|
||||||
}, Error);
|
}, Error);
|
||||||
E('ERR_SCRIPT_EXECUTION_INTERRUPTED',
|
E('ERR_SCRIPT_EXECUTION_INTERRUPTED',
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
const {
|
const {
|
||||||
ArrayPrototypeForEach,
|
ArrayPrototypeForEach,
|
||||||
ArrayPrototypeJoin,
|
ArrayPrototypeJoin,
|
||||||
|
ArrayPrototypeSome,
|
||||||
ObjectDefineProperty,
|
ObjectDefineProperty,
|
||||||
ObjectPrototypeHasOwnProperty,
|
ObjectPrototypeHasOwnProperty,
|
||||||
SafeMap,
|
SafeMap,
|
||||||
@ -184,9 +185,26 @@ function normalizeReferrerURL(referrer) {
|
|||||||
return new URL(referrer).href;
|
return new URL(referrer).href;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For error messages only - used to check if ESM syntax is in use.
|
||||||
|
function hasEsmSyntax(code) {
|
||||||
|
const parser = require('internal/deps/acorn/acorn/dist/acorn').Parser;
|
||||||
|
let root;
|
||||||
|
try {
|
||||||
|
root = parser.parse(code, { sourceType: 'module', ecmaVersion: 'latest' });
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArrayPrototypeSome(root.body, (stmt) =>
|
||||||
|
stmt.type === 'ExportNamedDeclaration' ||
|
||||||
|
stmt.type === 'ImportDeclaration' ||
|
||||||
|
stmt.type === 'ExportAllDeclaration');
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
addBuiltinLibsToObject,
|
addBuiltinLibsToObject,
|
||||||
cjsConditions,
|
cjsConditions,
|
||||||
|
hasEsmSyntax,
|
||||||
loadNativeModule,
|
loadNativeModule,
|
||||||
makeRequireFunction,
|
makeRequireFunction,
|
||||||
normalizeReferrerURL,
|
normalizeReferrerURL,
|
||||||
|
@ -48,6 +48,7 @@ const {
|
|||||||
Proxy,
|
Proxy,
|
||||||
ReflectApply,
|
ReflectApply,
|
||||||
ReflectSet,
|
ReflectSet,
|
||||||
|
RegExpPrototypeExec,
|
||||||
RegExpPrototypeTest,
|
RegExpPrototypeTest,
|
||||||
SafeMap,
|
SafeMap,
|
||||||
SafeWeakMap,
|
SafeWeakMap,
|
||||||
@ -58,6 +59,7 @@ const {
|
|||||||
StringPrototypeLastIndexOf,
|
StringPrototypeLastIndexOf,
|
||||||
StringPrototypeIndexOf,
|
StringPrototypeIndexOf,
|
||||||
StringPrototypeMatch,
|
StringPrototypeMatch,
|
||||||
|
StringPrototypeRepeat,
|
||||||
StringPrototypeSlice,
|
StringPrototypeSlice,
|
||||||
StringPrototypeSplit,
|
StringPrototypeSplit,
|
||||||
StringPrototypeStartsWith,
|
StringPrototypeStartsWith,
|
||||||
@ -88,11 +90,12 @@ const { internalModuleStat } = internalBinding('fs');
|
|||||||
const packageJsonReader = require('internal/modules/package_json_reader');
|
const packageJsonReader = require('internal/modules/package_json_reader');
|
||||||
const { safeGetenv } = internalBinding('credentials');
|
const { safeGetenv } = internalBinding('credentials');
|
||||||
const {
|
const {
|
||||||
|
cjsConditions,
|
||||||
|
hasEsmSyntax,
|
||||||
|
loadNativeModule,
|
||||||
makeRequireFunction,
|
makeRequireFunction,
|
||||||
normalizeReferrerURL,
|
normalizeReferrerURL,
|
||||||
stripBOM,
|
stripBOM,
|
||||||
cjsConditions,
|
|
||||||
loadNativeModule
|
|
||||||
} = require('internal/modules/cjs/helpers');
|
} = require('internal/modules/cjs/helpers');
|
||||||
const { getOptionValue } = require('internal/options');
|
const { getOptionValue } = require('internal/options');
|
||||||
const preserveSymlinks = getOptionValue('--preserve-symlinks');
|
const preserveSymlinks = getOptionValue('--preserve-symlinks');
|
||||||
@ -107,11 +110,14 @@ const policy = getOptionValue('--experimental-policy') ?
|
|||||||
let hasLoadedAnyUserCJSModule = false;
|
let hasLoadedAnyUserCJSModule = false;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
codes: {
|
||||||
ERR_INVALID_ARG_VALUE,
|
ERR_INVALID_ARG_VALUE,
|
||||||
ERR_INVALID_MODULE_SPECIFIER,
|
ERR_INVALID_MODULE_SPECIFIER,
|
||||||
ERR_REQUIRE_ESM,
|
ERR_REQUIRE_ESM,
|
||||||
ERR_UNKNOWN_BUILTIN_MODULE,
|
ERR_UNKNOWN_BUILTIN_MODULE,
|
||||||
} = require('internal/errors').codes;
|
},
|
||||||
|
setArrowMessage,
|
||||||
|
} = require('internal/errors');
|
||||||
const { validateString } = require('internal/validators');
|
const { validateString } = require('internal/validators');
|
||||||
const pendingDeprecation = getOptionValue('--pending-deprecation');
|
const pendingDeprecation = getOptionValue('--pending-deprecation');
|
||||||
|
|
||||||
@ -970,7 +976,7 @@ Module.prototype.load = function(filename) {
|
|||||||
const extension = findLongestRegisteredExtension(filename);
|
const extension = findLongestRegisteredExtension(filename);
|
||||||
// allow .mjs to be overridden
|
// allow .mjs to be overridden
|
||||||
if (StringPrototypeEndsWith(filename, '.mjs') && !Module._extensions['.mjs'])
|
if (StringPrototypeEndsWith(filename, '.mjs') && !Module._extensions['.mjs'])
|
||||||
throw new ERR_REQUIRE_ESM(filename);
|
throw new ERR_REQUIRE_ESM(filename, true);
|
||||||
|
|
||||||
Module._extensions[extension](this, filename);
|
Module._extensions[extension](this, filename);
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
@ -1102,16 +1108,6 @@ Module.prototype._compile = function(content, filename) {
|
|||||||
|
|
||||||
// Native extension for .js
|
// Native extension for .js
|
||||||
Module._extensions['.js'] = function(module, filename) {
|
Module._extensions['.js'] = function(module, filename) {
|
||||||
if (StringPrototypeEndsWith(filename, '.js')) {
|
|
||||||
const pkg = readPackageScope(filename);
|
|
||||||
// Function require shouldn't be used in ES modules.
|
|
||||||
if (pkg?.data?.type === 'module') {
|
|
||||||
const parent = moduleParentCache.get(module);
|
|
||||||
const parentPath = parent?.filename;
|
|
||||||
const packageJsonPath = path.resolve(pkg.path, 'package.json');
|
|
||||||
throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If already analyzed the source, then it will be cached.
|
// If already analyzed the source, then it will be cached.
|
||||||
const cached = cjsParseCache.get(module);
|
const cached = cjsParseCache.get(module);
|
||||||
let content;
|
let content;
|
||||||
@ -1121,6 +1117,39 @@ Module._extensions['.js'] = function(module, filename) {
|
|||||||
} else {
|
} else {
|
||||||
content = fs.readFileSync(filename, 'utf8');
|
content = fs.readFileSync(filename, 'utf8');
|
||||||
}
|
}
|
||||||
|
if (StringPrototypeEndsWith(filename, '.js')) {
|
||||||
|
const pkg = readPackageScope(filename);
|
||||||
|
// Function require shouldn't be used in ES modules.
|
||||||
|
if (pkg?.data?.type === 'module') {
|
||||||
|
const parent = moduleParentCache.get(module);
|
||||||
|
const parentPath = parent?.filename;
|
||||||
|
const packageJsonPath = path.resolve(pkg.path, 'package.json');
|
||||||
|
const usesEsm = hasEsmSyntax(content);
|
||||||
|
const err = new ERR_REQUIRE_ESM(filename, usesEsm, parentPath,
|
||||||
|
packageJsonPath);
|
||||||
|
// Attempt to reconstruct the parent require frame.
|
||||||
|
if (Module._cache[parentPath]) {
|
||||||
|
let parentSource;
|
||||||
|
try {
|
||||||
|
parentSource = fs.readFileSync(parentPath, 'utf8');
|
||||||
|
} catch {}
|
||||||
|
if (parentSource) {
|
||||||
|
const errLine = StringPrototypeSplit(
|
||||||
|
StringPrototypeSlice(err.stack, StringPrototypeIndexOf(
|
||||||
|
err.stack, ' at ')), '\n', 1)[0];
|
||||||
|
const { 1: line, 2: col } =
|
||||||
|
RegExpPrototypeExec(/(\d+):(\d+)\)/, errLine) || [];
|
||||||
|
if (line && col) {
|
||||||
|
const srcLine = StringPrototypeSplit(parentSource, '\n')[line - 1];
|
||||||
|
const frame = `${parentPath}:${line}\n${srcLine}\n${
|
||||||
|
StringPrototypeRepeat(' ', col - 1)}^\n`;
|
||||||
|
setArrowMessage(err, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
module._compile(content, filename);
|
module._compile(content, filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,6 +215,12 @@ void AppendExceptionLine(Environment* env,
|
|||||||
Local<Object> err_obj;
|
Local<Object> err_obj;
|
||||||
if (!er.IsEmpty() && er->IsObject()) {
|
if (!er.IsEmpty() && er->IsObject()) {
|
||||||
err_obj = er.As<Object>();
|
err_obj = er.As<Object>();
|
||||||
|
// If arrow_message is already set, skip.
|
||||||
|
auto maybe_value = err_obj->GetPrivate(env->context(),
|
||||||
|
env->arrow_message_private_symbol());
|
||||||
|
Local<Value> lvalue;
|
||||||
|
if (!maybe_value.ToLocal(&lvalue) || lvalue->IsString())
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool added_exception_line = false;
|
bool added_exception_line = false;
|
||||||
|
@ -6,17 +6,45 @@ const { spawn } = require('child_process');
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const requiring = path.resolve(fixtures.path('/es-modules/cjs-esm.js'));
|
const requiringCjsAsEsm = path.resolve(fixtures.path('/es-modules/cjs-esm.js'));
|
||||||
const required = path.resolve(
|
const requiringEsm = path.resolve(fixtures.path('/es-modules/cjs-esm-esm.js'));
|
||||||
fixtures.path('/es-modules/package-type-module/cjs.js')
|
|
||||||
);
|
|
||||||
const pjson = path.resolve(
|
const pjson = path.resolve(
|
||||||
fixtures.path('/es-modules/package-type-module/package.json')
|
fixtures.path('/es-modules/package-type-module/package.json')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
const required = path.resolve(
|
||||||
|
fixtures.path('/es-modules/package-type-module/cjs.js')
|
||||||
|
);
|
||||||
const basename = 'cjs.js';
|
const basename = 'cjs.js';
|
||||||
|
const child = spawn(process.execPath, [requiringCjsAsEsm]);
|
||||||
|
let stderr = '';
|
||||||
|
child.stderr.setEncoding('utf8');
|
||||||
|
child.stderr.on('data', (data) => {
|
||||||
|
stderr += data;
|
||||||
|
});
|
||||||
|
child.on('close', common.mustCall((code, signal) => {
|
||||||
|
assert.strictEqual(code, 1);
|
||||||
|
assert.strictEqual(signal, null);
|
||||||
|
|
||||||
const child = spawn(process.execPath, [requiring]);
|
assert.ok(stderr.replaceAll('\r', '').includes(
|
||||||
|
`Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${
|
||||||
|
requiringCjsAsEsm} not supported.\n`));
|
||||||
|
assert.ok(stderr.replaceAll('\r', '').includes(
|
||||||
|
`Instead rename ${basename} to end in .cjs, change the requiring ` +
|
||||||
|
'code to use dynamic import() which is available in all CommonJS ' +
|
||||||
|
`modules, or change "type": "module" to "type": "commonjs" in ${pjson} to ` +
|
||||||
|
'treat all .js files as CommonJS (using .mjs for all ES modules ' +
|
||||||
|
'instead).\n'));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const required = path.resolve(
|
||||||
|
fixtures.path('/es-modules/package-type-module/esm.js')
|
||||||
|
);
|
||||||
|
const basename = 'esm.js';
|
||||||
|
const child = spawn(process.execPath, [requiringEsm]);
|
||||||
let stderr = '';
|
let stderr = '';
|
||||||
child.stderr.setEncoding('utf8');
|
child.stderr.setEncoding('utf8');
|
||||||
child.stderr.on('data', (data) => {
|
child.stderr.on('data', (data) => {
|
||||||
@ -27,15 +55,10 @@ child.on('close', common.mustCall((code, signal) => {
|
|||||||
assert.strictEqual(signal, null);
|
assert.strictEqual(signal, null);
|
||||||
|
|
||||||
assert.ok(stderr.replace(/\r/g, '').includes(
|
assert.ok(stderr.replace(/\r/g, '').includes(
|
||||||
`Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ${required}` +
|
`Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${
|
||||||
'\nrequire() of ES modules is not supported.\nrequire() of ' +
|
requiringEsm} not supported.\n`));
|
||||||
`${required} from ${requiring} ` +
|
assert.ok(stderr.replace(/\r/g, '').includes(
|
||||||
'is an ES module file as it is a .js file whose nearest parent ' +
|
`Instead change the require of ${basename} in ${requiringEsm} to` +
|
||||||
'package.json contains "type": "module" which defines all .js ' +
|
' a dynamic import() which is available in all CommonJS modules.\n'));
|
||||||
'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`));
|
|
||||||
assert.ok(stderr.includes(
|
|
||||||
'Error [ERR_REQUIRE_ESM]: Must use import to load ES Module'));
|
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
@ -29,8 +29,8 @@ try {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
assert.strictEqual(e.name, 'Error');
|
assert.strictEqual(e.name, 'Error');
|
||||||
assert.strictEqual(e.code, 'ERR_REQUIRE_ESM');
|
assert.strictEqual(e.code, 'ERR_REQUIRE_ESM');
|
||||||
assert(e.toString().match(/Must use import to load ES Module/g));
|
assert(e.toString().match(/require\(\) of ES Module/g));
|
||||||
assert(e.message.match(/Must use import to load ES Module/g));
|
assert(e.message.match(/require\(\) of ES Module/g));
|
||||||
}
|
}
|
||||||
|
|
||||||
function expect(opt = '', inputFile, want, wantsError = false) {
|
function expect(opt = '', inputFile, want, wantsError = false) {
|
||||||
|
1
test/fixtures/es-modules/cjs-esm-esm.js
vendored
Normal file
1
test/fixtures/es-modules/cjs-esm-esm.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
require('./package-type-module/esm.js');
|
1
test/fixtures/es-modules/package-type-module/esm.js
vendored
Normal file
1
test/fixtures/es-modules/package-type-module/esm.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export var p = 5;
|
@ -5,7 +5,7 @@ const assert = require('assert');
|
|||||||
assert.throws(
|
assert.throws(
|
||||||
() => require('../fixtures/es-modules/test-esm-ok.mjs'),
|
() => require('../fixtures/es-modules/test-esm-ok.mjs'),
|
||||||
{
|
{
|
||||||
message: /Must use import to load ES Module/,
|
message: /dynamic import\(\) which is available in all CommonJS modules/,
|
||||||
code: 'ERR_REQUIRE_ESM'
|
code: 'ERR_REQUIRE_ESM'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user