summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-07-17 16:19:00 -0400
committerGitHub <noreply@github.com>2023-07-17 16:19:00 -0400
commit4ebe3bdb06a4d539cc8991e1241aa3150100f866 (patch)
tree604b07d51d349adfa780c7a67d9fb15e16ba5c97
parent7a9f7f34195d74fe60eb48381bc2a32db741ceb7 (diff)
fix(node): improve error message requiring non-npm es module (#19856)
Closes #19842 Closes #16913
-rw-r--r--cli/tests/integration/npm_tests.rs8
-rw-r--r--cli/tests/testdata/node/require_esm_error/esm.js1
-rw-r--r--cli/tests/testdata/node/require_esm_error/main.out3
-rw-r--r--cli/tests/testdata/node/require_esm_error/main.ts5
-rw-r--r--cli/tests/testdata/npm/cjs_require_esm_error/main.out4
-rw-r--r--cli/tests/testdata/npm/cjs_require_esm_mjs_error/main.out4
-rw-r--r--ext/node/polyfills/01_require.js57
7 files changed, 53 insertions, 29 deletions
diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs
index 3ecc271e4..2f998e3a2 100644
--- a/cli/tests/integration/npm_tests.rs
+++ b/cli/tests/integration/npm_tests.rs
@@ -104,6 +104,14 @@ itest!(cjs_require_esm_mjs_error {
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 {
args: "run -A --quiet npm/translate_cjs_to_esm/main.js",
output: "npm/translate_cjs_to_esm/main.out",
diff --git a/cli/tests/testdata/node/require_esm_error/esm.js b/cli/tests/testdata/node/require_esm_error/esm.js
new file mode 100644
index 000000000..0613f1911
--- /dev/null
+++ b/cli/tests/testdata/node/require_esm_error/esm.js
@@ -0,0 +1 @@
+export class Test {}
diff --git a/cli/tests/testdata/node/require_esm_error/main.out b/cli/tests/testdata/node/require_esm_error/main.out
new file mode 100644
index 000000000..c7b355411
--- /dev/null
+++ b/cli/tests/testdata/node/require_esm_error/main.out
@@ -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
diff --git a/cli/tests/testdata/node/require_esm_error/main.ts b/cli/tests/testdata/node/require_esm_error/main.ts
new file mode 100644
index 000000000..612e91714
--- /dev/null
+++ b/cli/tests/testdata/node/require_esm_error/main.ts
@@ -0,0 +1,5 @@
+import { createRequire } from "node:module";
+
+const require = createRequire(import.meta.url);
+
+require("./esm.js");
diff --git a/cli/tests/testdata/npm/cjs_require_esm_error/main.out b/cli/tests/testdata/npm/cjs_require_esm_error/main.out
index dcb3d15b7..5c735b3a6 100644
--- a/cli/tests/testdata/npm/cjs_require_esm_error/main.out
+++ b/cli/tests/testdata/npm/cjs_require_esm_error/main.out
@@ -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.
- at Object.Module._extensions..js (node:module:[WILDCARD])
+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.
[WILDCARD]
- at Module.load (node:module:[WILDCARD])
diff --git a/cli/tests/testdata/npm/cjs_require_esm_mjs_error/main.out b/cli/tests/testdata/npm/cjs_require_esm_mjs_error/main.out
index df37e997a..e6a8abe27 100644
--- a/cli/tests/testdata/npm/cjs_require_esm_mjs_error/main.out
+++ b/cli/tests/testdata/npm/cjs_require_esm_mjs_error/main.out
@@ -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.
- at Module.load (node:module:[WILDCARD])
+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.
[WILDCARD]
- at Function.Module._load (node:module:[WILDCARD])
diff --git a/ext/node/polyfills/01_require.js b/ext/node/polyfills/01_require.js
index 0fe75107d..3ca4ab428 100644
--- a/ext/node/polyfills/01_require.js
+++ b/ext/node/polyfills/01_require.js
@@ -878,9 +878,9 @@ Module.prototype.load = function (filename) {
if (
StringPrototypeEndsWith(filename, ".mjs") && !Module._extensions[".mjs"]
) {
- // TODO: use proper error class
- throw new Error(
- requireEsmErrorText(filename, moduleParentCache.get(this)?.filename),
+ throw createRequireEsmError(
+ filename,
+ moduleParentCache.get(this)?.filename,
);
}
@@ -923,20 +923,22 @@ Module.wrap = function (script) {
return `${Module.wrapper[0]}${script}${Module.wrapper[1]}`;
};
+function isEsmSyntaxError(error) {
+ return error instanceof SyntaxError && (
+ StringPrototypeIncludes(
+ error.message,
+ "Cannot use import statement outside a module",
+ ) ||
+ StringPrototypeIncludes(error.message, "Unexpected token 'export'")
+ );
+}
+
function enrichCJSError(error) {
- if (error instanceof SyntaxError) {
- if (
- StringPrototypeIncludes(
- error.message,
- "Cannot use import statement outside a module",
- ) ||
- StringPrototypeIncludes(error.message, "Unexpected token 'export'")
- ) {
- console.error(
- 'To load an ES module, set "type": "module" in the package.json or use ' +
- "the .mjs extension.",
- );
- }
+ if (isEsmSyntaxError(error)) {
+ console.error(
+ 'To load an ES module, set "type": "module" in the package.json or use ' +
+ "the .mjs extension.",
+ );
}
}
@@ -951,7 +953,14 @@ function wrapSafe(
if (nodeGlobalThis.process.mainModule === cjsModuleInstance) {
enrichCJSError(err.thrown);
}
- throw err.thrown;
+ if (isEsmSyntaxError(err.thrown)) {
+ throw createRequireEsmError(
+ filename,
+ moduleParentCache.get(cjsModuleInstance)?.filename,
+ );
+ } else {
+ throw err.thrown;
+ }
}
return f;
}
@@ -963,7 +972,6 @@ Module.prototype._compile = function (content, filename) {
const require = makeRequireFunction(this);
const exports = this.exports;
const thisValue = exports;
- const module = this;
if (requireDepth === 0) {
statCache = new SafeMap();
}
@@ -994,8 +1002,9 @@ Module._extensions[".js"] = function (module, filename) {
if (StringPrototypeEndsWith(filename, ".js")) {
const pkg = ops.op_require_read_closest_package_json(filename);
if (pkg && pkg.exists && pkg.typ === "module") {
- throw new Error(
- requireEsmErrorText(filename, moduleParentCache.get(module)?.filename),
+ throw createRequireEsmError(
+ filename,
+ moduleParentCache.get(module)?.filename,
);
}
}
@@ -1003,8 +1012,8 @@ Module._extensions[".js"] = function (module, filename) {
module._compile(content, filename);
};
-function requireEsmErrorText(filename, parent) {
- let message = `[ERR_REQUIRE_ESM]: require() of ES Module ${filename}`;
+function createRequireEsmError(filename, parent) {
+ let message = `require() of ES Module ${filename}`;
if (parent) {
message += ` from ${parent}`;
@@ -1012,7 +1021,9 @@ function requireEsmErrorText(filename, parent) {
message +=
` 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) {