mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
fix(node): improve error message requiring non-npm es module (#19856)
Closes #19842 Closes #16913
This commit is contained in:
parent
7a9f7f3419
commit
4ebe3bdb06
7 changed files with 53 additions and 29 deletions
|
@ -104,6 +104,14 @@ itest!(cjs_require_esm_mjs_error {
|
||||||
exit_code: 1,
|
exit_code: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(require_esm_error {
|
||||||
|
args: "run --allow-read --quiet node/require_esm_error/main.ts",
|
||||||
|
output: "node/require_esm_error/main.out",
|
||||||
|
envs: env_vars_for_npm_tests(),
|
||||||
|
http_server: true,
|
||||||
|
exit_code: 1,
|
||||||
|
});
|
||||||
|
|
||||||
itest!(translate_cjs_to_esm {
|
itest!(translate_cjs_to_esm {
|
||||||
args: "run -A --quiet npm/translate_cjs_to_esm/main.js",
|
args: "run -A --quiet npm/translate_cjs_to_esm/main.js",
|
||||||
output: "npm/translate_cjs_to_esm/main.out",
|
output: "npm/translate_cjs_to_esm/main.out",
|
||||||
|
|
1
cli/tests/testdata/node/require_esm_error/esm.js
vendored
Normal file
1
cli/tests/testdata/node/require_esm_error/esm.js
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export class Test {}
|
3
cli/tests/testdata/node/require_esm_error/main.out
vendored
Normal file
3
cli/tests/testdata/node/require_esm_error/main.out
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
error: Uncaught Error: require() of ES Module [WILDCARD]esm.js from [WILDCARD]main.ts not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.
|
||||||
|
at [WILDCARD]
|
||||||
|
at file:///[WILDCARD]/require_esm_error/main.ts:5:1
|
5
cli/tests/testdata/node/require_esm_error/main.ts
vendored
Normal file
5
cli/tests/testdata/node/require_esm_error/main.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { createRequire } from "node:module";
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
|
require("./esm.js");
|
|
@ -1,4 +1,2 @@
|
||||||
error: Uncaught Error: [ERR_REQUIRE_ESM]: require() of ES Module [WILDCARD]my_esm_module.js from [WILDCARD]index.js not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.
|
error: Uncaught Error: require() of ES Module [WILDCARD]my_esm_module.js from [WILDCARD]index.js not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.
|
||||||
at Object.Module._extensions..js (node:module:[WILDCARD])
|
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
at Module.load (node:module:[WILDCARD])
|
|
||||||
|
|
|
@ -1,4 +1,2 @@
|
||||||
error: Uncaught Error: [ERR_REQUIRE_ESM]: require() of ES Module [WILDCARD]esm_mjs.mjs from [WILDCARD]require_mjs.js not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.
|
error: Uncaught Error: require() of ES Module [WILDCARD]esm_mjs.mjs from [WILDCARD]require_mjs.js not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.
|
||||||
at Module.load (node:module:[WILDCARD])
|
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
at Function.Module._load (node:module:[WILDCARD])
|
|
||||||
|
|
|
@ -878,9 +878,9 @@ Module.prototype.load = function (filename) {
|
||||||
if (
|
if (
|
||||||
StringPrototypeEndsWith(filename, ".mjs") && !Module._extensions[".mjs"]
|
StringPrototypeEndsWith(filename, ".mjs") && !Module._extensions[".mjs"]
|
||||||
) {
|
) {
|
||||||
// TODO: use proper error class
|
throw createRequireEsmError(
|
||||||
throw new Error(
|
filename,
|
||||||
requireEsmErrorText(filename, moduleParentCache.get(this)?.filename),
|
moduleParentCache.get(this)?.filename,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,22 +923,24 @@ Module.wrap = function (script) {
|
||||||
return `${Module.wrapper[0]}${script}${Module.wrapper[1]}`;
|
return `${Module.wrapper[0]}${script}${Module.wrapper[1]}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
function enrichCJSError(error) {
|
function isEsmSyntaxError(error) {
|
||||||
if (error instanceof SyntaxError) {
|
return error instanceof SyntaxError && (
|
||||||
if (
|
|
||||||
StringPrototypeIncludes(
|
StringPrototypeIncludes(
|
||||||
error.message,
|
error.message,
|
||||||
"Cannot use import statement outside a module",
|
"Cannot use import statement outside a module",
|
||||||
) ||
|
) ||
|
||||||
StringPrototypeIncludes(error.message, "Unexpected token 'export'")
|
StringPrototypeIncludes(error.message, "Unexpected token 'export'")
|
||||||
) {
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enrichCJSError(error) {
|
||||||
|
if (isEsmSyntaxError(error)) {
|
||||||
console.error(
|
console.error(
|
||||||
'To load an ES module, set "type": "module" in the package.json or use ' +
|
'To load an ES module, set "type": "module" in the package.json or use ' +
|
||||||
"the .mjs extension.",
|
"the .mjs extension.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function wrapSafe(
|
function wrapSafe(
|
||||||
filename,
|
filename,
|
||||||
|
@ -951,8 +953,15 @@ function wrapSafe(
|
||||||
if (nodeGlobalThis.process.mainModule === cjsModuleInstance) {
|
if (nodeGlobalThis.process.mainModule === cjsModuleInstance) {
|
||||||
enrichCJSError(err.thrown);
|
enrichCJSError(err.thrown);
|
||||||
}
|
}
|
||||||
|
if (isEsmSyntaxError(err.thrown)) {
|
||||||
|
throw createRequireEsmError(
|
||||||
|
filename,
|
||||||
|
moduleParentCache.get(cjsModuleInstance)?.filename,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
throw err.thrown;
|
throw err.thrown;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +972,6 @@ Module.prototype._compile = function (content, filename) {
|
||||||
const require = makeRequireFunction(this);
|
const require = makeRequireFunction(this);
|
||||||
const exports = this.exports;
|
const exports = this.exports;
|
||||||
const thisValue = exports;
|
const thisValue = exports;
|
||||||
const module = this;
|
|
||||||
if (requireDepth === 0) {
|
if (requireDepth === 0) {
|
||||||
statCache = new SafeMap();
|
statCache = new SafeMap();
|
||||||
}
|
}
|
||||||
|
@ -994,8 +1002,9 @@ Module._extensions[".js"] = function (module, filename) {
|
||||||
if (StringPrototypeEndsWith(filename, ".js")) {
|
if (StringPrototypeEndsWith(filename, ".js")) {
|
||||||
const pkg = ops.op_require_read_closest_package_json(filename);
|
const pkg = ops.op_require_read_closest_package_json(filename);
|
||||||
if (pkg && pkg.exists && pkg.typ === "module") {
|
if (pkg && pkg.exists && pkg.typ === "module") {
|
||||||
throw new Error(
|
throw createRequireEsmError(
|
||||||
requireEsmErrorText(filename, moduleParentCache.get(module)?.filename),
|
filename,
|
||||||
|
moduleParentCache.get(module)?.filename,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1003,8 +1012,8 @@ Module._extensions[".js"] = function (module, filename) {
|
||||||
module._compile(content, filename);
|
module._compile(content, filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
function requireEsmErrorText(filename, parent) {
|
function createRequireEsmError(filename, parent) {
|
||||||
let message = `[ERR_REQUIRE_ESM]: require() of ES Module ${filename}`;
|
let message = `require() of ES Module ${filename}`;
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
message += ` from ${parent}`;
|
message += ` from ${parent}`;
|
||||||
|
@ -1012,7 +1021,9 @@ function requireEsmErrorText(filename, parent) {
|
||||||
|
|
||||||
message +=
|
message +=
|
||||||
` not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.`;
|
` not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.`;
|
||||||
return message;
|
const err = new Error(message);
|
||||||
|
err.code = "ERR_REQUIRE_ESM";
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripBOM(content) {
|
function stripBOM(content) {
|
||||||
|
|
Loading…
Reference in a new issue