Merge pull request #7358 from loganfsmyth/babelrc-resolution-changes

Allow more flexible file-based configuration while preventing .babelrcs from breaking things
This commit is contained in:
Logan Smyth 2018-04-22 13:28:05 -07:00 committed by GitHub
commit d6dcbdad48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 505 additions and 129 deletions

View File

@ -238,10 +238,6 @@ if (errors.length) {
// //
const opts = commander.opts(); const opts = commander.opts();
//the configFile CLI option maps to the extends option in the node API
if (opts.configFile) {
opts.extends = opts.configFile;
}
// Delete options that are specific to @babel/cli and shouldn't be passed to @babel/core. // Delete options that are specific to @babel/cli and shouldn't be passed to @babel/core.
delete opts.version; delete opts.version;
@ -253,7 +249,6 @@ delete opts.outDir;
delete opts.copyFiles; delete opts.copyFiles;
delete opts.includeDotfiles; delete opts.includeDotfiles;
delete opts.verbose; delete opts.verbose;
delete opts.configFile;
delete opts.deleteDirOnStart; delete opts.deleteDirOnStart;
delete opts.keepFileExtension; delete opts.keepFileExtension;
delete opts.relative; delete opts.relative;

View File

@ -216,7 +216,10 @@ Following is a table of the options you can use:
| `ast` | `false` | Include the AST in the returned object | | `ast` | `false` | Include the AST in the returned object |
| `auxiliaryCommentAfter` | `null` | Attach a comment after all non-user injected code | | `auxiliaryCommentAfter` | `null` | Attach a comment after all non-user injected code |
| `auxiliaryCommentBefore` | `null` | Attach a comment before all non-user injected code | | `auxiliaryCommentBefore` | `null` | Attach a comment before all non-user injected code |
| `root` | `"."` | Specify the "root" folder that defines the location to search for "babel.config.js", and the default folder to allow `.babelrc` files inside of.|
| `configFile` | `undefined` | The config file to load Babel's config from. Defaults to searching for "babel.config.js" inside the "root" folder. `false` will disable searching for config files.|
| `babelrc` | `true` | Specify whether or not to use .babelrc and .babelignore files. Not available when using the CLI, [use `--no-babelrc` instead](https://babeljs.io/docs/usage/cli/#babel-ignoring-babelrc) | | `babelrc` | `true` | Specify whether or not to use .babelrc and .babelignore files. Not available when using the CLI, [use `--no-babelrc` instead](https://babeljs.io/docs/usage/cli/#babel-ignoring-babelrc) |
| `babelrcRoots` | `(root)` | Specify which packages should be search for .babelrc files when they are being compiled. `true` to _always_ search, or a path string or an array of paths to packages to search inside of. Defaults to only searching the "root" package. |
| `envName` | env vars | Defaults to environment variable `BABEL_ENV` if set, or else `NODE_ENV` if set, or else it defaults to `"development"` | | `envName` | env vars | Defaults to environment variable `BABEL_ENV` if set, or else `NODE_ENV` if set, or else it defaults to `"development"` |
| `code` | `true` | Enable code generation | | `code` | `true` | Enable code generation |
| `comments` | `true` | Output comments in generated output | | `comments` | `true` | Output comments in generated output |

View File

@ -8,15 +8,19 @@ import {
type ValidatedOptions, type ValidatedOptions,
type IgnoreList, type IgnoreList,
type ConfigApplicableTest, type ConfigApplicableTest,
type BabelrcSearch,
} from "./validation/options"; } from "./validation/options";
const debug = buildDebug("babel:config:config-chain"); const debug = buildDebug("babel:config:config-chain");
import { import {
findPackageData,
findRelativeConfig, findRelativeConfig,
findRootConfig,
loadConfig, loadConfig,
type ConfigFile, type ConfigFile,
type IgnoreFile, type IgnoreFile,
type FilePackageData,
} from "./files"; } from "./files";
import { makeWeakCache, makeStrongCache } from "./caching"; import { makeWeakCache, makeStrongCache } from "./caching";
@ -106,6 +110,7 @@ const loadPresetOverridesEnvDescriptors = makeWeakCache(
export type RootConfigChain = ConfigChain & { export type RootConfigChain = ConfigChain & {
babelrc: ConfigFile | void, babelrc: ConfigFile | void,
config: ConfigFile | void,
ignore: IgnoreFile | void, ignore: IgnoreFile | void,
}; };
@ -125,24 +130,57 @@ export function buildRootChain(
); );
if (!programmaticChain) return null; if (!programmaticChain) return null;
let ignore, babelrc; const {
root: rootDir = ".",
babelrc = true,
babelrcRoots,
configFile: configFileName = true,
} = opts;
const absoluteRoot = path.resolve(context.cwd, rootDir);
let configFile;
if (typeof configFileName === "string") {
configFile = loadConfig(configFileName, context.cwd, context.envName);
} else if (configFileName === true) {
configFile = findRootConfig(absoluteRoot, context.envName);
}
const configFileChain = emptyChain();
if (configFile) {
const result = loadFileChain(configFile, context);
if (!result) return null;
mergeChain(configFileChain, result);
}
const pkgData =
typeof context.filename === "string"
? findPackageData(context.filename)
: null;
let ignoreFile, babelrcFile;
const fileChain = emptyChain(); const fileChain = emptyChain();
// resolve all .babelrc files // resolve all .babelrc files
if (opts.babelrc !== false && context.filename !== null) { if (
const filename = context.filename; babelrc &&
pkgData &&
({ ignore, config: babelrc } = findRelativeConfig( babelrcLoadEnabled(context, pkgData, babelrcRoots, absoluteRoot)
filename, ) {
({ ignore: ignoreFile, config: babelrcFile } = findRelativeConfig(
pkgData,
context.envName, context.envName,
)); ));
if (ignore && shouldIgnore(context, ignore.ignore, null, ignore.dirname)) { if (
ignoreFile &&
shouldIgnore(context, ignoreFile.ignore, null, ignoreFile.dirname)
) {
return null; return null;
} }
if (babelrc) { if (babelrcFile) {
const result = loadFileChain(babelrc, context); const result = loadFileChain(babelrcFile, context);
if (!result) return null; if (!result) return null;
mergeChain(fileChain, result); mergeChain(fileChain, result);
@ -152,7 +190,7 @@ export function buildRootChain(
// Insert file chain in front so programmatic options have priority // Insert file chain in front so programmatic options have priority
// over configuration file chain items. // over configuration file chain items.
const chain = mergeChain( const chain = mergeChain(
mergeChain(emptyChain(), fileChain), mergeChain(mergeChain(emptyChain(), configFileChain), fileChain),
programmaticChain, programmaticChain,
); );
@ -160,11 +198,39 @@ export function buildRootChain(
plugins: dedupDescriptors(chain.plugins), plugins: dedupDescriptors(chain.plugins),
presets: dedupDescriptors(chain.presets), presets: dedupDescriptors(chain.presets),
options: chain.options.map(o => normalizeOptions(o)), options: chain.options.map(o => normalizeOptions(o)),
ignore: ignore || undefined, ignore: ignoreFile || undefined,
babelrc: babelrc || undefined, babelrc: babelrcFile || undefined,
config: configFile || undefined,
}; };
} }
function babelrcLoadEnabled(
context: ConfigContext,
pkgData: FilePackageData,
babelrcRoots: BabelrcSearch | void,
absoluteRoot: string,
): boolean {
if (typeof babelrcRoots === "boolean") return babelrcRoots;
// Fast path to avoid having to load micromatch if the babelrc is just
// loading in the standard root directory.
if (babelrcRoots === undefined) {
return pkgData.directories.indexOf(absoluteRoot) !== -1;
}
let babelrcPatterns = babelrcRoots;
if (!Array.isArray(babelrcPatterns)) babelrcPatterns = [babelrcPatterns];
babelrcPatterns = babelrcPatterns.map(pat => path.resolve(context.cwd, pat));
// Fast path to avoid having to load micromatch if the babelrc is just
// loading in the standard root directory.
if (babelrcPatterns.length === 1 && babelrcPatterns[0] === absoluteRoot) {
return pkgData.directories.indexOf(absoluteRoot) !== -1;
}
return micromatch(pkgData.directories, babelrcPatterns).length > 0;
}
/** /**
* Build a config chain for just the programmatic options passed into Babel. * Build a config chain for just the programmatic options passed into Babel.
*/ */

View File

@ -5,45 +5,35 @@ import path from "path";
import fs from "fs"; import fs from "fs";
import json5 from "json5"; import json5 from "json5";
import resolve from "resolve"; import resolve from "resolve";
import { makeStrongCache, type CacheConfigurator } from "../caching"; import {
makeStrongCache,
makeWeakCache,
type CacheConfigurator,
} from "../caching";
import makeAPI from "../helpers/config-api"; import makeAPI from "../helpers/config-api";
import { makeStaticFileCache } from "./utils";
import type { FilePackageData, RelativeConfig, ConfigFile } from "./types";
const debug = buildDebug("babel:config:loading:files:configuration"); const debug = buildDebug("babel:config:loading:files:configuration");
export type ConfigFile = { const BABEL_CONFIG_JS_FILENAME = "babel.config.js";
filepath: string,
dirname: string,
options: {},
};
export type IgnoreFile = {
filepath: string,
dirname: string,
ignore: Array<string>,
};
export type RelativeConfig = {
config: ConfigFile | null,
ignore: IgnoreFile | null,
};
const BABELRC_FILENAME = ".babelrc"; const BABELRC_FILENAME = ".babelrc";
const BABELRC_JS_FILENAME = ".babelrc.js"; const BABELRC_JS_FILENAME = ".babelrc.js";
const PACKAGE_FILENAME = "package.json";
const BABELIGNORE_FILENAME = ".babelignore"; const BABELIGNORE_FILENAME = ".babelignore";
export function findRelativeConfig( export function findRelativeConfig(
filepath: string, packageData: FilePackageData,
envName: string, envName: string,
): RelativeConfig { ): RelativeConfig {
let config = null; let config = null;
let ignore = null; let ignore = null;
const dirname = path.dirname(filepath); const dirname = path.dirname(packageData.filepath);
let loc = dirname;
while (true) { for (const loc of packageData.directories) {
if (!config) { if (!config) {
config = [BABELRC_FILENAME, BABELRC_JS_FILENAME, PACKAGE_FILENAME].reduce( config = [BABELRC_FILENAME, BABELRC_JS_FILENAME].reduce(
(previousConfig: ConfigFile | null, name) => { (previousConfig: ConfigFile | null, name) => {
const filepath = path.join(loc, name); const filepath = path.join(loc, name);
const config = readConfig(filepath, envName); const config = readConfig(filepath, envName);
@ -62,6 +52,23 @@ export function findRelativeConfig(
null, null,
); );
const pkgConfig =
packageData.pkg && packageData.pkg.dirname === loc
? packageToBabelConfig(packageData.pkg)
: null;
if (pkgConfig) {
if (config) {
throw new Error(
`Multiple configuration files found. Please remove one:\n` +
` - ${path.basename(pkgConfig.filepath)}#babel\n` +
` - ${path.basename(config.filepath)}\n` +
`from ${loc}`,
);
}
config = pkgConfig;
}
if (config) { if (config) {
debug("Found configuration %o from %o.", config.filepath, dirname); debug("Found configuration %o from %o.", config.filepath, dirname);
} }
@ -75,15 +82,24 @@ export function findRelativeConfig(
debug("Found ignore %o from %o.", ignore.filepath, dirname); debug("Found ignore %o from %o.", ignore.filepath, dirname);
} }
} }
const nextLoc = path.dirname(loc);
if (loc === nextLoc) break;
loc = nextLoc;
} }
return { config, ignore }; return { config, ignore };
} }
export function findRootConfig(
dirname: string,
envName: string,
): ConfigFile | null {
const filepath = path.resolve(dirname, BABEL_CONFIG_JS_FILENAME);
const conf = readConfig(filepath, envName);
if (conf) {
debug("Found root config %o in $o.", BABEL_CONFIG_JS_FILENAME, dirname);
}
return conf;
}
export function loadConfig( export function loadConfig(
name: string, name: string,
dirname: string, dirname: string,
@ -107,7 +123,7 @@ export function loadConfig(
function readConfig(filepath, envName): ConfigFile | null { function readConfig(filepath, envName): ConfigFile | null {
return path.extname(filepath) === ".js" return path.extname(filepath) === ".js"
? readConfigJS(filepath, { envName }) ? readConfigJS(filepath, { envName })
: readConfigFile(filepath); : readConfigJSON5(filepath);
} }
const LOADING_CONFIGS = new Set(); const LOADING_CONFIGS = new Set();
@ -180,27 +196,34 @@ const readConfigJS = makeStrongCache(
}, },
); );
const readConfigFile = makeStaticFileCache((filepath, content) => { const packageToBabelConfig = makeWeakCache(
let options; (file: ConfigFile): ConfigFile | null => {
if (path.basename(filepath) === PACKAGE_FILENAME) { if (typeof file.options.babel === "undefined") return null;
try { const babel = file.options.babel;
options = JSON.parse(content).babel;
} catch (err) { if (typeof babel !== "object" || Array.isArray(babel) || babel === null) {
err.message = `${filepath}: Error while parsing JSON - ${err.message}`; throw new Error(`${file.filepath}: .babel property must be an object`);
throw err;
}
if (!options) return null;
} else {
try {
options = json5.parse(content);
} catch (err) {
err.message = `${filepath}: Error while parsing config - ${err.message}`;
throw err;
} }
if (!options) throw new Error(`${filepath}: No config detected`); return {
filepath: file.filepath,
dirname: file.dirname,
options: babel,
};
},
);
const readConfigJSON5 = makeStaticFileCache((filepath, content) => {
let options;
try {
options = json5.parse(content);
} catch (err) {
err.message = `${filepath}: Error while parsing config - ${err.message}`;
throw err;
} }
if (!options) throw new Error(`${filepath}: No config detected`);
if (typeof options !== "object") { if (typeof options !== "object") {
throw new Error(`${filepath}: Config returned typeof ${typeof options}`); throw new Error(`${filepath}: Config returned typeof ${typeof options}`);
} }
@ -228,27 +251,6 @@ const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
}; };
}); });
function makeStaticFileCache<T>(fn: (string, string) => T): string => T | null {
return makeStrongCache((filepath, cache) => {
if (cache.invalidate(() => fileMtime(filepath)) === null) {
cache.forever();
return null;
}
return fn(filepath, fs.readFileSync(filepath, "utf8"));
});
}
function fileMtime(filepath: string): number | null {
try {
return +fs.statSync(filepath).mtime;
} catch (e) {
if (e.code !== "ENOENT") throw e;
}
return null;
}
function throwConfigError() { function throwConfigError() {
throw new Error(`\ throw new Error(`\
Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured

View File

@ -1,17 +1,42 @@
// @flow // @flow
import type { ConfigFile, IgnoreFile, RelativeConfig } from "./configuration"; import type {
ConfigFile,
IgnoreFile,
RelativeConfig,
FilePackageData,
} from "./types";
export type { ConfigFile, IgnoreFile, RelativeConfig }; export type { ConfigFile, IgnoreFile, RelativeConfig, FilePackageData };
export function findRelativeConfig( export function findPackageData(filepath: string): FilePackageData {
filepath: string, return {
envName: string, // eslint-disable-line no-unused-vars filepath,
): RelativeConfig { directories: [],
return { config: null, ignore: null }; pkg: null,
isPackage: false,
};
} }
export function loadConfig(name: string, dirname: string): ConfigFile { export function findRelativeConfig(
pkgData: FilePackageData,
envName: string, // eslint-disable-line no-unused-vars
): RelativeConfig {
return { pkg: null, config: null, ignore: null };
}
export function findRootConfig(
dirname: string,
envName: string, // eslint-disable-line no-unused-vars
): ConfigFile | null {
return null;
}
export function loadConfig(
name: string,
dirname: string,
envName: string, // eslint-disable-line no-unused-vars
): ConfigFile {
throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`); throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`);
} }

View File

@ -7,5 +7,22 @@ import typeof * as indexType from "./index";
// exports of index-browser, since this file may be replaced at bundle time with index-browser. // exports of index-browser, since this file may be replaced at bundle time with index-browser.
((({}: any): $Exact<indexBrowserType>): $Exact<indexType>); ((({}: any): $Exact<indexBrowserType>): $Exact<indexType>);
export * from "./configuration"; export { findPackageData } from "./package";
export * from "./plugins";
export {
findRelativeConfig,
findRootConfig,
loadConfig,
} from "./configuration";
export type {
ConfigFile,
IgnoreFile,
RelativeConfig,
FilePackageData,
} from "./types";
export {
resolvePlugin,
resolvePreset,
loadPlugin,
loadPreset,
} from "./plugins";

View File

@ -0,0 +1,60 @@
// @flow
import path from "path";
import { makeStaticFileCache } from "./utils";
import type { ConfigFile, FilePackageData } from "./types";
const PACKAGE_FILENAME = "package.json";
/**
* Find metadata about the package that this file is inside of. Resolution
* of Babel's config requires general package information to decide when to
* search for .babelrc files
*/
export function findPackageData(filepath: string): FilePackageData {
let pkg = null;
const directories = [];
let isPackage = true;
let dirname = path.dirname(filepath);
while (!pkg && path.basename(dirname) !== "node_modules") {
directories.push(dirname);
pkg = readConfigPackage(path.join(dirname, PACKAGE_FILENAME));
const nextLoc = path.dirname(dirname);
if (dirname === nextLoc) {
isPackage = false;
break;
}
dirname = nextLoc;
}
return { filepath, directories, pkg, isPackage };
}
const readConfigPackage = makeStaticFileCache(
(filepath, content): ConfigFile => {
let options;
try {
options = JSON.parse(content);
} catch (err) {
err.message = `${filepath}: Error while parsing JSON - ${err.message}`;
throw err;
}
if (typeof options !== "object") {
throw new Error(`${filepath}: Config returned typeof ${typeof options}`);
}
if (Array.isArray(options)) {
throw new Error(`${filepath}: Expected config object but found array`);
}
return {
filepath,
dirname: path.dirname(filepath),
options,
};
},
);

View File

@ -0,0 +1,38 @@
// @flow
export type ConfigFile = {
filepath: string,
dirname: string,
options: {},
};
export type IgnoreFile = {
filepath: string,
dirname: string,
ignore: Array<string>,
};
export type RelativeConfig = {
// The actual config, either from package.json#babel, .babelrc, or
// .babelrc.js, if there was one.
config: ConfigFile | null,
// The .babelignore, if there was one.
ignore: IgnoreFile | null,
};
export type FilePackageData = {
// The file in the package.
filepath: string,
// Any ancestor directories of the file that are within the package.
directories: Array<string>,
// The contents of the package.json. May not be found if the package just
// terminated at a node_modules folder without finding one.
pkg: ConfigFile | null,
// True if a package.json or node_modules folder was found while traversing
// the directory structure.
isPackage: boolean,
};

View File

@ -0,0 +1,27 @@
// @flow
import fs from "fs";
import { makeStrongCache } from "../caching";
export function makeStaticFileCache<T>(
fn: (string, string) => T,
): string => T | null {
return makeStrongCache((filepath, cache) => {
if (cache.invalidate(() => fileMtime(filepath)) === null) {
cache.forever();
return null;
}
return fn(filepath, fs.readFileSync(filepath, "utf8"));
});
}
function fileMtime(filepath: string): number | null {
try {
return +fs.statSync(filepath).mtime;
} catch (e) {
if (e.code !== "ENOENT" && e.code !== "ENOTDIR") throw e;
}
return null;
}

View File

@ -17,6 +17,7 @@ export default function loadPrivatePartialConfig(
context: ConfigContext, context: ConfigContext,
ignore: IgnoreFile | void, ignore: IgnoreFile | void,
babelrc: ConfigFile | void, babelrc: ConfigFile | void,
config: ConfigFile | void,
} | null { } | null {
if ( if (
inputOpts != null && inputOpts != null &&
@ -64,6 +65,7 @@ export default function loadPrivatePartialConfig(
context, context,
ignore: configChain.ignore, ignore: configChain.ignore,
babelrc: configChain.babelrc, babelrc: configChain.babelrc,
config: configChain.config,
}; };
} }
@ -71,7 +73,7 @@ export function loadPartialConfig(inputOpts: mixed): PartialConfig | null {
const result = loadPrivatePartialConfig(inputOpts); const result = loadPrivatePartialConfig(inputOpts);
if (!result) return null; if (!result) return null;
const { options, babelrc, ignore } = result; const { options, babelrc, ignore, config } = result;
(options.plugins || []).forEach(item => { (options.plugins || []).forEach(item => {
if (item.value instanceof Plugin) { if (item.value instanceof Plugin) {
@ -86,6 +88,7 @@ export function loadPartialConfig(inputOpts: mixed): PartialConfig | null {
options, options,
babelrc ? babelrc.filepath : undefined, babelrc ? babelrc.filepath : undefined,
ignore ? ignore.filepath : undefined, ignore ? ignore.filepath : undefined,
config ? config.filepath : undefined,
); );
} }
@ -99,15 +102,18 @@ class PartialConfig {
options: ValidatedOptions; options: ValidatedOptions;
babelrc: string | void; babelrc: string | void;
babelignore: string | void; babelignore: string | void;
config: string | void;
constructor( constructor(
options: ValidatedOptions, options: ValidatedOptions,
babelrc: string | void, babelrc: string | void,
ignore: string | void, ignore: string | void,
config: string | void,
) { ) {
this.options = options; this.options = options;
this.babelignore = ignore; this.babelignore = ignore;
this.babelrc = babelrc; this.babelrc = babelrc;
this.config = config;
// Freeze since this is a public API and it should be extremely obvious that // Freeze since this is a public API and it should be extremely obvious that
// reassigning properties on here does nothing. // reassigning properties on here does nothing.
@ -122,7 +128,7 @@ class PartialConfig {
* this.babelrc directly. * this.babelrc directly.
*/ */
hasFilesystemConfig(): boolean { hasFilesystemConfig(): boolean {
return this.babelrc !== undefined; return this.babelrc !== undefined || this.config !== undefined;
} }
} }
Object.freeze(PartialConfig.prototype); Object.freeze(PartialConfig.prototype);

View File

@ -1,6 +1,8 @@
// @flow // @flow
import type { import type {
ConfigFileSearch,
BabelrcSearch,
IgnoreList, IgnoreList,
IgnoreItem, IgnoreItem,
PluginList, PluginList,
@ -164,6 +166,45 @@ function checkValidTest(value: mixed): boolean {
); );
} }
export function assertConfigFileSearch(
key: string,
value: mixed,
): ConfigFileSearch | void {
if (
value !== undefined &&
typeof value !== "boolean" &&
typeof value !== "string"
) {
throw new Error(
`.${key} must be a undefined, a boolean, a string, ` +
`got ${JSON.stringify(value)}`,
);
}
return value;
}
export function assertBabelrcSearch(
key: string,
value: mixed,
): BabelrcSearch | void {
if (value === undefined || typeof value === "boolean") return value;
if (Array.isArray(value)) {
value.forEach((item, i) => {
if (typeof item !== "string") {
throw new Error(`.${key}[${i}] must be a string.`);
}
});
} else if (typeof value !== "string") {
throw new Error(
`.${key} must be a undefined, a boolean, a string, ` +
`or an array of strings, got ${JSON.stringify(value)}`,
);
}
return (value: any);
}
export function assertPluginList(key: string, value: mixed): PluginList | void { export function assertPluginList(key: string, value: mixed): PluginList | void {
const arr = assertArray(key, value); const arr = assertArray(key, value);
if (arr) { if (arr) {

View File

@ -13,6 +13,8 @@ import {
assertIgnoreList, assertIgnoreList,
assertPluginList, assertPluginList,
assertConfigApplicableTest, assertConfigApplicableTest,
assertConfigFileSearch,
assertBabelrcSearch,
assertFunction, assertFunction,
assertSourceMaps, assertSourceMaps,
assertCompact, assertCompact,
@ -23,6 +25,11 @@ import {
const ROOT_VALIDATORS: ValidatorSet = { const ROOT_VALIDATORS: ValidatorSet = {
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>), cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
root: (assertString: Validator<$PropertyType<ValidatedOptions, "root">>),
configFile: (assertConfigFileSearch: Validator<
$PropertyType<ValidatedOptions, "configFile">,
>),
filename: (assertString: Validator< filename: (assertString: Validator<
$PropertyType<ValidatedOptions, "filename">, $PropertyType<ValidatedOptions, "filename">,
>), >),
@ -32,6 +39,9 @@ const ROOT_VALIDATORS: ValidatorSet = {
babelrc: (assertBoolean: Validator< babelrc: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "babelrc">, $PropertyType<ValidatedOptions, "babelrc">,
>), >),
babelrcRoots: (assertBabelrcSearch: Validator<
$PropertyType<ValidatedOptions, "babelrcRoots">,
>),
code: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "code">>), code: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "code">>),
ast: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "ast">>), ast: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "ast">>),
@ -151,6 +161,9 @@ export type ValidatedOptions = {
filename?: string, filename?: string,
filenameRelative?: string, filenameRelative?: string,
babelrc?: boolean, babelrc?: boolean,
babelrcRoots?: BabelrcSearch,
configFile?: ConfigFileSearch,
root?: string,
code?: boolean, code?: boolean,
ast?: boolean, ast?: boolean,
inputSourceMap?: RootInputSourceMapOption, inputSourceMap?: RootInputSourceMapOption,
@ -223,6 +236,8 @@ export type PluginList = $ReadOnlyArray<PluginItem>;
export type OverridesList = Array<ValidatedOptions>; export type OverridesList = Array<ValidatedOptions>;
export type ConfigApplicableTest = IgnoreItem | Array<IgnoreItem>; export type ConfigApplicableTest = IgnoreItem | Array<IgnoreItem>;
export type ConfigFileSearch = string | boolean;
export type BabelrcSearch = boolean | string | Array<string>;
export type SourceMapsOption = boolean | "inline" | "both"; export type SourceMapsOption = boolean | "inline" | "both";
export type SourceTypeOption = "module" | "script" | "unambiguous"; export type SourceTypeOption = "module" | "script" | "unambiguous";
export type CompactOption = boolean | "auto"; export type CompactOption = boolean | "auto";

View File

@ -294,6 +294,7 @@ describe("api", function() {
process.env.BABEL_ENV = "development"; process.env.BABEL_ENV = "development";
const result = babel.transform("", { const result = babel.transform("", {
cwd: path.join(__dirname, "fixtures", "config", "complex-plugin-config"),
filename: path.join( filename: path.join(
__dirname, __dirname,
"fixtures", "fixtures",

View File

@ -11,6 +11,7 @@ describe("buildConfigChain", function() {
describe("single", () => { describe("single", () => {
it("should process matching string values", () => { it("should process matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: fixture("nonexistant-fake"), test: fixture("nonexistant-fake"),
@ -22,6 +23,7 @@ describe("buildConfigChain", function() {
it("should process matching RegExp values", () => { it("should process matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: new RegExp(fixture("nonexistant-fake")), test: new RegExp(fixture("nonexistant-fake")),
@ -33,6 +35,7 @@ describe("buildConfigChain", function() {
it("should process matching function values", () => { it("should process matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: p => p.indexOf(fixture("nonexistant-fake")) === 0, test: p => p.indexOf(fixture("nonexistant-fake")) === 0,
@ -44,6 +47,7 @@ describe("buildConfigChain", function() {
it("should process non-matching string values", () => { it("should process non-matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: fixture("nonexistant-fake-unknown"), test: fixture("nonexistant-fake-unknown"),
@ -55,6 +59,7 @@ describe("buildConfigChain", function() {
it("should process non-matching RegExp values", () => { it("should process non-matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: new RegExp(fixture("nonexistant-unknown")), test: new RegExp(fixture("nonexistant-unknown")),
@ -66,6 +71,7 @@ describe("buildConfigChain", function() {
it("should process non-matching function values", () => { it("should process non-matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: p => p.indexOf(fixture("nonexistant-unknown")) === 0, test: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
@ -79,6 +85,7 @@ describe("buildConfigChain", function() {
describe("array", () => { describe("array", () => {
it("should process matching string values", () => { it("should process matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: [fixture("nonexistant-fake")], test: [fixture("nonexistant-fake")],
@ -90,6 +97,7 @@ describe("buildConfigChain", function() {
it("should process matching RegExp values", () => { it("should process matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: [new RegExp(fixture("nonexistant-fake"))], test: [new RegExp(fixture("nonexistant-fake"))],
@ -101,6 +109,7 @@ describe("buildConfigChain", function() {
it("should process matching function values", () => { it("should process matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: [p => p.indexOf(fixture("nonexistant-fake")) === 0], test: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
@ -112,6 +121,7 @@ describe("buildConfigChain", function() {
it("should process non-matching string values", () => { it("should process non-matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: [fixture("nonexistant-fake-unknown")], test: [fixture("nonexistant-fake-unknown")],
@ -123,6 +133,7 @@ describe("buildConfigChain", function() {
it("should process non-matching RegExp values", () => { it("should process non-matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: [new RegExp(fixture("nonexistant-unknown"))], test: [new RegExp(fixture("nonexistant-unknown"))],
@ -134,6 +145,7 @@ describe("buildConfigChain", function() {
it("should process non-matching function values", () => { it("should process non-matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
test: [p => p.indexOf(fixture("nonexistant-unknown")) === 0], test: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
@ -149,6 +161,7 @@ describe("buildConfigChain", function() {
describe("single", () => { describe("single", () => {
it("should process matching string values", () => { it("should process matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: fixture("nonexistant-fake"), include: fixture("nonexistant-fake"),
@ -160,6 +173,7 @@ describe("buildConfigChain", function() {
it("should process matching RegExp values", () => { it("should process matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: new RegExp(fixture("nonexistant-fake")), include: new RegExp(fixture("nonexistant-fake")),
@ -171,6 +185,7 @@ describe("buildConfigChain", function() {
it("should process matching function values", () => { it("should process matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: p => p.indexOf(fixture("nonexistant-fake")) === 0, include: p => p.indexOf(fixture("nonexistant-fake")) === 0,
@ -182,6 +197,7 @@ describe("buildConfigChain", function() {
it("should process non-matching string values", () => { it("should process non-matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: fixture("nonexistant-fake-unknown"), include: fixture("nonexistant-fake-unknown"),
@ -193,6 +209,7 @@ describe("buildConfigChain", function() {
it("should process non-matching RegExp values", () => { it("should process non-matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: new RegExp(fixture("nonexistant-unknown")), include: new RegExp(fixture("nonexistant-unknown")),
@ -204,6 +221,7 @@ describe("buildConfigChain", function() {
it("should process non-matching function values", () => { it("should process non-matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: p => p.indexOf(fixture("nonexistant-unknown")) === 0, include: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
@ -217,6 +235,7 @@ describe("buildConfigChain", function() {
describe("array", () => { describe("array", () => {
it("should process matching string values", () => { it("should process matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: [fixture("nonexistant-fake")], include: [fixture("nonexistant-fake")],
@ -228,6 +247,7 @@ describe("buildConfigChain", function() {
it("should process matching RegExp values", () => { it("should process matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: [new RegExp(fixture("nonexistant-fake"))], include: [new RegExp(fixture("nonexistant-fake"))],
@ -239,6 +259,7 @@ describe("buildConfigChain", function() {
it("should process matching function values", () => { it("should process matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: [p => p.indexOf(fixture("nonexistant-fake")) === 0], include: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
@ -250,6 +271,7 @@ describe("buildConfigChain", function() {
it("should process non-matching string values", () => { it("should process non-matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: [fixture("nonexistant-fake-unknown")], include: [fixture("nonexistant-fake-unknown")],
@ -261,6 +283,7 @@ describe("buildConfigChain", function() {
it("should process non-matching RegExp values", () => { it("should process non-matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: [new RegExp(fixture("nonexistant-unknown"))], include: [new RegExp(fixture("nonexistant-unknown"))],
@ -272,6 +295,7 @@ describe("buildConfigChain", function() {
it("should process non-matching function values", () => { it("should process non-matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
include: [p => p.indexOf(fixture("nonexistant-unknown")) === 0], include: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
@ -287,6 +311,7 @@ describe("buildConfigChain", function() {
describe("single", () => { describe("single", () => {
it("should process matching string values", () => { it("should process matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: fixture("nonexistant-fake"), exclude: fixture("nonexistant-fake"),
@ -298,6 +323,7 @@ describe("buildConfigChain", function() {
it("should process matching RegExp values", () => { it("should process matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: new RegExp(fixture("nonexistant-fake")), exclude: new RegExp(fixture("nonexistant-fake")),
@ -309,6 +335,7 @@ describe("buildConfigChain", function() {
it("should process matching function values", () => { it("should process matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: p => p.indexOf(fixture("nonexistant-fake")) === 0, exclude: p => p.indexOf(fixture("nonexistant-fake")) === 0,
@ -320,6 +347,7 @@ describe("buildConfigChain", function() {
it("should process non-matching string values", () => { it("should process non-matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: fixture("nonexistant-fake-unknown"), exclude: fixture("nonexistant-fake-unknown"),
@ -331,6 +359,7 @@ describe("buildConfigChain", function() {
it("should process non-matching RegExp values", () => { it("should process non-matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: new RegExp(fixture("nonexistant-unknown")), exclude: new RegExp(fixture("nonexistant-unknown")),
@ -342,6 +371,7 @@ describe("buildConfigChain", function() {
it("should process non-matching function values", () => { it("should process non-matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: p => p.indexOf(fixture("nonexistant-unknown")) === 0, exclude: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
@ -355,6 +385,7 @@ describe("buildConfigChain", function() {
describe("array", () => { describe("array", () => {
it("should process matching string values", () => { it("should process matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: [fixture("nonexistant-fake")], exclude: [fixture("nonexistant-fake")],
@ -366,6 +397,7 @@ describe("buildConfigChain", function() {
it("should process matching RegExp values", () => { it("should process matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: [new RegExp(fixture("nonexistant-fake"))], exclude: [new RegExp(fixture("nonexistant-fake"))],
@ -377,6 +409,7 @@ describe("buildConfigChain", function() {
it("should process matching function values", () => { it("should process matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: [p => p.indexOf(fixture("nonexistant-fake")) === 0], exclude: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
@ -388,6 +421,7 @@ describe("buildConfigChain", function() {
it("should process non-matching string values", () => { it("should process non-matching string values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: [fixture("nonexistant-fake-unknown")], exclude: [fixture("nonexistant-fake-unknown")],
@ -399,6 +433,7 @@ describe("buildConfigChain", function() {
it("should process non-matching RegExp values", () => { it("should process non-matching RegExp values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: [new RegExp(fixture("nonexistant-unknown"))], exclude: [new RegExp(fixture("nonexistant-unknown"))],
@ -410,6 +445,7 @@ describe("buildConfigChain", function() {
it("should process non-matching function values", () => { it("should process non-matching function values", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
exclude: [p => p.indexOf(fixture("nonexistant-unknown")) === 0], exclude: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
@ -424,6 +460,7 @@ describe("buildConfigChain", function() {
describe("ignore", () => { describe("ignore", () => {
it("should ignore files that match", () => { it("should ignore files that match", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
ignore: [ ignore: [
@ -441,6 +478,7 @@ describe("buildConfigChain", function() {
it("should not ignore files that don't match", () => { it("should not ignore files that don't match", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
ignore: [ ignore: [
@ -456,6 +494,7 @@ describe("buildConfigChain", function() {
describe("only", () => { describe("only", () => {
it("should ignore files that don't match", () => { it("should ignore files that don't match", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
only: [ only: [
@ -469,6 +508,7 @@ describe("buildConfigChain", function() {
it("should not ignore files that match", () => { it("should not ignore files that match", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
only: [ only: [
@ -484,6 +524,7 @@ describe("buildConfigChain", function() {
describe("ignore/only", () => { describe("ignore/only", () => {
it("should ignore files that match ignore and don't match only", () => { it("should ignore files that match ignore and don't match only", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
ignore: [fixture("nonexistant-fake", "src.js")], ignore: [fixture("nonexistant-fake", "src.js")],
@ -495,6 +536,7 @@ describe("buildConfigChain", function() {
it("should ignore files that match ignore and also only", () => { it("should ignore files that match ignore and also only", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
ignore: [fixture("nonexistant-fake", "src.js")], ignore: [fixture("nonexistant-fake", "src.js")],
@ -506,6 +548,7 @@ describe("buildConfigChain", function() {
it("should not ignore files that match only and not ignore", () => { it("should not ignore files that match only and not ignore", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
only: [fixture("nonexistant-fake", "src.js")], only: [fixture("nonexistant-fake", "src.js")],
@ -516,6 +559,7 @@ describe("buildConfigChain", function() {
it("should not ignore files when no ignore/only are specified", () => { it("should not ignore files when no ignore/only are specified", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
}); });
@ -525,6 +569,7 @@ describe("buildConfigChain", function() {
it("should allow negation of only", () => { it("should allow negation of only", () => {
const opts1 = loadOptions({ const opts1 = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
only: [ only: [
@ -535,6 +580,7 @@ describe("buildConfigChain", function() {
expect(opts1).toBeNull(); expect(opts1).toBeNull();
const opts2 = loadOptions({ const opts2 = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
only: [ only: [
@ -545,6 +591,7 @@ describe("buildConfigChain", function() {
expect(opts2).not.toBeNull(); expect(opts2).not.toBeNull();
const opts3 = loadOptions({ const opts3 = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "folder", "src.js"), filename: fixture("nonexistant-fake", "folder", "src.js"),
babelrc: false, babelrc: false,
only: [ only: [
@ -557,6 +604,7 @@ describe("buildConfigChain", function() {
it("should allow negation of ignore", () => { it("should allow negation of ignore", () => {
const opts1 = loadOptions({ const opts1 = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
ignore: [ ignore: [
@ -568,6 +616,7 @@ describe("buildConfigChain", function() {
// Tests disabled pending https://github.com/babel/babel/issues/6907 // Tests disabled pending https://github.com/babel/babel/issues/6907
// const opts2 = loadOptions({ // const opts2 = loadOptions({
// cwd: fixture("nonexistant-fake"),
// filename: fixture("nonexistant-fake", "src.js"), // filename: fixture("nonexistant-fake", "src.js"),
// babelrc: false, // babelrc: false,
// ignore: [ // ignore: [
@ -578,6 +627,7 @@ describe("buildConfigChain", function() {
// expect(opts2).not.toBeNull(); // expect(opts2).not.toBeNull();
// //
// const opts3 = loadOptions({ // const opts3 = loadOptions({
// cwd: fixture("nonexistant-fake"),
// filename: fixture("nonexistant-fake", "folder", "src.js"), // filename: fixture("nonexistant-fake", "folder", "src.js"),
// babelrc: false, // babelrc: false,
// ignore: [ // ignore: [
@ -718,13 +768,13 @@ describe("buildConfigChain", function() {
"package.json", "package.json",
); );
const opts1 = loadOptions({ filename }); const opts1 = loadOptions({ filename, cwd: path.dirname(filename) });
const opts2 = loadOptions({ filename }); const opts2 = loadOptions({ filename, cwd: path.dirname(filename) });
touch(pkgJSON); touch(pkgJSON);
const opts3 = loadOptions({ filename }); const opts3 = loadOptions({ filename, cwd: path.dirname(filename) });
const opts4 = loadOptions({ filename }); const opts4 = loadOptions({ filename, cwd: path.dirname(filename) });
expect(opts1.plugins).toHaveLength(1); expect(opts1.plugins).toHaveLength(1);
expect(opts2.plugins).toHaveLength(1); expect(opts2.plugins).toHaveLength(1);
@ -752,13 +802,13 @@ describe("buildConfigChain", function() {
".babelrc", ".babelrc",
); );
const opts1 = loadOptions({ filename }); const opts1 = loadOptions({ filename, cwd: path.dirname(filename) });
const opts2 = loadOptions({ filename }); const opts2 = loadOptions({ filename, cwd: path.dirname(filename) });
touch(babelrcFile); touch(babelrcFile);
const opts3 = loadOptions({ filename }); const opts3 = loadOptions({ filename, cwd: path.dirname(filename) });
const opts4 = loadOptions({ filename }); const opts4 = loadOptions({ filename, cwd: path.dirname(filename) });
expect(opts1.plugins).toHaveLength(1); expect(opts1.plugins).toHaveLength(1);
expect(opts2.plugins).toHaveLength(1); expect(opts2.plugins).toHaveLength(1);
@ -780,11 +830,19 @@ describe("buildConfigChain", function() {
"src.js", "src.js",
); );
const opts1 = loadOptions({ filename }); const opts1 = loadOptions({ filename, cwd: path.dirname(filename) });
const opts2 = loadOptions({ filename }); const opts2 = loadOptions({ filename, cwd: path.dirname(filename) });
const opts3 = loadOptions({ filename, envName: "new-env" }); const opts3 = loadOptions({
const opts4 = loadOptions({ filename, envName: "new-env" }); filename,
envName: "new-env",
cwd: path.dirname(filename),
});
const opts4 = loadOptions({
filename,
envName: "new-env",
cwd: path.dirname(filename),
});
expect(opts1.plugins).toHaveLength(1); expect(opts1.plugins).toHaveLength(1);
expect(opts2.plugins).toHaveLength(1); expect(opts2.plugins).toHaveLength(1);
@ -803,6 +861,7 @@ describe("buildConfigChain", function() {
describe("overrides merging", () => { describe("overrides merging", () => {
it("should apply matching overrides over base configs", () => { it("should apply matching overrides over base configs", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
comments: true, comments: true,
@ -819,6 +878,7 @@ describe("buildConfigChain", function() {
it("should not apply non-matching overrides over base configs", () => { it("should not apply non-matching overrides over base configs", () => {
const opts = loadOptions({ const opts = loadOptions({
cwd: fixture("nonexistant-fake"),
filename: fixture("nonexistant-fake", "src.js"), filename: fixture("nonexistant-fake", "src.js"),
babelrc: false, babelrc: false,
comments: true, comments: true,
@ -860,9 +920,15 @@ describe("buildConfigChain", function() {
it("should load .babelrc", () => { it("should load .babelrc", () => {
const filename = fixture("config-files", "babelrc", "src.js"); const filename = fixture("config-files", "babelrc", "src.js");
expect(loadOptions({ filename })).toEqual({ expect(
loadOptions({
filename,
cwd: path.dirname(filename),
}),
).toEqual({
...getDefaults(), ...getDefaults(),
filename, filename,
cwd: path.dirname(filename),
comments: true, comments: true,
}); });
}); });
@ -870,9 +936,10 @@ describe("buildConfigChain", function() {
it("should load .babelrc.js", () => { it("should load .babelrc.js", () => {
const filename = fixture("config-files", "babelrc-js", "src.js"); const filename = fixture("config-files", "babelrc-js", "src.js");
expect(loadOptions({ filename })).toEqual({ expect(loadOptions({ filename, cwd: path.dirname(filename) })).toEqual({
...getDefaults(), ...getDefaults(),
filename, filename,
cwd: path.dirname(filename),
comments: true, comments: true,
}); });
}); });
@ -880,9 +947,10 @@ describe("buildConfigChain", function() {
it("should load package.json#babel", () => { it("should load package.json#babel", () => {
const filename = fixture("config-files", "pkg", "src.js"); const filename = fixture("config-files", "pkg", "src.js");
expect(loadOptions({ filename })).toEqual({ expect(loadOptions({ filename, cwd: path.dirname(filename) })).toEqual({
...getDefaults(), ...getDefaults(),
filename, filename,
cwd: path.dirname(filename),
comments: true, comments: true,
}); });
}); });
@ -890,39 +958,40 @@ describe("buildConfigChain", function() {
it("should load .babelignore", () => { it("should load .babelignore", () => {
const filename = fixture("config-files", "babelignore", "src.js"); const filename = fixture("config-files", "babelignore", "src.js");
expect(loadOptions({ filename })).toBeNull(); expect(loadOptions({ filename, cwd: path.dirname(filename) })).toBeNull();
}); });
it("should throw if there are both .babelrc and .babelrc.js", () => { it("should throw if there are both .babelrc and .babelrc.js", () => {
const filename = fixture("config-files", "both-babelrc", "src.js"); const filename = fixture("config-files", "both-babelrc", "src.js");
expect(() => loadOptions({ filename })).toThrow( expect(() =>
/Multiple configuration files found/, loadOptions({ filename, cwd: path.dirname(filename) }),
); ).toThrow(/Multiple configuration files found/);
}); });
it("should throw if there are both .babelrc and package.json", () => { it("should throw if there are both .babelrc and package.json", () => {
const filename = fixture("config-files", "pkg-babelrc", "src.js"); const filename = fixture("config-files", "pkg-babelrc", "src.js");
expect(() => loadOptions({ filename })).toThrow( expect(() =>
/Multiple configuration files found/, loadOptions({ filename, cwd: path.dirname(filename) }),
); ).toThrow(/Multiple configuration files found/);
}); });
it("should throw if there are both .babelrc.js and package.json", () => { it("should throw if there are both .babelrc.js and package.json", () => {
const filename = fixture("config-files", "pkg-babelrc-js", "src.js"); const filename = fixture("config-files", "pkg-babelrc-js", "src.js");
expect(() => loadOptions({ filename })).toThrow( expect(() =>
/Multiple configuration files found/, loadOptions({ filename, cwd: path.dirname(filename) }),
); ).toThrow(/Multiple configuration files found/);
}); });
it("should ignore package.json without a 'babel' property", () => { it("should ignore package.json without a 'babel' property", () => {
const filename = fixture("config-files", "pkg-ignored", "src.js"); const filename = fixture("config-files", "pkg-ignored", "src.js");
expect(loadOptions({ filename })).toEqual({ expect(loadOptions({ filename, cwd: path.dirname(filename) })).toEqual({
...getDefaults(), ...getDefaults(),
filename, filename,
cwd: path.dirname(filename),
comments: true, comments: true,
}); });
}); });
@ -930,23 +999,25 @@ describe("buildConfigChain", function() {
it("should show helpful errors for .babelrc", () => { it("should show helpful errors for .babelrc", () => {
const filename = fixture("config-files", "babelrc-error", "src.js"); const filename = fixture("config-files", "babelrc-error", "src.js");
expect(() => loadOptions({ filename })).toThrow( expect(() =>
/Error while parsing config - /, loadOptions({ filename, cwd: path.dirname(filename) }),
); ).toThrow(/Error while parsing config - /);
}); });
it("should show helpful errors for .babelrc.js", () => { it("should show helpful errors for .babelrc.js", () => {
const filename = fixture("config-files", "babelrc-js-error", "src.js"); const filename = fixture("config-files", "babelrc-js-error", "src.js");
expect(() => loadOptions({ filename })).toThrow(/Babelrc threw an error/); expect(() =>
loadOptions({ filename, cwd: path.dirname(filename) }),
).toThrow(/Babelrc threw an error/);
}); });
it("should show helpful errors for package.json", () => { it("should show helpful errors for package.json", () => {
const filename = fixture("config-files", "pkg-error", "src.js"); const filename = fixture("config-files", "pkg-error", "src.js");
expect(() => loadOptions({ filename })).toThrow( expect(() =>
/Error while parsing JSON - /, loadOptions({ filename, cwd: path.dirname(filename) }),
); ).toThrow(/Error while parsing JSON - /);
}); });
}); });
}); });

View File

@ -25,6 +25,7 @@ describe("@babel/core config loading", () => {
function makeOpts(skipProgrammatic = false) { function makeOpts(skipProgrammatic = false) {
return { return {
cwd: path.dirname(FILEPATH),
filename: FILEPATH, filename: FILEPATH,
presets: skipProgrammatic presets: skipProgrammatic
? null ? null

View File

@ -52,7 +52,9 @@ const buildTest = opts => {
let args = [binLoc]; let args = [binLoc];
args = args.concat(opts.args); args = args.concat(opts.args);
const spawn = child.spawn(process.execPath, args); const spawn = child.spawn(process.execPath, args, {
cwd: tmpLoc,
});
let stdout = ""; let stdout = "";
let stderr = ""; let stderr = "";

View File

@ -1,4 +1,5 @@
import fs from "fs"; import fs from "fs";
import path from "path";
let currentHook; let currentHook;
let currentOptions; let currentOptions;
@ -39,6 +40,11 @@ describe("@babel/register", function() {
let babelRegister; let babelRegister;
function setupRegister(config = { babelrc: false }) { function setupRegister(config = { babelrc: false }) {
config = {
cwd: path.dirname(testFile),
...config,
};
babelRegister = require(registerFile); babelRegister = require(registerFile);
babelRegister.default(config); babelRegister.default(config);
} }