diff --git a/lib/linter/linter.js b/lib/linter/linter.js index 95a83366a37..29d78da3969 100644 --- a/lib/linter/linter.js +++ b/lib/linter/linter.js @@ -1510,7 +1510,31 @@ class Linter { options.filterCodeBlock || (blockFilename => blockFilename.endsWith(".js")); const originalExtname = path.extname(filename); - const messageLists = preprocess(text, filenameToExpose).map((block, i) => { + + let blocks; + + try { + blocks = preprocess(text, filenameToExpose); + } catch (ex) { + + // If the message includes a leading line number, strip it: + const message = `Preprocessing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`; + + debug("%s\n%s", message, ex.stack); + + return [ + { + ruleId: null, + fatal: true, + severity: 2, + message, + line: ex.lineNumber, + column: ex.column + } + ]; + } + + const messageLists = blocks.map((block, i) => { debug("A code block was found: %o", block.filename || "(unnamed)"); // Keep the legacy behavior. @@ -1788,13 +1812,36 @@ class Linter { const physicalFilename = options.physicalFilename || filenameToExpose; const text = ensureText(textOrSourceCode); const preprocess = options.preprocess || (rawText => [rawText]); - const postprocess = options.postprocess || (messagesList => messagesList.flat()); const filterCodeBlock = options.filterCodeBlock || (blockFilename => blockFilename.endsWith(".js")); const originalExtname = path.extname(filename); - const messageLists = preprocess(text, filenameToExpose).map((block, i) => { + + let blocks; + + try { + blocks = preprocess(text, filenameToExpose); + } catch (ex) { + + // If the message includes a leading line number, strip it: + const message = `Preprocessing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`; + + debug("%s\n%s", message, ex.stack); + + return [ + { + ruleId: null, + fatal: true, + severity: 2, + message, + line: ex.lineNumber, + column: ex.column + } + ]; + } + + const messageLists = blocks.map((block, i) => { debug("A code block was found: %o", block.filename || "(unnamed)"); // Keep the legacy behavior. diff --git a/tests/lib/linter/linter.js b/tests/lib/linter/linter.js index 8239abd2086..73acdf64578 100644 --- a/tests/lib/linter/linter.js +++ b/tests/lib/linter/linter.js @@ -6660,6 +6660,31 @@ var a = "test2"; assert.strictEqual(preprocess.calledOnce, true); assert.deepStrictEqual(preprocess.args[0], [code, filename]); }); + + it("should catch preprocess error.", () => { + const code = "foo"; + const preprocess = sinon.spy(() => { + throw Object.assign(new SyntaxError("Invalid syntax"), { + lineNumber: 1, + column: 1 + }); + }); + + const messages = linter.verify(code, {}, { filename, preprocess }); + + assert.strictEqual(preprocess.calledOnce, true); + assert.deepStrictEqual(preprocess.args[0], [code, filename]); + assert.deepStrictEqual(messages, [ + { + ruleId: null, + fatal: true, + severity: 2, + message: "Preprocessing error: Invalid syntax", + line: 1, + column: 1 + } + ]); + }); }); describe("postprocessors", () => { @@ -15158,6 +15183,37 @@ var a = "test2"; assert.strictEqual(preprocess.calledOnce, true); assert.deepStrictEqual(preprocess.args[0], [code, filename]); }); + + it("should catch preprocess error.", () => { + const code = "foo"; + const preprocess = sinon.spy(() => { + throw Object.assign(new SyntaxError("Invalid syntax"), { + lineNumber: 1, + column: 1 + }); + }); + + const configs = createFlatConfigArray([ + extraConfig + ]); + + configs.normalizeSync(); + + const messages = linter.verify(code, configs, { filename, preprocess }); + + assert.strictEqual(preprocess.calledOnce, true); + assert.deepStrictEqual(preprocess.args[0], [code, filename]); + assert.deepStrictEqual(messages, [ + { + ruleId: null, + fatal: true, + severity: 2, + message: "Preprocessing error: Invalid syntax", + line: 1, + column: 1 + } + ]); + }); }); describe("postprocessors", () => {