From e68f2ce1950d2ff313bd97b17c79ca2cbed92634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 26 Mar 2021 20:07:28 +0100 Subject: [PATCH] Correctly handle relative `browserslistConfigFile` paths (#13031) * Correctly handle relative `browserslistConfigFile` * Fix flow --- .../src/config/config-descriptors.js | 19 +++++++++++-- packages/babel-core/src/config/partial.js | 2 +- .../src/config/resolve-targets-browser.js | 11 ++++++-- .../babel-core/src/config/resolve-targets.js | 18 ++++++++++--- packages/babel-core/test/targets.js | 27 +++++++++---------- 5 files changed, 53 insertions(+), 24 deletions(-) diff --git a/packages/babel-core/src/config/config-descriptors.js b/packages/babel-core/src/config/config-descriptors.js index 59f9e462c7fe..2ae3c4344b29 100644 --- a/packages/babel-core/src/config/config-descriptors.js +++ b/packages/babel-core/src/config/config-descriptors.js @@ -19,6 +19,8 @@ import type { PluginItem, } from "./validation/options"; +import { resolveBrowserslistConfigFile } from "./resolve-targets"; + // Represents a config object and functions to lazily load the descriptors // for the plugins and presets so we don't load the plugins/presets unless // the options object actually ends up being applicable. @@ -71,6 +73,19 @@ function* handlerOf(value: T): Handler { return value; } +function optionsWithResolvedBrowserslistConfigFile( + options: ValidatedOptions, + dirname: string, +): ValidatedOptions { + if (typeof options.browserslistConfigFile === "string") { + options.browserslistConfigFile = resolveBrowserslistConfigFile( + options.browserslistConfigFile, + dirname, + ); + } + return options; +} + /** * Create a set of descriptors from a given options object, preserving * descriptor identity based on the identity of the plugin/preset arrays @@ -83,7 +98,7 @@ export function createCachedDescriptors( ): OptionsAndDescriptors { const { plugins, presets, passPerPreset } = options; return { - options, + options: optionsWithResolvedBrowserslistConfigFile(options, dirname), plugins: plugins ? () => createCachedPluginDescriptors(plugins, dirname)(alias) : () => handlerOf([]), @@ -112,7 +127,7 @@ export function createUncachedDescriptors( let presets; return { - options, + options: optionsWithResolvedBrowserslistConfigFile(options, dirname), *plugins() { if (!plugins) { plugins = yield* createPluginDescriptors( diff --git a/packages/babel-core/src/config/partial.js b/packages/babel-core/src/config/partial.js index ae4cf8baa702..11c0c3d9fccb 100644 --- a/packages/babel-core/src/config/partial.js +++ b/packages/babel-core/src/config/partial.js @@ -126,7 +126,7 @@ export default function* loadPrivatePartialConfig( const options: NormalizedOptions = { ...merged, - targets: resolveTargets(merged, absoluteRootDir, absoluteRootDir), + targets: resolveTargets(merged, absoluteRootDir), // Tack the passes onto the object itself so that, if this object is // passed back to Babel a second time, it will be in the right structure diff --git a/packages/babel-core/src/config/resolve-targets-browser.js b/packages/babel-core/src/config/resolve-targets-browser.js index eee0f115b7b5..1b8c43429071 100644 --- a/packages/babel-core/src/config/resolve-targets-browser.js +++ b/packages/babel-core/src/config/resolve-targets-browser.js @@ -3,12 +3,19 @@ import type { ValidatedOptions } from "./validation/options"; import getTargets, { type Targets } from "@babel/helper-compilation-targets"; +export function resolveBrowserslistConfigFile( + // eslint-disable-next-line no-unused-vars + browserslistConfigFile: string, + // eslint-disable-next-line no-unused-vars + configFilePath: string, +): string | void { + return undefined; +} + export function resolveTargets( options: ValidatedOptions, // eslint-disable-next-line no-unused-vars root: string, - // eslint-disable-next-line no-unused-vars - configFilePath: string | void, ): Targets { let { targets } = options; if (typeof targets === "string" || Array.isArray(targets)) { diff --git a/packages/babel-core/src/config/resolve-targets.js b/packages/babel-core/src/config/resolve-targets.js index c612bbfd85b5..72361f27abff 100644 --- a/packages/babel-core/src/config/resolve-targets.js +++ b/packages/babel-core/src/config/resolve-targets.js @@ -11,10 +11,16 @@ import type { ValidatedOptions } from "./validation/options"; import path from "path"; import getTargets, { type Targets } from "@babel/helper-compilation-targets"; +export function resolveBrowserslistConfigFile( + browserslistConfigFile: string, + configFileDir: string, +): string | void { + return path.resolve(configFileDir, browserslistConfigFile); +} + export function resolveTargets( options: ValidatedOptions, root: string, - configFilePath: string = root, ): Targets { let { targets } = options; if (typeof targets === "string" || Array.isArray(targets)) { @@ -25,13 +31,17 @@ export function resolveTargets( targets = { ...targets, esmodules: "intersect" }; } + const { browserslistConfigFile } = options; let configFile; - if (typeof options.browserslistConfigFile === "string") { - configFile = path.resolve(configFilePath, options.browserslistConfigFile); + let ignoreBrowserslistConfig = false; + if (typeof browserslistConfigFile === "string") { + configFile = browserslistConfigFile; + } else { + ignoreBrowserslistConfig = browserslistConfigFile === false; } return getTargets((targets: any), { - ignoreBrowserslistConfig: options.browserslistConfigFile === false, + ignoreBrowserslistConfig, configFile, configPath: root, browserslistEnv: options.browserslistEnv, diff --git a/packages/babel-core/test/targets.js b/packages/babel-core/test/targets.js index 08592127abcd..1fafeff48673 100644 --- a/packages/babel-core/test/targets.js +++ b/packages/babel-core/test/targets.js @@ -100,19 +100,6 @@ describe("browserslist", () => { ).toEqual({ chrome: "80.0.0" }); }); - // TODO: browserslistConfig is currently resolved starting from the root - // rather than from the config file. - // eslint-disable-next-line jest/no-disabled-tests - it.skip("loads nested .browserslistrc files if explicitly specified", () => { - expect( - loadOptions({ - cwd: join(cwd, "fixtures", "targets"), - filename: "./node_modules/dep/test.js", - babelrcRoots: ["./node_modules/dep/"], - }).targets, - ).toEqual({ edge: "14.0.0" }); - }); - describe("browserslistConfigFile", () => { it("can disable config loading", () => { expect( @@ -132,16 +119,26 @@ describe("browserslist", () => { ).toEqual({ firefox: "74.0.0" }); }); - it("is relative to the project root", () => { + it("is relative to the cwd even if specifying 'root'", () => { expect( loadOptions({ cwd: join(cwd, "fixtures", "targets"), root: "..", filename: "./nested/test.js", - browserslistConfigFile: "./targets/.browserslistrc-firefox", + browserslistConfigFile: "./.browserslistrc-firefox", }).targets, ).toEqual({ firefox: "74.0.0" }); }); + + it("is relative to the config files that defines it", () => { + expect( + loadOptions({ + cwd: join(cwd, "fixtures", "targets"), + filename: "./node_modules/dep/test.js", + babelrcRoots: ["./node_modules/dep/"], + }).targets, + ).toEqual({ edge: "14.0.0" }); + }); }); describe("browserslistEnv", () => {