diff --git a/eslint/babel-eslint-parser/src/worker/configuration.cjs b/eslint/babel-eslint-parser/src/worker/configuration.cjs index 24877f5c59ef..5864863b37ac 100644 --- a/eslint/babel-eslint-parser/src/worker/configuration.cjs +++ b/eslint/babel-eslint-parser/src/worker/configuration.cjs @@ -58,15 +58,37 @@ function validateResolvedConfig(config, options) { } } +function getDefaultParserOptions(options) { + return { + plugins: [], + ...options, + babelrc: false, + configFile: false, + browserslistConfigFile: false, + ignore: null, + only: null, + }; +} + module.exports = function normalizeBabelParseConfig(options) { const parseOptions = normalizeParserOptions(options); if (process.env.BABEL_8_BREAKING) { return babel .loadPartialConfigAsync(parseOptions) - .then(config => validateResolvedConfig(config, options) || parseOptions); + .then(config => validateConfigWithFallback(config)); } else { const config = babel.loadPartialConfigSync(parseOptions); - return validateResolvedConfig(config, options) || parseOptions; + return validateConfigWithFallback(config); + } + + function validateConfigWithFallback(inputConfig) { + const result = validateResolvedConfig(inputConfig, options); + if (result) { + return result; + } else { + // Fallback when `loadPartialConfig` returns `null` (e.g.: when the file is ignored) + return getDefaultParserOptions(parseOptions); + } } }; diff --git a/eslint/babel-eslint-parser/test/index.js b/eslint/babel-eslint-parser/test/index.js index 3522bdd218b8..64a3ae09d07d 100644 --- a/eslint/babel-eslint-parser/test/index.js +++ b/eslint/babel-eslint-parser/test/index.js @@ -5,9 +5,11 @@ import { fileURLToPath } from "url"; import { createRequire } from "module"; import { parseForESLint } from "../lib/index.cjs"; +const dirname = path.dirname(fileURLToPath(import.meta.url)); + const BABEL_OPTIONS = { configFile: path.resolve( - path.dirname(fileURLToPath(import.meta.url)), + dirname, "../../babel-eslint-shared-fixtures/config/babel.config.js", ), }; @@ -75,7 +77,7 @@ describe("Babel and Espree", () => { expect(babelAST).toEqual(espreeAST); } - beforeAll(async () => { + beforeAll(() => { const require = createRequire(import.meta.url); // Use the version of Espree that is a dependency of @@ -88,7 +90,7 @@ describe("Babel and Espree", () => { }); describe("compatibility", () => { - it("should allow ast.analyze to be called without options", function () { + it("should allow ast.analyze to be called without options", () => { const ast = parseForESLint("`test`", { eslintScopeManager: true, eslintVisitorKeys: true, @@ -98,6 +100,16 @@ describe("Babel and Espree", () => { escope.analyze(ast); }).not.toThrow(new TypeError("Should allow no options argument.")); }); + + it("should not crash when `loadPartialConfigSync` returns `null`", () => { + const thunk = () => + parseForESLint("`test`", { + eslintScopeManager: true, + eslintVisitorKeys: true, + babelOptions: { filename: "test.js", ignore: [/./] }, + }); + expect(thunk).not.toThrow(); + }); }); describe("templates", () => {