diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-07-17 16:19:00 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-17 16:19:00 -0400 |
commit | 4ebe3bdb06a4d539cc8991e1241aa3150100f866 (patch) | |
tree | 604b07d51d349adfa780c7a67d9fb15e16ba5c97 | |
parent | 7a9f7f34195d74fe60eb48381bc2a32db741ceb7 (diff) |
fix(node): improve error message requiring non-npm es module (#19856)
Closes #19842
Closes #16913
-rw-r--r-- | cli/tests/integration/npm_tests.rs | 8 | ||||
-rw-r--r-- | cli/tests/testdata/node/require_esm_error/esm.js | 1 | ||||
-rw-r--r-- | cli/tests/testdata/node/require_esm_error/main.out | 3 | ||||
-rw-r--r-- | cli/tests/testdata/node/require_esm_error/main.ts | 5 | ||||
-rw-r--r-- | cli/tests/testdata/npm/cjs_require_esm_error/main.out | 4 | ||||
-rw-r--r-- | cli/tests/testdata/npm/cjs_require_esm_mjs_error/main.out | 4 | ||||
-rw-r--r-- | ext/node/polyfills/01_require.js | 57 |
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) { |