Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

module: refine enrichCJSError #39507

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/internal/modules/cjs/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ function normalizeReferrerURL(referrer) {

// For error messages only - used to check if ESM syntax is in use.
function hasEsmSyntax(code) {
debug('Checking for ESM syntax');
const parser = require('internal/deps/acorn/acorn/dist/acorn').Parser;
let root;
try {
Expand All @@ -196,6 +197,7 @@ function hasEsmSyntax(code) {
}

return ArrayPrototypeSome(root.body, (stmt) =>
stmt.type === 'ExportDefaultDeclaration' ||
stmt.type === 'ExportNamedDeclaration' ||
stmt.type === 'ImportDeclaration' ||
stmt.type === 'ExportAllDeclaration');
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ function wrapSafe(filename, content, cjsModuleInstance) {
});
} catch (err) {
if (process.mainModule === cjsModuleInstance)
enrichCJSError(err);
enrichCJSError(err, content);
throw err;
}
}
Expand Down
27 changes: 11 additions & 16 deletions lib/internal/modules/esm/translators.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ const {
ObjectKeys,
PromisePrototypeCatch,
PromiseReject,
RegExpPrototypeTest,
SafeArrayIterator,
SafeMap,
SafeSet,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith,
SyntaxErrorPrototype,
globalThis: { WebAssembly },
Expand All @@ -31,8 +29,9 @@ function lazyTypes() {
const { readFileSync } = require('fs');
const { extname, isAbsolute } = require('path');
const {
hasEsmSyntax,
loadNativeModule,
stripBOM,
loadNativeModule
} = require('internal/modules/cjs/helpers');
const {
Module: CJSModule,
Expand Down Expand Up @@ -152,18 +151,14 @@ translators.set('module', async function moduleStrategy(url) {
return module;
});

function enrichCJSError(err) {
if (err == null || ObjectGetPrototypeOf(err) !== SyntaxErrorPrototype) {
return;
}
const stack = StringPrototypeSplit(err.stack, '\n');
/*
* The regular expression below targets the most common import statement
* usage. However, some cases are not matching, cases like import statement
* after a comment block and/or after a variable definition.
*/
if (StringPrototypeStartsWith(err.message, 'Unexpected token \'export\'') ||
RegExpPrototypeTest(/^\s*import(?=[ {'"*])\s*(?![ (])/, stack[1])) {
/**
* @param {Error | any} err
* @param {string} [content] Content of the file, if known.
* @param {string} [filename] Useful only if `content` is unknown.
*/
function enrichCJSError(err, content, filename) {
if (err != null && ObjectGetPrototypeOf(err) === SyntaxErrorPrototype &&
hasEsmSyntax(content || readFileSync(filename, 'utf-8'))) {
// Emit the warning synchronously because we are in the middle of handling
// a SyntaxError that will throw and likely terminate the process before an
// asynchronous warning would be emitted.
Expand Down Expand Up @@ -200,7 +195,7 @@ translators.set('commonjs', async function commonjsStrategy(url, isMain) {
try {
exports = CJSModule._load(filename, undefined, isMain);
} catch (err) {
enrichCJSError(err);
enrichCJSError(err, undefined, filename);
throw err;
}
}
Expand Down