diff --git a/packages/babel-cli/src/babel/index.js b/packages/babel-cli/src/babel/index.js index 00fcdfbd77..606f5b33cd 100755 --- a/packages/babel-cli/src/babel/index.js +++ b/packages/babel-cli/src/babel/index.js @@ -49,6 +49,11 @@ commander.option( collect, ); commander.option("--config-file [path]", "Path a to .babelrc file to use"); +commander.option( + "--env-name [name]", + "The name of the 'env' to use when loading configs and plugins. " + + "Defaults to the value of BABEL_ENV, or else NODE_ENV, or else 'development'.", +); // Basic file input configuration. commander.option("--source-type [script|module]", ""); diff --git a/packages/babel-core/README.md b/packages/babel-core/README.md index c014d4d77b..24262bec47 100644 --- a/packages/babel-core/README.md +++ b/packages/babel-core/README.md @@ -144,10 +144,11 @@ Following is a table of the options you can use: | `auxiliaryCommentAfter` | `null` | Attach a comment after all non-user injected code | | `auxiliaryCommentBefore` | `null` | Attach a comment before all non-user injected code | | `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) | +| `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 | | `comments` | `true` | Output comments in generated output | | `compact` | `"auto"` | Do not include superfluous whitespace characters and line terminators. When set to `"auto"` compact is set to `true` on input sizes of >500KB | -| `env` | `{}` | This is an object of keys that represent different environments. For example, you may have: `{ env: { production: { /* specific options */ } } }` which will use those options when the environment variable `BABEL_ENV` is set to `"production"`. If `BABEL_ENV` isn't set then `NODE_ENV` will be used, if it's not set then it defaults to `"development"` | +| `env` | `{}` | This is an object of keys that represent different environments. For example, you may have: `{ env: { production: { /* specific options */ } } }` which will use those options when the `envName` is `production` | | `extends` | `null` | A path to a `.babelrc` file to extend | | `filename` | `"unknown"` | Filename for use in errors etc | | `filenameRelative` | `(filename)` | Filename relative to `sourceRoot` | diff --git a/packages/babel-core/src/config/build-config-chain.js b/packages/babel-core/src/config/build-config-chain.js index 5b4b8cee24..ab253cf8dc 100644 --- a/packages/babel-core/src/config/build-config-chain.js +++ b/packages/babel-core/src/config/build-config-chain.js @@ -1,6 +1,5 @@ // @flow -import { getEnv } from "./helpers/environment"; import path from "path"; import micromatch from "micromatch"; import buildDebug from "debug"; @@ -41,20 +40,20 @@ type ConfigPart = export default function buildConfigChain( opts: ValidatedOptions, + envName: string, ): Array | null { const filename = opts.filename ? path.resolve(opts.filename) : null; const builder = new ConfigChainBuilder( filename ? new LoadedFile(filename) : null, ); - const envKey = getEnv(); try { - builder.mergeConfigArguments(opts, process.cwd(), envKey); + builder.mergeConfigArguments(opts, process.cwd(), envName); // resolve all .babelrc files if (opts.babelrc !== false && filename) { - findConfigs(path.dirname(filename)).forEach(configFile => - builder.mergeConfigFile(configFile, envKey), + findConfigs(path.dirname(filename), envName).forEach(configFile => + builder.mergeConfigFile(configFile, envName), ); } } catch (e) { @@ -85,21 +84,21 @@ class ConfigChainBuilder { ); } - mergeConfigFile(file: ConfigFile, envKey: string) { + mergeConfigFile(file: ConfigFile, envName: string) { if (this.seenFiles.has(file)) { throw new Error( `Cycle detected in Babel configuration file through "${file.filepath}".`, ); } - const parts = flattenFileOptionsParts(file)(envKey); + const parts = flattenFileOptionsParts(file)(envName); this.seenFiles.add(file); - parts.forEach(part => this._processConfigPart(part, envKey)); + parts.forEach(part => this._processConfigPart(part, envName)); this.seenFiles.delete(file); } - _processConfigPart(part: ConfigPart, envKey: string) { + _processConfigPart(part: ConfigPart, envName: string) { if (part.part === "config") { const { ignore, only } = part; @@ -116,7 +115,10 @@ class ConfigChainBuilder { this.configs.push(part.config); } else { - this.mergeConfigFile(loadConfig(part.path, part.dirname), envKey); + this.mergeConfigFile( + loadConfig(part.path, part.dirname, envName), + envName, + ); } } } @@ -129,7 +131,7 @@ class ConfigChainBuilder { function flattenArgumentsOptionsParts( opts: ValidatedOptions, dirname: string, - envKey: string, + envName: string, ): Array { const { env, @@ -142,7 +144,7 @@ function flattenArgumentsOptionsParts( const raw = []; if (env) { - raw.push(...flattenArgumentsEnvOptionsParts(env)(dirname)(envKey)); + raw.push(...flattenArgumentsEnvOptionsParts(env)(dirname)(envName)); } if (Object.keys(options).length > 0) { @@ -263,7 +265,7 @@ function flattenOptionsPartsLookup( }); } - return envKey => lookup.get(envKey) || def; + return envName => lookup.get(envName) || def; } /** diff --git a/packages/babel-core/src/config/caching.js b/packages/babel-core/src/config/caching.js index bd12bc31ac..47414fbc68 100644 --- a/packages/babel-core/src/config/caching.js +++ b/packages/babel-core/src/config/caching.js @@ -1,29 +1,33 @@ // @flow -type CacheConfigurator = CacheConfiguratorFn & CacheConfiguratorObj; +type SimpleCacheConfigurator = SimpleCacheConfiguratorFn & + SimpleCacheConfiguratorObj; -type CacheConfiguratorFn = { +type SimpleCacheConfiguratorFn = { (boolean): void, (handler: () => T): T, }; -type CacheConfiguratorObj = { +type SimpleCacheConfiguratorObj = { forever: () => void, never: () => void, using: (handler: () => T) => T, invalidate: (handler: () => T) => T, }; -type CacheEntry = Array<[ResultT, () => boolean]>; +type CacheEntry = Array< + [ResultT, (SideChannel) => boolean], +>; + +export type { CacheConfigurator }; /** * Given a function with a single argument, cache its results based on its argument and how it * configures its caching behavior. Cached values are stored strongly. */ -export function makeStrongCache( - handler: (ArgT, CacheConfigurator) => ResultT, - autoPermacache?: boolean, -): ArgT => ResultT { - return makeCachedFunction(new Map(), handler, autoPermacache); +export function makeStrongCache( + handler: (ArgT, CacheConfigurator) => ResultT, +): (ArgT, SideChannel) => ResultT { + return makeCachedFunction(new Map(), handler); } /** @@ -31,190 +35,182 @@ export function makeStrongCache( * configures its caching behavior. Cached values are stored weakly and the function argument must be * an object type. */ -export function makeWeakCache | $ReadOnlyArray<*>, ResultT>( - handler: (ArgT, CacheConfigurator) => ResultT, - autoPermacache?: boolean, -): ArgT => ResultT { - return makeCachedFunction(new WeakMap(), handler, autoPermacache); +export function makeWeakCache< + ArgT: {} | Array<*> | $ReadOnlyArray<*>, + ResultT, + SideChannel, +>( + handler: (ArgT, CacheConfigurator) => ResultT, +): (ArgT, SideChannel) => ResultT { + return makeCachedFunction(new WeakMap(), handler); } -type CacheMap = - | Map> - | WeakMap>; +type CacheMap = + | Map> + | WeakMap>; -function makeCachedFunction>( +function makeCachedFunction< + ArgT, + ResultT, + SideChannel, + Cache: CacheMap, +>( callCache: Cache, - handler: (ArgT, CacheConfigurator) => ResultT, - autoPermacache: boolean = true, -): ArgT => ResultT { - return function cachedFunction(arg) { - let cachedValue: CacheEntry | void = callCache.get(arg); + handler: (ArgT, CacheConfigurator) => ResultT, +): (ArgT, SideChannel) => ResultT { + return function cachedFunction(arg, data) { + let cachedValue: CacheEntry | void = callCache.get( + arg, + ); if (cachedValue) { for (const [value, valid] of cachedValue) { - if (valid()) return value; + if (valid(data)) return value; } } - const { cache, result, deactivate } = makeCacheConfig(); + const cache = new CacheConfigurator(data); const value = handler(arg, cache); - if (autoPermacache && !result.configured) cache.forever(); + if (!cache.configured()) cache.forever(); - deactivate(); + cache.deactivate(); - if (!result.configured) { - // eslint-disable-next-line max-len - throw new Error( - [ - "Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured", - "for various types of caching, using the first param of their handler functions:", - "", - "module.exports = function(api) {", - " // The API exposes the following:", - "", - " // Cache the returned value forever and don't call this function again.", - " api.cache(true);", - "", - " // Don't cache at all. Not recommended because it will be very slow.", - " api.cache(false);", - "", - " // Cached based on the value of some function. If this function returns a value different from", - " // a previously-encountered value, the plugins will re-evaluate.", - " var env = api.cache(() => process.env.NODE_ENV);", - "", - " // If testing for a specific env, we recommend specifics to avoid instantiating a plugin for", - " // any possible NODE_ENV value that might come up during plugin execution.", - ' var isProd = api.cache(() => process.env.NODE_ENV === "production");', - "", - " // .cache(fn) will perform a linear search though instances to find the matching plugin based", - " // based on previous instantiated plugins. If you want to recreate the plugin and discard the", - " // previous instance whenever something changes, you may use:", - ' var isProd = api.cache.invalidate(() => process.env.NODE_ENV === "production");', - "", - " // Note, we also expose the following more-verbose versions of the above examples:", - " api.cache.forever(); // api.cache(true)", - " api.cache.never(); // api.cache(false)", - " api.cache.using(fn); // api.cache(fn)", - "", - " // Return the value that will be cached.", - " return { };", - "};", - ].join("\n"), - ); - } - - if (!result.never) { - if (result.forever) { + switch (cache.mode()) { + case "forever": cachedValue = [[value, () => true]]; - } else if (result.invalidate) { - cachedValue = [[value, result.valid]]; - } else { - cachedValue = cachedValue || []; - cachedValue.push([value, result.valid]); - } - callCache.set(arg, cachedValue); + callCache.set(arg, cachedValue); + break; + case "invalidate": + cachedValue = [[value, cache.validator()]]; + callCache.set(arg, cachedValue); + break; + case "valid": + if (cachedValue) { + cachedValue.push([value, cache.validator()]); + } else { + cachedValue = [[value, cache.validator()]]; + callCache.set(arg, cachedValue); + } } return value; }; } -function makeCacheConfig(): { - cache: CacheConfigurator, - result: *, - deactivate: () => void, -} { - const pairs = []; +class CacheConfigurator { + _active: boolean = true; + _never: boolean = false; + _forever: boolean = false; + _invalidate: boolean = false; - const result = { - configured: false, - never: false, - forever: false, - invalidate: false, - valid: () => pairs.every(([key, fn]) => key === fn()), - }; + _configured: boolean = false; - let active = true; - const deactivate = () => { - active = false; - }; + _pairs: Array<[mixed, (SideChannel) => mixed]> = []; - const cache: CacheConfigurator = Object.assign( - (function cacheFn(val) { - if (typeof val === "boolean") { - if (val) cache.forever(); - else cache.never(); - return; - } + _data: SideChannel; - return cache.using(val); - }: any), - ({ - forever() { - if (!active) { - throw new Error( - "Cannot change caching after evaluation has completed.", - ); - } - if (result.never) { - throw new Error("Caching has already been configured with .never()"); - } - result.forever = true; - result.configured = true; - }, - never() { - if (!active) { - throw new Error( - "Cannot change caching after evaluation has completed.", - ); - } - if (result.forever) { - throw new Error( - "Caching has already been configured with .forever()", - ); - } - result.never = true; - result.configured = true; - }, - using(handler: () => T): T { - if (!active) { - throw new Error( - "Cannot change caching after evaluation has completed.", - ); - } - if (result.never || result.forever) { - throw new Error( - "Caching has already been configured with .never or .forever()", - ); - } - result.configured = true; + constructor(data: SideChannel) { + this._data = data; + } - const key = handler(); - pairs.push([key, handler]); - return key; - }, - invalidate(handler: () => T): T { - if (!active) { - throw new Error( - "Cannot change caching after evaluation has completed.", - ); - } - if (result.never || result.forever) { - throw new Error( - "Caching has already been configured with .never or .forever()", - ); - } - result.invalidate = true; - result.configured = true; + simple() { + return makeSimpleConfigurator(this); + } - const key = handler(); - pairs.push([key, handler]); - return key; - }, - }: CacheConfiguratorObj), - ); + mode() { + if (this._never) return "never"; + if (this._forever) return "forever"; + if (this._invalidate) return "invalidate"; + return "valid"; + } - return { cache, result, deactivate }; + forever() { + if (!this._active) { + throw new Error("Cannot change caching after evaluation has completed."); + } + if (this._never) { + throw new Error("Caching has already been configured with .never()"); + } + this._forever = true; + this._configured = true; + } + + never() { + if (!this._active) { + throw new Error("Cannot change caching after evaluation has completed."); + } + if (this._forever) { + throw new Error("Caching has already been configured with .forever()"); + } + this._never = true; + this._configured = true; + } + + using(handler: SideChannel => T): T { + if (!this._active) { + throw new Error("Cannot change caching after evaluation has completed."); + } + if (this._never || this._forever) { + throw new Error( + "Caching has already been configured with .never or .forever()", + ); + } + this._configured = true; + + const key = handler(this._data); + this._pairs.push([key, handler]); + return key; + } + + invalidate(handler: SideChannel => T): T { + if (!this._active) { + throw new Error("Cannot change caching after evaluation has completed."); + } + if (this._never || this._forever) { + throw new Error( + "Caching has already been configured with .never or .forever()", + ); + } + this._invalidate = true; + this._configured = true; + + const key = handler(this._data); + this._pairs.push([key, handler]); + return key; + } + + validator(): SideChannel => boolean { + const pairs = this._pairs; + return (data: SideChannel) => pairs.every(([key, fn]) => key === fn(data)); + } + + deactivate() { + this._active = false; + } + + configured() { + return this._configured; + } +} + +function makeSimpleConfigurator( + cache: CacheConfigurator, +): SimpleCacheConfigurator { + function cacheFn(val) { + if (typeof val === "boolean") { + if (val) cache.forever(); + else cache.never(); + return; + } + + return cache.using(val); + } + cacheFn.forever = () => cache.forever(); + cacheFn.never = () => cache.never(); + cacheFn.using = cb => cache.using(() => cb()); + cacheFn.invalidate = cb => cache.invalidate(() => cb()); + + return (cacheFn: any); } diff --git a/packages/babel-core/src/config/loading/files/configuration.js b/packages/babel-core/src/config/loading/files/configuration.js index 1c44439092..a8caa01cdc 100644 --- a/packages/babel-core/src/config/loading/files/configuration.js +++ b/packages/babel-core/src/config/loading/files/configuration.js @@ -5,8 +5,7 @@ import path from "path"; import fs from "fs"; import json5 from "json5"; import resolve from "resolve"; -import { getEnv } from "../../helpers/environment"; -import { makeStrongCache } from "../../caching"; +import { makeStrongCache, type CacheConfigurator } from "../../caching"; const debug = buildDebug("babel:config:loading:files:configuration"); @@ -21,7 +20,10 @@ const BABELRC_JS_FILENAME = ".babelrc.js"; const PACKAGE_FILENAME = "package.json"; const BABELIGNORE_FILENAME = ".babelignore"; -export function findConfigs(dirname: string): Array { +export function findConfigs( + dirname: string, + envName: string, +): Array { let foundConfig = false; let foundIgnore = false; @@ -47,7 +49,7 @@ export function findConfigs(dirname: string): Array { PACKAGE_FILENAME, ].reduce((previousConfig: ConfigFile | null, name) => { const filepath = path.join(loc, name); - const config = readConfig(filepath); + const config = readConfig(filepath, envName); if (config && previousConfig) { throw new Error( @@ -77,10 +79,14 @@ export function findConfigs(dirname: string): Array { return confs; } -export function loadConfig(name: string, dirname: string): ConfigFile { +export function loadConfig( + name: string, + dirname: string, + envName: string, +): ConfigFile { const filepath = resolve.sync(name, { basedir: dirname }); - const conf = readConfig(filepath); + const conf = readConfig(filepath, envName); if (!conf) { throw new Error(`Config file ${filepath} contains no configuration data`); } @@ -93,83 +99,86 @@ export function loadConfig(name: string, dirname: string): ConfigFile { * Read the given config file, returning the result. Returns null if no config was found, but will * throw if there are parsing errors while loading a config. */ -function readConfig(filepath) { +function readConfig(filepath, envName) { return path.extname(filepath) === ".js" - ? readConfigJS(filepath) + ? readConfigJS(filepath, { envName }) : readConfigFile(filepath); } const LOADING_CONFIGS = new Set(); -const readConfigJS = makeStrongCache((filepath, cache) => { - if (!fs.existsSync(filepath)) { - cache.forever(); - return null; - } - // The `require()` call below can make this code reentrant if a require hook like @babel/register has been - // loaded into the system. That would cause Babel to attempt to compile the `.babelrc.js` file as it loads - // below. To cover this case, we auto-ignore re-entrant config processing. - if (LOADING_CONFIGS.has(filepath)) { - cache.never(); +const readConfigJS = makeStrongCache( + (filepath, cache: CacheConfigurator<{ envName: string }>) => { + if (!fs.existsSync(filepath)) { + cache.forever(); + return null; + } + + // The `require()` call below can make this code reentrant if a require hook like @babel/register has been + // loaded into the system. That would cause Babel to attempt to compile the `.babelrc.js` file as it loads + // below. To cover this case, we auto-ignore re-entrant config processing. + if (LOADING_CONFIGS.has(filepath)) { + cache.never(); + + debug("Auto-ignoring usage of config %o.", filepath); + return { + filepath, + dirname: path.dirname(filepath), + options: {}, + }; + } + + let options; + try { + LOADING_CONFIGS.add(filepath); + + // $FlowIssue + const configModule = (require(filepath): mixed); + options = + configModule && configModule.__esModule + ? configModule.default || undefined + : configModule; + } catch (err) { + err.message = `${filepath}: Error while loading config - ${err.message}`; + throw err; + } finally { + LOADING_CONFIGS.delete(filepath); + } + + if (typeof options === "function") { + options = options({ + cache: cache.simple(), + // Expose ".env()" so people can easily get the same env that we expose using the "env" key. + env: () => cache.using(data => data.envName), + async: () => false, + }); + + if (!cache.configured()) throwConfigError(); + } + + if (!options || typeof options !== "object" || Array.isArray(options)) { + throw new Error( + `${filepath}: Configuration should be an exported JavaScript object.`, + ); + } + + if (typeof options.then === "function") { + throw new Error( + `You appear to be using an async configuration, ` + + `which your current version of Babel does not support. ` + + `We may add support for this in the future, ` + + `but if you're on the most recent version of @babel/core and still ` + + `seeing this error, then you'll need to synchronously return your config.`, + ); + } - debug("Auto-ignoring usage of config %o.", filepath); return { filepath, dirname: path.dirname(filepath), - options: {}, + options, }; - } - - let options; - try { - LOADING_CONFIGS.add(filepath); - - // $FlowIssue - const configModule = (require(filepath): mixed); - options = - configModule && configModule.__esModule - ? configModule.default || undefined - : configModule; - } catch (err) { - err.message = `${filepath}: Error while loading config - ${err.message}`; - throw err; - } finally { - LOADING_CONFIGS.delete(filepath); - } - - if (typeof options === "function") { - options = options({ - cache, - // Expose ".env()" so people can easily get the same env that we expose using the "env" key. - env: () => cache.using(() => getEnv()), - async: () => false, - }); - } else { - cache.forever(); - } - - if (!options || typeof options !== "object" || Array.isArray(options)) { - throw new Error( - `${filepath}: Configuration should be an exported JavaScript object.`, - ); - } - - if (typeof options.then === "function") { - throw new Error( - `You appear to be using an async configuration, ` + - `which your current version of Babel does not support. ` + - `We may add support for this in the future, ` + - `but if you're on the most recent version of @babel/core and still ` + - `seeing this error, then you'll need to synchronously return your config.`, - ); - } - - return { - filepath, - dirname: path.dirname(filepath), - options, - }; -}, false /* autoPermacache */); + }, +); const readConfigFile = makeStaticFileCache((filepath, content) => { let options; @@ -239,3 +248,40 @@ function fileMtime(filepath: string): number | null { return null; } + +function throwConfigError() { + throw new Error(`\ +Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured +for various types of caching, using the first param of their handler functions: + +module.exports = function(api) { + // The API exposes the following: + + // Cache the returned value forever and don't call this function again. + api.cache(true); + + // Don't cache at all. Not recommended because it will be very slow. + api.cache(false); + + // Cached based on the value of some function. If this function returns a value different from + // a previously-encountered value, the plugins will re-evaluate. + var env = api.cache(() => process.env.NODE_ENV); + + // If testing for a specific env, we recommend specifics to avoid instantiating a plugin for + // any possible NODE_ENV value that might come up during plugin execution. + var isProd = api.cache(() => process.env.NODE_ENV === "production"); + + // .cache(fn) will perform a linear search though instances to find the matching plugin based + // based on previous instantiated plugins. If you want to recreate the plugin and discard the + // previous instance whenever something changes, you may use: + var isProd = api.cache.invalidate(() => process.env.NODE_ENV === "production"); + + // Note, we also expose the following more-verbose versions of the above examples: + api.cache.forever(); // api.cache(true) + api.cache.never(); // api.cache(false) + api.cache.using(fn); // api.cache(fn) + + // Return the value that will be cached. + return { }; +};`); +} diff --git a/packages/babel-core/src/config/option-manager.js b/packages/babel-core/src/config/option-manager.js index b9ea81c796..d7c7c958c5 100644 --- a/packages/babel-core/src/config/option-manager.js +++ b/packages/babel-core/src/config/option-manager.js @@ -6,7 +6,7 @@ import merge from "lodash/merge"; import buildConfigChain, { type ConfigItem } from "./build-config-chain"; import traverse from "@babel/traverse"; import clone from "lodash/clone"; -import { makeWeakCache } from "./caching"; +import { makeWeakCache, type CacheConfigurator } from "./caching"; import { getEnv } from "./helpers/environment"; import { validate, type ValidatedOptions, type PluginItem } from "./options"; @@ -46,14 +46,14 @@ class OptionManager { * - `dirname` is used to resolve plugins relative to it. */ - mergeOptions(config: MergeOptions, pass?: Array) { + mergeOptions(config: MergeOptions, pass?: Array, envName: string) { const result = loadConfig(config); const plugins = result.plugins.map(descriptor => - loadPluginDescriptor(descriptor), + loadPluginDescriptor(descriptor, envName), ); const presets = result.presets.map(descriptor => - loadPresetDescriptor(descriptor), + loadPresetDescriptor(descriptor, envName), ); const passPerPreset = config.options.passPerPreset; @@ -70,7 +70,11 @@ class OptionManager { } presets.forEach((presetConfig, i) => { - this.mergeOptions(presetConfig, presetPasses ? presetPasses[i] : pass); + this.mergeOptions( + presetConfig, + presetPasses ? presetPasses[i] : pass, + envName, + ); }); } @@ -99,12 +103,14 @@ class OptionManager { init(inputOpts: {}) { const args = validate("arguments", inputOpts); - const configChain = buildConfigChain(args); + const { envName = getEnv() } = args; + + const configChain = buildConfigChain(args, envName); if (!configChain) return null; try { for (const config of configChain) { - this.mergeOptions(config); + this.mergeOptions(config, undefined, envName); } } catch (e) { // There are a few case where thrown errors will try to annotate themselves multiple times, so @@ -127,6 +133,7 @@ class OptionManager { .filter(plugins => plugins.length > 0) .map(plugins => ({ plugins })); opts.passPerPreset = opts.presets.length > 0; + opts.envName = envName; return { options: opts, @@ -182,13 +189,13 @@ const loadConfig = makeWeakCache((config: MergeOptions): { const loadDescriptor = makeWeakCache( ( { value, options = {}, dirname, alias }: BasicDescriptor, - cache, + cache: CacheConfigurator<{ envName: string }>, ): LoadedDescriptor => { let item = value; if (typeof value === "function") { const api = Object.assign(Object.create(context), { - cache, - env: () => cache.using(() => getEnv()), + cache: cache.simple(), + env: () => cache.using(data => data.envName), async: () => false, }); @@ -222,7 +229,10 @@ const loadDescriptor = makeWeakCache( /** * Instantiate a plugin for the given descriptor, returning the plugin/options pair. */ -function loadPluginDescriptor(descriptor: BasicDescriptor): Plugin { +function loadPluginDescriptor( + descriptor: BasicDescriptor, + envName: string, +): Plugin { if (descriptor.value instanceof Plugin) { if (descriptor.options) { throw new Error( @@ -233,11 +243,16 @@ function loadPluginDescriptor(descriptor: BasicDescriptor): Plugin { return descriptor.value; } - return instantiatePlugin(loadDescriptor(descriptor)); + return instantiatePlugin(loadDescriptor(descriptor, { envName }), { + envName, + }); } const instantiatePlugin = makeWeakCache( - ({ value, options, dirname, alias }: LoadedDescriptor, cache): Plugin => { + ( + { value, options, dirname, alias }: LoadedDescriptor, + cache: CacheConfigurator<{ envName: string }>, + ): Plugin => { const pluginObj = validatePluginObject(value); const plugin = Object.assign({}, pluginObj); @@ -254,8 +269,8 @@ const instantiatePlugin = makeWeakCache( }; // If the inherited plugin changes, reinstantiate this plugin. - const inherits = cache.invalidate(() => - loadPluginDescriptor(inheritsDescriptor), + const inherits = cache.invalidate(data => + loadPluginDescriptor(inheritsDescriptor, data.envName), ); plugin.pre = chain(inherits.pre, plugin.pre); @@ -277,8 +292,11 @@ const instantiatePlugin = makeWeakCache( /** * Generate a config object that will act as the root of a new nested config. */ -const loadPresetDescriptor = (descriptor: BasicDescriptor): MergeOptions => { - return instantiatePreset(loadDescriptor(descriptor)); +const loadPresetDescriptor = ( + descriptor: BasicDescriptor, + envName: string, +): MergeOptions => { + return instantiatePreset(loadDescriptor(descriptor, { envName })); }; const instantiatePreset = makeWeakCache( diff --git a/packages/babel-core/src/config/options.js b/packages/babel-core/src/config/options.js index aa915cc94c..5ca278b14b 100644 --- a/packages/babel-core/src/config/options.js +++ b/packages/babel-core/src/config/options.js @@ -28,6 +28,10 @@ const ROOT_VALIDATORS: ValidatorSet = { >), code: (assertBoolean: Validator<$PropertyType>), ast: (assertBoolean: Validator<$PropertyType>), + + envName: (assertString: Validator< + $PropertyType, + >), }; const NONPRESET_VALIDATORS: ValidatorSet = { @@ -130,6 +134,7 @@ export type ValidatedOptions = { code?: boolean, ast?: boolean, inputSourceMap?: RootInputSourceMapOption, + envName?: string, extends?: string, env?: EnvSet, diff --git a/packages/babel-core/test/caching-api.js b/packages/babel-core/test/caching-api.js index d846fd85bb..9daee26fdc 100644 --- a/packages/babel-core/test/caching-api.js +++ b/packages/babel-core/test/caching-api.js @@ -19,23 +19,6 @@ describe("caching API", () => { assert.notEqual(fn("one"), fn("two")); }); - it("should allow permacaching with cache(true)", () => { - let count = 0; - - const fn = makeStrongCache((arg, cache) => { - cache(true); - return { arg, count: count++ }; - }); - - assert.deepEqual(fn("one"), { arg: "one", count: 0 }); - assert.equal(fn("one"), fn("one")); - - assert.deepEqual(fn("two"), { arg: "two", count: 1 }); - assert.equal(fn("two"), fn("two")); - - assert.notEqual(fn("one"), fn("two")); - }); - it("should allow disabling caching with .never()", () => { let count = 0; @@ -55,25 +38,6 @@ describe("caching API", () => { assert.notEqual(fn("one"), fn("two")); }); - it("should allow disabling caching with cache(false)", () => { - let count = 0; - - const fn = makeStrongCache((arg, cache) => { - cache(false); - return { arg, count: count++ }; - }); - - assert.deepEqual(fn("one"), { arg: "one", count: 0 }); - assert.deepEqual(fn("one"), { arg: "one", count: 1 }); - assert.notEqual(fn("one"), fn("one")); - - assert.deepEqual(fn("two"), { arg: "two", count: 4 }); - assert.deepEqual(fn("two"), { arg: "two", count: 5 }); - assert.notEqual(fn("two"), fn("two")); - - assert.notEqual(fn("one"), fn("two")); - }); - it("should allow caching based on a value with .using(fn)", () => { let count = 0; let other = "default"; @@ -115,47 +79,6 @@ describe("caching API", () => { assert.equal(fn("two"), fn("two")); }); - it("should allow caching based on a value with cache(fn)", () => { - let count = 0; - let other = "default"; - - const fn = makeStrongCache((arg, cache) => { - const val = cache(() => other); - - return { arg, val, count: count++ }; - }); - - assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 }); - assert.equal(fn("one"), fn("one")); - - assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 }); - assert.equal(fn("two"), fn("two")); - - other = "new"; - - assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 }); - assert.equal(fn("one"), fn("one")); - - assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 }); - assert.equal(fn("two"), fn("two")); - - other = "default"; - - assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 }); - assert.equal(fn("one"), fn("one")); - - assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 }); - assert.equal(fn("two"), fn("two")); - - other = "new"; - - assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 }); - assert.equal(fn("one"), fn("one")); - - assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 }); - assert.equal(fn("two"), fn("two")); - }); - it("should allow invalidation based on a value with .invalidate(fn)", () => { let count = 0; let other = "default"; @@ -298,12 +221,6 @@ describe("caching API", () => { assert.equal(fn("two"), fn("two")); }); - it("should throw if caching is never configured and not defaulting", () => { - const fn = makeStrongCache(() => {}, false /* autoPermacache */); - - assert.throws(() => fn(), /Error: Caching was left unconfigured./); - }); - it("should auto-permacache by default", () => { let count = 0; @@ -410,4 +327,89 @@ describe("caching API", () => { /Cannot change caching after evaluation/, ); }); + + describe("simple", () => { + it("should allow permacaching with cache(true)", () => { + let count = 0; + + const fn = makeStrongCache((arg, cache) => { + cache = cache.simple(); + + cache(true); + return { arg, count: count++ }; + }); + + assert.deepEqual(fn("one"), { arg: "one", count: 0 }); + assert.equal(fn("one"), fn("one")); + + assert.deepEqual(fn("two"), { arg: "two", count: 1 }); + assert.equal(fn("two"), fn("two")); + + assert.notEqual(fn("one"), fn("two")); + }); + + it("should allow disabling caching with cache(false)", () => { + let count = 0; + + const fn = makeStrongCache((arg, cache) => { + cache = cache.simple(); + + cache(false); + return { arg, count: count++ }; + }); + + assert.deepEqual(fn("one"), { arg: "one", count: 0 }); + assert.deepEqual(fn("one"), { arg: "one", count: 1 }); + assert.notEqual(fn("one"), fn("one")); + + assert.deepEqual(fn("two"), { arg: "two", count: 4 }); + assert.deepEqual(fn("two"), { arg: "two", count: 5 }); + assert.notEqual(fn("two"), fn("two")); + + assert.notEqual(fn("one"), fn("two")); + }); + + it("should allow caching based on a value with cache(fn)", () => { + let count = 0; + let other = "default"; + + const fn = makeStrongCache((arg, cache) => { + cache = cache.simple(); + + const val = cache(() => other); + + return { arg, val, count: count++ }; + }); + + assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 }); + assert.equal(fn("one"), fn("one")); + + assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 }); + assert.equal(fn("two"), fn("two")); + + other = "new"; + + assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 }); + assert.equal(fn("one"), fn("one")); + + assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 }); + assert.equal(fn("two"), fn("two")); + + other = "default"; + + assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 }); + assert.equal(fn("one"), fn("one")); + + assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 }); + assert.equal(fn("two"), fn("two")); + + other = "new"; + + assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 }); + assert.equal(fn("one"), fn("one")); + + assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 }); + assert.equal(fn("two"), fn("two")); + }); + }); }); diff --git a/packages/babel-core/test/config-chain.js b/packages/babel-core/test/config-chain.js index 097112cb07..d4bb482212 100644 --- a/packages/babel-core/test/config-chain.js +++ b/packages/babel-core/test/config-chain.js @@ -3,6 +3,8 @@ import fs from "fs"; import path from "path"; import buildConfigChain from "../lib/config/build-config-chain"; +const DEFAULT_ENV = "development"; + function fixture() { const args = [__dirname, "fixtures", "config"]; for (let i = 0; i < arguments.length; i++) { @@ -16,49 +18,39 @@ function base() { } describe("buildConfigChain", function() { - let oldBabelEnv; - let oldNodeEnv; - - beforeEach(function() { - oldBabelEnv = process.env.BABEL_ENV; - oldNodeEnv = process.env.NODE_ENV; - - delete process.env.BABEL_ENV; - delete process.env.NODE_ENV; - }); - - afterEach(function() { - process.env.BABEL_ENV = oldBabelEnv; - process.env.NODE_ENV = oldNodeEnv; - }); - describe("ignore", () => { it("should ignore files that match", () => { - const chain = buildConfigChain({ - filename: fixture("nonexistant-fake", "src.js"), - babelrc: false, - ignore: [ - fixture("nonexistant-fake", "src.js"), + const chain = buildConfigChain( + { + filename: fixture("nonexistant-fake", "src.js"), + babelrc: false, + ignore: [ + fixture("nonexistant-fake", "src.js"), - // We had a regression where multiple ignore patterns broke things, so - // we keep some extra random items in here. - fixture("nonexistant-fake", "other.js"), - fixture("nonexistant-fake", "misc.js"), - ], - }); + // We had a regression where multiple ignore patterns broke things, so + // we keep some extra random items in here. + fixture("nonexistant-fake", "other.js"), + fixture("nonexistant-fake", "misc.js"), + ], + }, + DEFAULT_ENV, + ); assert.equal(chain, null); }); it("should not ignore files that don't match", () => { - const chain = buildConfigChain({ - filename: fixture("nonexistant-fake", "src.js"), - babelrc: false, - ignore: [ - fixture("nonexistant-fake", "other.js"), - fixture("nonexistant-fake", "misc.js"), - ], - }); + const chain = buildConfigChain( + { + filename: fixture("nonexistant-fake", "src.js"), + babelrc: false, + ignore: [ + fixture("nonexistant-fake", "other.js"), + fixture("nonexistant-fake", "misc.js"), + ], + }, + DEFAULT_ENV, + ); const expected = [ { @@ -82,27 +74,33 @@ describe("buildConfigChain", function() { describe("only", () => { it("should ignore files that don't match", () => { - const chain = buildConfigChain({ - filename: fixture("nonexistant-fake", "src.js"), - babelrc: false, - only: [ - fixture("nonexistant-fake", "other.js"), - fixture("nonexistant-fake", "misc.js"), - ], - }); + const chain = buildConfigChain( + { + filename: fixture("nonexistant-fake", "src.js"), + babelrc: false, + only: [ + fixture("nonexistant-fake", "other.js"), + fixture("nonexistant-fake", "misc.js"), + ], + }, + DEFAULT_ENV, + ); assert.equal(chain, null); }); it("should not ignore files that match", () => { - const chain = buildConfigChain({ - filename: fixture("nonexistant-fake", "src.js"), - babelrc: false, - only: [ - fixture("nonexistant-fake", "src.js"), - fixture("nonexistant-fake", "misc.js"), - ], - }); + const chain = buildConfigChain( + { + filename: fixture("nonexistant-fake", "src.js"), + babelrc: false, + only: [ + fixture("nonexistant-fake", "src.js"), + fixture("nonexistant-fake", "misc.js"), + ], + }, + DEFAULT_ENV, + ); const expected = [ { @@ -126,12 +124,15 @@ describe("buildConfigChain", function() { describe("ignore/only", () => { it("should ignore files that match ignore and don't match only", () => { - const chain = buildConfigChain({ - filename: fixture("nonexistant-fake", "src.js"), - babelrc: false, - ignore: [fixture("nonexistant-fake", "src.js")], - only: [fixture("nonexistant-fake", "src.js")], - }); + const chain = buildConfigChain( + { + filename: fixture("nonexistant-fake", "src.js"), + babelrc: false, + ignore: [fixture("nonexistant-fake", "src.js")], + only: [fixture("nonexistant-fake", "src.js")], + }, + DEFAULT_ENV, + ); assert.equal(chain, null); }); @@ -142,8 +143,8 @@ describe("buildConfigChain", function() { it("should not cache the input options by identity", () => { const comments = false; - const chain1 = buildConfigChain({ comments }); - const chain2 = buildConfigChain({ comments }); + const chain1 = buildConfigChain({ comments }, DEFAULT_ENV); + const chain2 = buildConfigChain({ comments }, DEFAULT_ENV); assert.equal(chain1.length, 1); assert.equal(chain2.length, 1); @@ -151,15 +152,14 @@ describe("buildConfigChain", function() { }); it("should cache the env options by identity", () => { - process.env.NODE_ENV = "foo"; const env = { foo: { comments: false, }, }; - const chain1 = buildConfigChain({ env }); - const chain2 = buildConfigChain({ env }); + const chain1 = buildConfigChain({ env }, "foo"); + const chain2 = buildConfigChain({ env }, "foo"); assert.equal(chain1.length, 2); assert.equal(chain2.length, 2); @@ -170,8 +170,8 @@ describe("buildConfigChain", function() { it("should cache the plugin options by identity", () => { const plugins = []; - const chain1 = buildConfigChain({ plugins }); - const chain2 = buildConfigChain({ plugins }); + const chain1 = buildConfigChain({ plugins }, DEFAULT_ENV); + const chain2 = buildConfigChain({ plugins }, DEFAULT_ENV); assert.equal(chain1.length, 1); assert.equal(chain2.length, 1); @@ -181,8 +181,8 @@ describe("buildConfigChain", function() { it("should cache the presets options by identity", () => { const presets = []; - const chain1 = buildConfigChain({ presets }); - const chain2 = buildConfigChain({ presets }); + const chain1 = buildConfigChain({ presets }, DEFAULT_ENV); + const chain2 = buildConfigChain({ presets }, DEFAULT_ENV); assert.equal(chain1.length, 1); assert.equal(chain2.length, 1); @@ -192,9 +192,15 @@ describe("buildConfigChain", function() { it("should not cache the presets options with passPerPreset", () => { const presets = []; - const chain1 = buildConfigChain({ presets }); - const chain2 = buildConfigChain({ presets, passPerPreset: true }); - const chain3 = buildConfigChain({ presets, passPerPreset: false }); + const chain1 = buildConfigChain({ presets }, DEFAULT_ENV); + const chain2 = buildConfigChain( + { presets, passPerPreset: true }, + DEFAULT_ENV, + ); + const chain3 = buildConfigChain( + { presets, passPerPreset: false }, + DEFAULT_ENV, + ); assert.equal(chain1.length, 1); assert.equal(chain2.length, 1); @@ -229,13 +235,13 @@ describe("buildConfigChain", function() { "package.json", ); - const chain1 = buildConfigChain({ filename }); - const chain2 = buildConfigChain({ filename }); + const chain1 = buildConfigChain({ filename }, DEFAULT_ENV); + const chain2 = buildConfigChain({ filename }, DEFAULT_ENV); touch(pkgJSON); - const chain3 = buildConfigChain({ filename }); - const chain4 = buildConfigChain({ filename }); + const chain3 = buildConfigChain({ filename }, DEFAULT_ENV); + const chain4 = buildConfigChain({ filename }, DEFAULT_ENV); assert.equal(chain1.length, 3); assert.equal(chain2.length, 3); @@ -266,13 +272,13 @@ describe("buildConfigChain", function() { ".babelrc", ); - const chain1 = buildConfigChain({ filename }); - const chain2 = buildConfigChain({ filename }); + const chain1 = buildConfigChain({ filename }, DEFAULT_ENV); + const chain2 = buildConfigChain({ filename }, DEFAULT_ENV); touch(babelrcFile); - const chain3 = buildConfigChain({ filename }); - const chain4 = buildConfigChain({ filename }); + const chain3 = buildConfigChain({ filename }, DEFAULT_ENV); + const chain4 = buildConfigChain({ filename }, DEFAULT_ENV); assert.equal(chain1.length, 3); assert.equal(chain2.length, 3); @@ -303,13 +309,13 @@ describe("buildConfigChain", function() { ".babelignore", ); - const chain1 = buildConfigChain({ filename }); - const chain2 = buildConfigChain({ filename }); + const chain1 = buildConfigChain({ filename }, DEFAULT_ENV); + const chain2 = buildConfigChain({ filename }, DEFAULT_ENV); touch(babelignoreFile); - const chain3 = buildConfigChain({ filename }); - const chain4 = buildConfigChain({ filename }); + const chain3 = buildConfigChain({ filename }, DEFAULT_ENV); + const chain4 = buildConfigChain({ filename }, DEFAULT_ENV); assert.equal(chain1.length, 6); assert.equal(chain2.length, 6); @@ -340,13 +346,11 @@ describe("buildConfigChain", function() { ".babelrc.js", ); - const chain1 = buildConfigChain({ filename }); - const chain2 = buildConfigChain({ filename }); + const chain1 = buildConfigChain({ filename }, DEFAULT_ENV); + const chain2 = buildConfigChain({ filename }, DEFAULT_ENV); - process.env.NODE_ENV = "new-env"; - - const chain3 = buildConfigChain({ filename }); - const chain4 = buildConfigChain({ filename }); + const chain3 = buildConfigChain({ filename }, "new-env"); + const chain4 = buildConfigChain({ filename }, "new-env"); assert.equal(chain1.length, 3); assert.equal(chain2.length, 3); @@ -358,7 +362,7 @@ describe("buildConfigChain", function() { assert.equal(chain4[1].alias, babelrcFile); assert.strictEqual(chain1[1], chain2[1]); - // Identity changed after changing the NODE_ENV. + // Identity changed after changing the envName. assert.notStrictEqual(chain3[1], chain1[1]); assert.strictEqual(chain3[1], chain4[1]); }); @@ -366,9 +370,12 @@ describe("buildConfigChain", function() { }); it("dir1", function() { - const chain = buildConfigChain({ - filename: fixture("dir1", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("dir1", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -410,9 +417,12 @@ describe("buildConfigChain", function() { }); it("dir2", function() { - const chain = buildConfigChain({ - filename: fixture("dir2", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("dir2", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -445,9 +455,12 @@ describe("buildConfigChain", function() { }); it("dir3", function() { - const chain = buildConfigChain({ - filename: fixture("dir3", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("dir3", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -489,9 +502,12 @@ describe("buildConfigChain", function() { }); it("env - base", function() { - const chain = buildConfigChain({ - filename: fixture("env", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("env", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -532,11 +548,12 @@ describe("buildConfigChain", function() { }); it("env - foo", function() { - process.env.NODE_ENV = "foo"; - - const chain = buildConfigChain({ - filename: fixture("env", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("env", "src.js"), + }, + "foo", + ); const expected = [ { @@ -585,12 +602,12 @@ describe("buildConfigChain", function() { }); it("env - bar", function() { - process.env.NODE_ENV = "foo"; // overridden - process.env.NODE_ENV = "bar"; - - const chain = buildConfigChain({ - filename: fixture("env", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("env", "src.js"), + }, + "bar", + ); const expected = [ { @@ -639,11 +656,12 @@ describe("buildConfigChain", function() { }); it("env - foo", function() { - process.env.NODE_ENV = "foo"; - - const chain = buildConfigChain({ - filename: fixture("pkg", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("pkg", "src.js"), + }, + "foo", + ); const expected = [ { @@ -676,9 +694,12 @@ describe("buildConfigChain", function() { }); it("js-config", function() { - const chain = buildConfigChain({ - filename: fixture("js-config", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("js-config", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -711,9 +732,12 @@ describe("buildConfigChain", function() { }); it("js-config-function", function() { - const chain = buildConfigChain({ - filename: fixture("js-config-function", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("js-config-function", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -746,9 +770,12 @@ describe("buildConfigChain", function() { }); it("js-config-default - should read transpiled export default", function() { - const chain = buildConfigChain({ - filename: fixture("js-config-default", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("js-config-default", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -780,9 +807,12 @@ describe("buildConfigChain", function() { assert.deepEqual(chain, expected); }); it("js-config-extended", function() { - const chain = buildConfigChain({ - filename: fixture("js-config-extended", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("js-config-extended", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -827,9 +857,12 @@ describe("buildConfigChain", function() { "json-pkg-config-no-babel - should not throw if" + " package.json doesn't contain a `babel` field", function() { - const chain = buildConfigChain({ - filename: fixture("json-pkg-config-no-babel", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("json-pkg-config-no-babel", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -863,9 +896,12 @@ describe("buildConfigChain", function() { ); it("should not ignore file matching negated file pattern", function() { - const chain = buildConfigChain({ - filename: fixture("ignore-negate", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("ignore-negate", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -896,17 +932,23 @@ describe("buildConfigChain", function() { assert.deepEqual(chain, expected); - const chain2 = buildConfigChain({ - filename: fixture("ignore-negate", "src2.js"), - }); + const chain2 = buildConfigChain( + { + filename: fixture("ignore-negate", "src2.js"), + }, + DEFAULT_ENV, + ); assert.equal(chain2, null); }); it("should not ignore file matching negated folder pattern", function() { - const chain = buildConfigChain({ - filename: fixture("ignore-negate-folder", "folder", "src.js"), - }); + const chain = buildConfigChain( + { + filename: fixture("ignore-negate-folder", "folder", "src.js"), + }, + DEFAULT_ENV, + ); const expected = [ { @@ -937,9 +979,12 @@ describe("buildConfigChain", function() { assert.deepEqual(chain, expected); - const chain2 = buildConfigChain({ - filename: fixture("ignore-negate-folder", "src2.js"), - }); + const chain2 = buildConfigChain( + { + filename: fixture("ignore-negate-folder", "src2.js"), + }, + DEFAULT_ENV, + ); assert.equal(chain2, null); }); @@ -949,9 +994,12 @@ describe("buildConfigChain", function() { " and a .babelrc.js are present", function() { assert.throws(function() { - buildConfigChain({ - filename: fixture("js-json-config", "src.js"), - }); + buildConfigChain( + { + filename: fixture("js-json-config", "src.js"), + }, + DEFAULT_ENV, + ); }, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/); }, ); @@ -961,9 +1009,12 @@ describe("buildConfigChain", function() { " and a package.json with a babel field are present", function() { assert.throws(function() { - buildConfigChain({ - filename: fixture("js-pkg-config", "src.js"), - }); + buildConfigChain( + { + filename: fixture("js-pkg-config", "src.js"), + }, + DEFAULT_ENV, + ); }, /Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/); }, ); @@ -973,42 +1024,57 @@ describe("buildConfigChain", function() { " and a package.json with a babel field are present", function() { assert.throws(function() { - buildConfigChain({ - filename: fixture("json-pkg-config", "src.js"), - }); + buildConfigChain( + { + filename: fixture("json-pkg-config", "src.js"), + }, + DEFAULT_ENV, + ); }, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/); }, ); it("js-config-error", function() { assert.throws(function() { - buildConfigChain({ - filename: fixture("js-config-error", "src.js"), - }); + buildConfigChain( + { + filename: fixture("js-config-error", "src.js"), + }, + DEFAULT_ENV, + ); }, /Error while loading config/); }); it("js-config-error2", function() { assert.throws(function() { - buildConfigChain({ - filename: fixture("js-config-error2", "src.js"), - }); + buildConfigChain( + { + filename: fixture("js-config-error2", "src.js"), + }, + DEFAULT_ENV, + ); }, /Configuration should be an exported JavaScript object/); }); it("js-config-error3", function() { assert.throws(function() { - buildConfigChain({ - filename: fixture("js-config-error3", "src.js"), - }); + buildConfigChain( + { + filename: fixture("js-config-error3", "src.js"), + }, + DEFAULT_ENV, + ); }, /Configuration should be an exported JavaScript object/); }); it("json-config-error", function() { assert.throws(function() { - buildConfigChain({ - filename: fixture("json-config-error", "src.js"), - }); + buildConfigChain( + { + filename: fixture("json-config-error", "src.js"), + }, + DEFAULT_ENV, + ); }, /Error while parsing config/); }); });