Merge pull request #6834 from loganfsmyth/caching-refactor
Expose `envName` as a top-level Babel option to avoid using environmental variables
This commit is contained in:
commit
a89171910f
@ -49,6 +49,11 @@ commander.option(
|
|||||||
collect,
|
collect,
|
||||||
);
|
);
|
||||||
commander.option("--config-file [path]", "Path a to .babelrc file to use");
|
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.
|
// Basic file input configuration.
|
||||||
commander.option("--source-type [script|module]", "");
|
commander.option("--source-type [script|module]", "");
|
||||||
|
|||||||
@ -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 |
|
| `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 |
|
||||||
| `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) |
|
||||||
|
| `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 |
|
||||||
| `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 |
|
| `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 |
|
| `extends` | `null` | A path to a `.babelrc` file to extend |
|
||||||
| `filename` | `"unknown"` | Filename for use in errors etc |
|
| `filename` | `"unknown"` | Filename for use in errors etc |
|
||||||
| `filenameRelative` | `(filename)` | Filename relative to `sourceRoot` |
|
| `filenameRelative` | `(filename)` | Filename relative to `sourceRoot` |
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import { getEnv } from "./helpers/environment";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import micromatch from "micromatch";
|
import micromatch from "micromatch";
|
||||||
import buildDebug from "debug";
|
import buildDebug from "debug";
|
||||||
@ -41,20 +40,20 @@ type ConfigPart =
|
|||||||
|
|
||||||
export default function buildConfigChain(
|
export default function buildConfigChain(
|
||||||
opts: ValidatedOptions,
|
opts: ValidatedOptions,
|
||||||
|
envName: string,
|
||||||
): Array<ConfigItem> | null {
|
): Array<ConfigItem> | null {
|
||||||
const filename = opts.filename ? path.resolve(opts.filename) : null;
|
const filename = opts.filename ? path.resolve(opts.filename) : null;
|
||||||
const builder = new ConfigChainBuilder(
|
const builder = new ConfigChainBuilder(
|
||||||
filename ? new LoadedFile(filename) : null,
|
filename ? new LoadedFile(filename) : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const envKey = getEnv();
|
|
||||||
try {
|
try {
|
||||||
builder.mergeConfigArguments(opts, process.cwd(), envKey);
|
builder.mergeConfigArguments(opts, process.cwd(), envName);
|
||||||
|
|
||||||
// resolve all .babelrc files
|
// resolve all .babelrc files
|
||||||
if (opts.babelrc !== false && filename) {
|
if (opts.babelrc !== false && filename) {
|
||||||
findConfigs(path.dirname(filename)).forEach(configFile =>
|
findConfigs(path.dirname(filename), envName).forEach(configFile =>
|
||||||
builder.mergeConfigFile(configFile, envKey),
|
builder.mergeConfigFile(configFile, envName),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -85,21 +84,21 @@ class ConfigChainBuilder {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeConfigFile(file: ConfigFile, envKey: string) {
|
mergeConfigFile(file: ConfigFile, envName: string) {
|
||||||
if (this.seenFiles.has(file)) {
|
if (this.seenFiles.has(file)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cycle detected in Babel configuration file through "${file.filepath}".`,
|
`Cycle detected in Babel configuration file through "${file.filepath}".`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parts = flattenFileOptionsParts(file)(envKey);
|
const parts = flattenFileOptionsParts(file)(envName);
|
||||||
|
|
||||||
this.seenFiles.add(file);
|
this.seenFiles.add(file);
|
||||||
parts.forEach(part => this._processConfigPart(part, envKey));
|
parts.forEach(part => this._processConfigPart(part, envName));
|
||||||
this.seenFiles.delete(file);
|
this.seenFiles.delete(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
_processConfigPart(part: ConfigPart, envKey: string) {
|
_processConfigPart(part: ConfigPart, envName: string) {
|
||||||
if (part.part === "config") {
|
if (part.part === "config") {
|
||||||
const { ignore, only } = part;
|
const { ignore, only } = part;
|
||||||
|
|
||||||
@ -116,7 +115,10 @@ class ConfigChainBuilder {
|
|||||||
|
|
||||||
this.configs.push(part.config);
|
this.configs.push(part.config);
|
||||||
} else {
|
} 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(
|
function flattenArgumentsOptionsParts(
|
||||||
opts: ValidatedOptions,
|
opts: ValidatedOptions,
|
||||||
dirname: string,
|
dirname: string,
|
||||||
envKey: string,
|
envName: string,
|
||||||
): Array<ConfigPart> {
|
): Array<ConfigPart> {
|
||||||
const {
|
const {
|
||||||
env,
|
env,
|
||||||
@ -142,7 +144,7 @@ function flattenArgumentsOptionsParts(
|
|||||||
|
|
||||||
const raw = [];
|
const raw = [];
|
||||||
if (env) {
|
if (env) {
|
||||||
raw.push(...flattenArgumentsEnvOptionsParts(env)(dirname)(envKey));
|
raw.push(...flattenArgumentsEnvOptionsParts(env)(dirname)(envName));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(options).length > 0) {
|
if (Object.keys(options).length > 0) {
|
||||||
@ -263,7 +265,7 @@ function flattenOptionsPartsLookup(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return envKey => lookup.get(envKey) || def;
|
return envName => lookup.get(envName) || def;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,29 +1,33 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
type CacheConfigurator = CacheConfiguratorFn & CacheConfiguratorObj;
|
type SimpleCacheConfigurator = SimpleCacheConfiguratorFn &
|
||||||
|
SimpleCacheConfiguratorObj;
|
||||||
|
|
||||||
type CacheConfiguratorFn = {
|
type SimpleCacheConfiguratorFn = {
|
||||||
(boolean): void,
|
(boolean): void,
|
||||||
<T>(handler: () => T): T,
|
<T>(handler: () => T): T,
|
||||||
};
|
};
|
||||||
type CacheConfiguratorObj = {
|
type SimpleCacheConfiguratorObj = {
|
||||||
forever: () => void,
|
forever: () => void,
|
||||||
never: () => void,
|
never: () => void,
|
||||||
using: <T>(handler: () => T) => T,
|
using: <T>(handler: () => T) => T,
|
||||||
invalidate: <T>(handler: () => T) => T,
|
invalidate: <T>(handler: () => T) => T,
|
||||||
};
|
};
|
||||||
|
|
||||||
type CacheEntry<ResultT> = Array<[ResultT, () => boolean]>;
|
type CacheEntry<ResultT, SideChannel> = Array<
|
||||||
|
[ResultT, (SideChannel) => boolean],
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type { CacheConfigurator };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a function with a single argument, cache its results based on its argument and how it
|
* 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.
|
* configures its caching behavior. Cached values are stored strongly.
|
||||||
*/
|
*/
|
||||||
export function makeStrongCache<ArgT, ResultT>(
|
export function makeStrongCache<ArgT, ResultT, SideChannel>(
|
||||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
handler: (ArgT, CacheConfigurator<SideChannel>) => ResultT,
|
||||||
autoPermacache?: boolean,
|
): (ArgT, SideChannel) => ResultT {
|
||||||
): ArgT => ResultT {
|
return makeCachedFunction(new Map(), handler);
|
||||||
return makeCachedFunction(new Map(), handler, autoPermacache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,190 +35,182 @@ export function makeStrongCache<ArgT, ResultT>(
|
|||||||
* configures its caching behavior. Cached values are stored weakly and the function argument must be
|
* configures its caching behavior. Cached values are stored weakly and the function argument must be
|
||||||
* an object type.
|
* an object type.
|
||||||
*/
|
*/
|
||||||
export function makeWeakCache<ArgT: {} | Array<*> | $ReadOnlyArray<*>, ResultT>(
|
export function makeWeakCache<
|
||||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
ArgT: {} | Array<*> | $ReadOnlyArray<*>,
|
||||||
autoPermacache?: boolean,
|
ResultT,
|
||||||
): ArgT => ResultT {
|
SideChannel,
|
||||||
return makeCachedFunction(new WeakMap(), handler, autoPermacache);
|
>(
|
||||||
|
handler: (ArgT, CacheConfigurator<SideChannel>) => ResultT,
|
||||||
|
): (ArgT, SideChannel) => ResultT {
|
||||||
|
return makeCachedFunction(new WeakMap(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
type CacheMap<ArgT, ResultT> =
|
type CacheMap<ArgT, ResultT, SideChannel> =
|
||||||
| Map<ArgT, CacheEntry<ResultT>>
|
| Map<ArgT, CacheEntry<ResultT, SideChannel>>
|
||||||
| WeakMap<ArgT, CacheEntry<ResultT>>;
|
| WeakMap<ArgT, CacheEntry<ResultT, SideChannel>>;
|
||||||
|
|
||||||
function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
|
function makeCachedFunction<
|
||||||
|
ArgT,
|
||||||
|
ResultT,
|
||||||
|
SideChannel,
|
||||||
|
Cache: CacheMap<ArgT, ResultT, SideChannel>,
|
||||||
|
>(
|
||||||
callCache: Cache,
|
callCache: Cache,
|
||||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
handler: (ArgT, CacheConfigurator<SideChannel>) => ResultT,
|
||||||
autoPermacache: boolean = true,
|
): (ArgT, SideChannel) => ResultT {
|
||||||
): ArgT => ResultT {
|
return function cachedFunction(arg, data) {
|
||||||
return function cachedFunction(arg) {
|
let cachedValue: CacheEntry<ResultT, SideChannel> | void = callCache.get(
|
||||||
let cachedValue: CacheEntry<ResultT> | void = callCache.get(arg);
|
arg,
|
||||||
|
);
|
||||||
|
|
||||||
if (cachedValue) {
|
if (cachedValue) {
|
||||||
for (const [value, valid] of 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);
|
const value = handler(arg, cache);
|
||||||
|
|
||||||
if (autoPermacache && !result.configured) cache.forever();
|
if (!cache.configured()) cache.forever();
|
||||||
|
|
||||||
deactivate();
|
cache.deactivate();
|
||||||
|
|
||||||
if (!result.configured) {
|
switch (cache.mode()) {
|
||||||
// eslint-disable-next-line max-len
|
case "forever":
|
||||||
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) {
|
|
||||||
cachedValue = [[value, () => true]];
|
cachedValue = [[value, () => true]];
|
||||||
} else if (result.invalidate) {
|
callCache.set(arg, cachedValue);
|
||||||
cachedValue = [[value, result.valid]];
|
break;
|
||||||
} else {
|
case "invalidate":
|
||||||
cachedValue = cachedValue || [];
|
cachedValue = [[value, cache.validator()]];
|
||||||
cachedValue.push([value, result.valid]);
|
callCache.set(arg, cachedValue);
|
||||||
}
|
break;
|
||||||
callCache.set(arg, cachedValue);
|
case "valid":
|
||||||
|
if (cachedValue) {
|
||||||
|
cachedValue.push([value, cache.validator()]);
|
||||||
|
} else {
|
||||||
|
cachedValue = [[value, cache.validator()]];
|
||||||
|
callCache.set(arg, cachedValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeCacheConfig(): {
|
class CacheConfigurator<SideChannel = void> {
|
||||||
cache: CacheConfigurator,
|
_active: boolean = true;
|
||||||
result: *,
|
_never: boolean = false;
|
||||||
deactivate: () => void,
|
_forever: boolean = false;
|
||||||
} {
|
_invalidate: boolean = false;
|
||||||
const pairs = [];
|
|
||||||
|
|
||||||
const result = {
|
_configured: boolean = false;
|
||||||
configured: false,
|
|
||||||
never: false,
|
|
||||||
forever: false,
|
|
||||||
invalidate: false,
|
|
||||||
valid: () => pairs.every(([key, fn]) => key === fn()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let active = true;
|
_pairs: Array<[mixed, (SideChannel) => mixed]> = [];
|
||||||
const deactivate = () => {
|
|
||||||
active = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const cache: CacheConfigurator = Object.assign(
|
_data: SideChannel;
|
||||||
(function cacheFn(val) {
|
|
||||||
if (typeof val === "boolean") {
|
|
||||||
if (val) cache.forever();
|
|
||||||
else cache.never();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache.using(val);
|
constructor(data: SideChannel) {
|
||||||
}: any),
|
this._data = data;
|
||||||
({
|
}
|
||||||
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<T>(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;
|
|
||||||
|
|
||||||
const key = handler();
|
simple() {
|
||||||
pairs.push([key, handler]);
|
return makeSimpleConfigurator(this);
|
||||||
return key;
|
}
|
||||||
},
|
|
||||||
invalidate<T>(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;
|
|
||||||
|
|
||||||
const key = handler();
|
mode() {
|
||||||
pairs.push([key, handler]);
|
if (this._never) return "never";
|
||||||
return key;
|
if (this._forever) return "forever";
|
||||||
},
|
if (this._invalidate) return "invalidate";
|
||||||
}: CacheConfiguratorObj),
|
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<T>(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<T>(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<any>,
|
||||||
|
): 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,7 @@ 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 { getEnv } from "../../helpers/environment";
|
import { makeStrongCache, type CacheConfigurator } from "../../caching";
|
||||||
import { makeStrongCache } from "../../caching";
|
|
||||||
|
|
||||||
const debug = buildDebug("babel:config:loading:files:configuration");
|
const debug = buildDebug("babel:config:loading:files:configuration");
|
||||||
|
|
||||||
@ -21,7 +20,10 @@ const BABELRC_JS_FILENAME = ".babelrc.js";
|
|||||||
const PACKAGE_FILENAME = "package.json";
|
const PACKAGE_FILENAME = "package.json";
|
||||||
const BABELIGNORE_FILENAME = ".babelignore";
|
const BABELIGNORE_FILENAME = ".babelignore";
|
||||||
|
|
||||||
export function findConfigs(dirname: string): Array<ConfigFile> {
|
export function findConfigs(
|
||||||
|
dirname: string,
|
||||||
|
envName: string,
|
||||||
|
): Array<ConfigFile> {
|
||||||
let foundConfig = false;
|
let foundConfig = false;
|
||||||
let foundIgnore = false;
|
let foundIgnore = false;
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ export function findConfigs(dirname: string): Array<ConfigFile> {
|
|||||||
PACKAGE_FILENAME,
|
PACKAGE_FILENAME,
|
||||||
].reduce((previousConfig: ConfigFile | null, name) => {
|
].reduce((previousConfig: ConfigFile | null, name) => {
|
||||||
const filepath = path.join(loc, name);
|
const filepath = path.join(loc, name);
|
||||||
const config = readConfig(filepath);
|
const config = readConfig(filepath, envName);
|
||||||
|
|
||||||
if (config && previousConfig) {
|
if (config && previousConfig) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -77,10 +79,14 @@ export function findConfigs(dirname: string): Array<ConfigFile> {
|
|||||||
return confs;
|
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 filepath = resolve.sync(name, { basedir: dirname });
|
||||||
|
|
||||||
const conf = readConfig(filepath);
|
const conf = readConfig(filepath, envName);
|
||||||
if (!conf) {
|
if (!conf) {
|
||||||
throw new Error(`Config file ${filepath} contains no configuration data`);
|
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
|
* 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.
|
* throw if there are parsing errors while loading a config.
|
||||||
*/
|
*/
|
||||||
function readConfig(filepath) {
|
function readConfig(filepath, envName) {
|
||||||
return path.extname(filepath) === ".js"
|
return path.extname(filepath) === ".js"
|
||||||
? readConfigJS(filepath)
|
? readConfigJS(filepath, { envName })
|
||||||
: readConfigFile(filepath);
|
: readConfigFile(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOADING_CONFIGS = new Set();
|
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
|
const readConfigJS = makeStrongCache(
|
||||||
// loaded into the system. That would cause Babel to attempt to compile the `.babelrc.js` file as it loads
|
(filepath, cache: CacheConfigurator<{ envName: string }>) => {
|
||||||
// below. To cover this case, we auto-ignore re-entrant config processing.
|
if (!fs.existsSync(filepath)) {
|
||||||
if (LOADING_CONFIGS.has(filepath)) {
|
cache.forever();
|
||||||
cache.never();
|
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 {
|
return {
|
||||||
filepath,
|
filepath,
|
||||||
dirname: path.dirname(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) => {
|
const readConfigFile = makeStaticFileCache((filepath, content) => {
|
||||||
let options;
|
let options;
|
||||||
@ -239,3 +248,40 @@ function fileMtime(filepath: string): number | null {
|
|||||||
|
|
||||||
return 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 { };
|
||||||
|
};`);
|
||||||
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import merge from "lodash/merge";
|
|||||||
import buildConfigChain, { type ConfigItem } from "./build-config-chain";
|
import buildConfigChain, { type ConfigItem } from "./build-config-chain";
|
||||||
import traverse from "@babel/traverse";
|
import traverse from "@babel/traverse";
|
||||||
import clone from "lodash/clone";
|
import clone from "lodash/clone";
|
||||||
import { makeWeakCache } from "./caching";
|
import { makeWeakCache, type CacheConfigurator } from "./caching";
|
||||||
import { getEnv } from "./helpers/environment";
|
import { getEnv } from "./helpers/environment";
|
||||||
import { validate, type ValidatedOptions, type PluginItem } from "./options";
|
import { validate, type ValidatedOptions, type PluginItem } from "./options";
|
||||||
|
|
||||||
@ -46,14 +46,14 @@ class OptionManager {
|
|||||||
* - `dirname` is used to resolve plugins relative to it.
|
* - `dirname` is used to resolve plugins relative to it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mergeOptions(config: MergeOptions, pass?: Array<Plugin>) {
|
mergeOptions(config: MergeOptions, pass?: Array<Plugin>, envName: string) {
|
||||||
const result = loadConfig(config);
|
const result = loadConfig(config);
|
||||||
|
|
||||||
const plugins = result.plugins.map(descriptor =>
|
const plugins = result.plugins.map(descriptor =>
|
||||||
loadPluginDescriptor(descriptor),
|
loadPluginDescriptor(descriptor, envName),
|
||||||
);
|
);
|
||||||
const presets = result.presets.map(descriptor =>
|
const presets = result.presets.map(descriptor =>
|
||||||
loadPresetDescriptor(descriptor),
|
loadPresetDescriptor(descriptor, envName),
|
||||||
);
|
);
|
||||||
|
|
||||||
const passPerPreset = config.options.passPerPreset;
|
const passPerPreset = config.options.passPerPreset;
|
||||||
@ -70,7 +70,11 @@ class OptionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
presets.forEach((presetConfig, i) => {
|
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: {}) {
|
init(inputOpts: {}) {
|
||||||
const args = validate("arguments", inputOpts);
|
const args = validate("arguments", inputOpts);
|
||||||
|
|
||||||
const configChain = buildConfigChain(args);
|
const { envName = getEnv() } = args;
|
||||||
|
|
||||||
|
const configChain = buildConfigChain(args, envName);
|
||||||
if (!configChain) return null;
|
if (!configChain) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const config of configChain) {
|
for (const config of configChain) {
|
||||||
this.mergeOptions(config);
|
this.mergeOptions(config, undefined, envName);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// There are a few case where thrown errors will try to annotate themselves multiple times, so
|
// 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)
|
.filter(plugins => plugins.length > 0)
|
||||||
.map(plugins => ({ plugins }));
|
.map(plugins => ({ plugins }));
|
||||||
opts.passPerPreset = opts.presets.length > 0;
|
opts.passPerPreset = opts.presets.length > 0;
|
||||||
|
opts.envName = envName;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
options: opts,
|
options: opts,
|
||||||
@ -182,13 +189,13 @@ const loadConfig = makeWeakCache((config: MergeOptions): {
|
|||||||
const loadDescriptor = makeWeakCache(
|
const loadDescriptor = makeWeakCache(
|
||||||
(
|
(
|
||||||
{ value, options = {}, dirname, alias }: BasicDescriptor,
|
{ value, options = {}, dirname, alias }: BasicDescriptor,
|
||||||
cache,
|
cache: CacheConfigurator<{ envName: string }>,
|
||||||
): LoadedDescriptor => {
|
): LoadedDescriptor => {
|
||||||
let item = value;
|
let item = value;
|
||||||
if (typeof value === "function") {
|
if (typeof value === "function") {
|
||||||
const api = Object.assign(Object.create(context), {
|
const api = Object.assign(Object.create(context), {
|
||||||
cache,
|
cache: cache.simple(),
|
||||||
env: () => cache.using(() => getEnv()),
|
env: () => cache.using(data => data.envName),
|
||||||
async: () => false,
|
async: () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -222,7 +229,10 @@ const loadDescriptor = makeWeakCache(
|
|||||||
/**
|
/**
|
||||||
* Instantiate a plugin for the given descriptor, returning the plugin/options pair.
|
* 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.value instanceof Plugin) {
|
||||||
if (descriptor.options) {
|
if (descriptor.options) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -233,11 +243,16 @@ function loadPluginDescriptor(descriptor: BasicDescriptor): Plugin {
|
|||||||
return descriptor.value;
|
return descriptor.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return instantiatePlugin(loadDescriptor(descriptor));
|
return instantiatePlugin(loadDescriptor(descriptor, { envName }), {
|
||||||
|
envName,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const instantiatePlugin = makeWeakCache(
|
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 pluginObj = validatePluginObject(value);
|
||||||
|
|
||||||
const plugin = Object.assign({}, pluginObj);
|
const plugin = Object.assign({}, pluginObj);
|
||||||
@ -254,8 +269,8 @@ const instantiatePlugin = makeWeakCache(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If the inherited plugin changes, reinstantiate this plugin.
|
// If the inherited plugin changes, reinstantiate this plugin.
|
||||||
const inherits = cache.invalidate(() =>
|
const inherits = cache.invalidate(data =>
|
||||||
loadPluginDescriptor(inheritsDescriptor),
|
loadPluginDescriptor(inheritsDescriptor, data.envName),
|
||||||
);
|
);
|
||||||
|
|
||||||
plugin.pre = chain(inherits.pre, plugin.pre);
|
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.
|
* Generate a config object that will act as the root of a new nested config.
|
||||||
*/
|
*/
|
||||||
const loadPresetDescriptor = (descriptor: BasicDescriptor): MergeOptions => {
|
const loadPresetDescriptor = (
|
||||||
return instantiatePreset(loadDescriptor(descriptor));
|
descriptor: BasicDescriptor,
|
||||||
|
envName: string,
|
||||||
|
): MergeOptions => {
|
||||||
|
return instantiatePreset(loadDescriptor(descriptor, { envName }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const instantiatePreset = makeWeakCache(
|
const instantiatePreset = makeWeakCache(
|
||||||
|
|||||||
@ -28,6 +28,10 @@ const ROOT_VALIDATORS: ValidatorSet = {
|
|||||||
>),
|
>),
|
||||||
code: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "code">>),
|
code: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "code">>),
|
||||||
ast: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "ast">>),
|
ast: (assertBoolean: Validator<$PropertyType<ValidatedOptions, "ast">>),
|
||||||
|
|
||||||
|
envName: (assertString: Validator<
|
||||||
|
$PropertyType<ValidatedOptions, "envName">,
|
||||||
|
>),
|
||||||
};
|
};
|
||||||
|
|
||||||
const NONPRESET_VALIDATORS: ValidatorSet = {
|
const NONPRESET_VALIDATORS: ValidatorSet = {
|
||||||
@ -130,6 +134,7 @@ export type ValidatedOptions = {
|
|||||||
code?: boolean,
|
code?: boolean,
|
||||||
ast?: boolean,
|
ast?: boolean,
|
||||||
inputSourceMap?: RootInputSourceMapOption,
|
inputSourceMap?: RootInputSourceMapOption,
|
||||||
|
envName?: string,
|
||||||
|
|
||||||
extends?: string,
|
extends?: string,
|
||||||
env?: EnvSet<ValidatedOptions>,
|
env?: EnvSet<ValidatedOptions>,
|
||||||
|
|||||||
@ -19,23 +19,6 @@ describe("caching API", () => {
|
|||||||
assert.notEqual(fn("one"), fn("two"));
|
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()", () => {
|
it("should allow disabling caching with .never()", () => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
@ -55,25 +38,6 @@ describe("caching API", () => {
|
|||||||
assert.notEqual(fn("one"), 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(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)", () => {
|
it("should allow caching based on a value with .using(fn)", () => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let other = "default";
|
let other = "default";
|
||||||
@ -115,47 +79,6 @@ describe("caching API", () => {
|
|||||||
assert.equal(fn("two"), fn("two"));
|
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)", () => {
|
it("should allow invalidation based on a value with .invalidate(fn)", () => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let other = "default";
|
let other = "default";
|
||||||
@ -298,12 +221,6 @@ describe("caching API", () => {
|
|||||||
assert.equal(fn("two"), fn("two"));
|
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", () => {
|
it("should auto-permacache by default", () => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
@ -410,4 +327,89 @@ describe("caching API", () => {
|
|||||||
/Cannot change caching after evaluation/,
|
/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"));
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import fs from "fs";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import buildConfigChain from "../lib/config/build-config-chain";
|
import buildConfigChain from "../lib/config/build-config-chain";
|
||||||
|
|
||||||
|
const DEFAULT_ENV = "development";
|
||||||
|
|
||||||
function fixture() {
|
function fixture() {
|
||||||
const args = [__dirname, "fixtures", "config"];
|
const args = [__dirname, "fixtures", "config"];
|
||||||
for (let i = 0; i < arguments.length; i++) {
|
for (let i = 0; i < arguments.length; i++) {
|
||||||
@ -16,49 +18,39 @@ function base() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("buildConfigChain", function() {
|
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", () => {
|
describe("ignore", () => {
|
||||||
it("should ignore files that match", () => {
|
it("should ignore files that match", () => {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("nonexistant-fake", "src.js"),
|
{
|
||||||
babelrc: false,
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
ignore: [
|
babelrc: false,
|
||||||
fixture("nonexistant-fake", "src.js"),
|
ignore: [
|
||||||
|
fixture("nonexistant-fake", "src.js"),
|
||||||
|
|
||||||
// We had a regression where multiple ignore patterns broke things, so
|
// We had a regression where multiple ignore patterns broke things, so
|
||||||
// we keep some extra random items in here.
|
// we keep some extra random items in here.
|
||||||
fixture("nonexistant-fake", "other.js"),
|
fixture("nonexistant-fake", "other.js"),
|
||||||
fixture("nonexistant-fake", "misc.js"),
|
fixture("nonexistant-fake", "misc.js"),
|
||||||
],
|
],
|
||||||
});
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(chain, null);
|
assert.equal(chain, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not ignore files that don't match", () => {
|
it("should not ignore files that don't match", () => {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("nonexistant-fake", "src.js"),
|
{
|
||||||
babelrc: false,
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
ignore: [
|
babelrc: false,
|
||||||
fixture("nonexistant-fake", "other.js"),
|
ignore: [
|
||||||
fixture("nonexistant-fake", "misc.js"),
|
fixture("nonexistant-fake", "other.js"),
|
||||||
],
|
fixture("nonexistant-fake", "misc.js"),
|
||||||
});
|
],
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -82,27 +74,33 @@ describe("buildConfigChain", function() {
|
|||||||
|
|
||||||
describe("only", () => {
|
describe("only", () => {
|
||||||
it("should ignore files that don't match", () => {
|
it("should ignore files that don't match", () => {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("nonexistant-fake", "src.js"),
|
{
|
||||||
babelrc: false,
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
only: [
|
babelrc: false,
|
||||||
fixture("nonexistant-fake", "other.js"),
|
only: [
|
||||||
fixture("nonexistant-fake", "misc.js"),
|
fixture("nonexistant-fake", "other.js"),
|
||||||
],
|
fixture("nonexistant-fake", "misc.js"),
|
||||||
});
|
],
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(chain, null);
|
assert.equal(chain, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not ignore files that match", () => {
|
it("should not ignore files that match", () => {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("nonexistant-fake", "src.js"),
|
{
|
||||||
babelrc: false,
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
only: [
|
babelrc: false,
|
||||||
fixture("nonexistant-fake", "src.js"),
|
only: [
|
||||||
fixture("nonexistant-fake", "misc.js"),
|
fixture("nonexistant-fake", "src.js"),
|
||||||
],
|
fixture("nonexistant-fake", "misc.js"),
|
||||||
});
|
],
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -126,12 +124,15 @@ 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 chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("nonexistant-fake", "src.js"),
|
{
|
||||||
babelrc: false,
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
ignore: [fixture("nonexistant-fake", "src.js")],
|
babelrc: false,
|
||||||
only: [fixture("nonexistant-fake", "src.js")],
|
ignore: [fixture("nonexistant-fake", "src.js")],
|
||||||
});
|
only: [fixture("nonexistant-fake", "src.js")],
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(chain, null);
|
assert.equal(chain, null);
|
||||||
});
|
});
|
||||||
@ -142,8 +143,8 @@ describe("buildConfigChain", function() {
|
|||||||
it("should not cache the input options by identity", () => {
|
it("should not cache the input options by identity", () => {
|
||||||
const comments = false;
|
const comments = false;
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ comments });
|
const chain1 = buildConfigChain({ comments }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ comments });
|
const chain2 = buildConfigChain({ comments }, DEFAULT_ENV);
|
||||||
|
|
||||||
assert.equal(chain1.length, 1);
|
assert.equal(chain1.length, 1);
|
||||||
assert.equal(chain2.length, 1);
|
assert.equal(chain2.length, 1);
|
||||||
@ -151,15 +152,14 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should cache the env options by identity", () => {
|
it("should cache the env options by identity", () => {
|
||||||
process.env.NODE_ENV = "foo";
|
|
||||||
const env = {
|
const env = {
|
||||||
foo: {
|
foo: {
|
||||||
comments: false,
|
comments: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ env });
|
const chain1 = buildConfigChain({ env }, "foo");
|
||||||
const chain2 = buildConfigChain({ env });
|
const chain2 = buildConfigChain({ env }, "foo");
|
||||||
|
|
||||||
assert.equal(chain1.length, 2);
|
assert.equal(chain1.length, 2);
|
||||||
assert.equal(chain2.length, 2);
|
assert.equal(chain2.length, 2);
|
||||||
@ -170,8 +170,8 @@ describe("buildConfigChain", function() {
|
|||||||
it("should cache the plugin options by identity", () => {
|
it("should cache the plugin options by identity", () => {
|
||||||
const plugins = [];
|
const plugins = [];
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ plugins });
|
const chain1 = buildConfigChain({ plugins }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ plugins });
|
const chain2 = buildConfigChain({ plugins }, DEFAULT_ENV);
|
||||||
|
|
||||||
assert.equal(chain1.length, 1);
|
assert.equal(chain1.length, 1);
|
||||||
assert.equal(chain2.length, 1);
|
assert.equal(chain2.length, 1);
|
||||||
@ -181,8 +181,8 @@ describe("buildConfigChain", function() {
|
|||||||
it("should cache the presets options by identity", () => {
|
it("should cache the presets options by identity", () => {
|
||||||
const presets = [];
|
const presets = [];
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ presets });
|
const chain1 = buildConfigChain({ presets }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ presets });
|
const chain2 = buildConfigChain({ presets }, DEFAULT_ENV);
|
||||||
|
|
||||||
assert.equal(chain1.length, 1);
|
assert.equal(chain1.length, 1);
|
||||||
assert.equal(chain2.length, 1);
|
assert.equal(chain2.length, 1);
|
||||||
@ -192,9 +192,15 @@ describe("buildConfigChain", function() {
|
|||||||
it("should not cache the presets options with passPerPreset", () => {
|
it("should not cache the presets options with passPerPreset", () => {
|
||||||
const presets = [];
|
const presets = [];
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ presets });
|
const chain1 = buildConfigChain({ presets }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ presets, passPerPreset: true });
|
const chain2 = buildConfigChain(
|
||||||
const chain3 = buildConfigChain({ presets, passPerPreset: false });
|
{ presets, passPerPreset: true },
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
const chain3 = buildConfigChain(
|
||||||
|
{ presets, passPerPreset: false },
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(chain1.length, 1);
|
assert.equal(chain1.length, 1);
|
||||||
assert.equal(chain2.length, 1);
|
assert.equal(chain2.length, 1);
|
||||||
@ -229,13 +235,13 @@ describe("buildConfigChain", function() {
|
|||||||
"package.json",
|
"package.json",
|
||||||
);
|
);
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ filename });
|
const chain1 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ filename });
|
const chain2 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
|
|
||||||
touch(pkgJSON);
|
touch(pkgJSON);
|
||||||
|
|
||||||
const chain3 = buildConfigChain({ filename });
|
const chain3 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
const chain4 = buildConfigChain({ filename });
|
const chain4 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
|
|
||||||
assert.equal(chain1.length, 3);
|
assert.equal(chain1.length, 3);
|
||||||
assert.equal(chain2.length, 3);
|
assert.equal(chain2.length, 3);
|
||||||
@ -266,13 +272,13 @@ describe("buildConfigChain", function() {
|
|||||||
".babelrc",
|
".babelrc",
|
||||||
);
|
);
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ filename });
|
const chain1 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ filename });
|
const chain2 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
|
|
||||||
touch(babelrcFile);
|
touch(babelrcFile);
|
||||||
|
|
||||||
const chain3 = buildConfigChain({ filename });
|
const chain3 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
const chain4 = buildConfigChain({ filename });
|
const chain4 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
|
|
||||||
assert.equal(chain1.length, 3);
|
assert.equal(chain1.length, 3);
|
||||||
assert.equal(chain2.length, 3);
|
assert.equal(chain2.length, 3);
|
||||||
@ -303,13 +309,13 @@ describe("buildConfigChain", function() {
|
|||||||
".babelignore",
|
".babelignore",
|
||||||
);
|
);
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ filename });
|
const chain1 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ filename });
|
const chain2 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
|
|
||||||
touch(babelignoreFile);
|
touch(babelignoreFile);
|
||||||
|
|
||||||
const chain3 = buildConfigChain({ filename });
|
const chain3 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
const chain4 = buildConfigChain({ filename });
|
const chain4 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
|
|
||||||
assert.equal(chain1.length, 6);
|
assert.equal(chain1.length, 6);
|
||||||
assert.equal(chain2.length, 6);
|
assert.equal(chain2.length, 6);
|
||||||
@ -340,13 +346,11 @@ describe("buildConfigChain", function() {
|
|||||||
".babelrc.js",
|
".babelrc.js",
|
||||||
);
|
);
|
||||||
|
|
||||||
const chain1 = buildConfigChain({ filename });
|
const chain1 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
const chain2 = buildConfigChain({ filename });
|
const chain2 = buildConfigChain({ filename }, DEFAULT_ENV);
|
||||||
|
|
||||||
process.env.NODE_ENV = "new-env";
|
const chain3 = buildConfigChain({ filename }, "new-env");
|
||||||
|
const chain4 = buildConfigChain({ filename }, "new-env");
|
||||||
const chain3 = buildConfigChain({ filename });
|
|
||||||
const chain4 = buildConfigChain({ filename });
|
|
||||||
|
|
||||||
assert.equal(chain1.length, 3);
|
assert.equal(chain1.length, 3);
|
||||||
assert.equal(chain2.length, 3);
|
assert.equal(chain2.length, 3);
|
||||||
@ -358,7 +362,7 @@ describe("buildConfigChain", function() {
|
|||||||
assert.equal(chain4[1].alias, babelrcFile);
|
assert.equal(chain4[1].alias, babelrcFile);
|
||||||
assert.strictEqual(chain1[1], chain2[1]);
|
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.notStrictEqual(chain3[1], chain1[1]);
|
||||||
assert.strictEqual(chain3[1], chain4[1]);
|
assert.strictEqual(chain3[1], chain4[1]);
|
||||||
});
|
});
|
||||||
@ -366,9 +370,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("dir1", function() {
|
it("dir1", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("dir1", "src.js"),
|
{
|
||||||
});
|
filename: fixture("dir1", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -410,9 +417,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("dir2", function() {
|
it("dir2", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("dir2", "src.js"),
|
{
|
||||||
});
|
filename: fixture("dir2", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -445,9 +455,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("dir3", function() {
|
it("dir3", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("dir3", "src.js"),
|
{
|
||||||
});
|
filename: fixture("dir3", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -489,9 +502,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("env - base", function() {
|
it("env - base", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("env", "src.js"),
|
{
|
||||||
});
|
filename: fixture("env", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -532,11 +548,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("env - foo", function() {
|
it("env - foo", function() {
|
||||||
process.env.NODE_ENV = "foo";
|
const chain = buildConfigChain(
|
||||||
|
{
|
||||||
const chain = buildConfigChain({
|
filename: fixture("env", "src.js"),
|
||||||
filename: fixture("env", "src.js"),
|
},
|
||||||
});
|
"foo",
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -585,12 +602,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("env - bar", function() {
|
it("env - bar", function() {
|
||||||
process.env.NODE_ENV = "foo"; // overridden
|
const chain = buildConfigChain(
|
||||||
process.env.NODE_ENV = "bar";
|
{
|
||||||
|
filename: fixture("env", "src.js"),
|
||||||
const chain = buildConfigChain({
|
},
|
||||||
filename: fixture("env", "src.js"),
|
"bar",
|
||||||
});
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -639,11 +656,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("env - foo", function() {
|
it("env - foo", function() {
|
||||||
process.env.NODE_ENV = "foo";
|
const chain = buildConfigChain(
|
||||||
|
{
|
||||||
const chain = buildConfigChain({
|
filename: fixture("pkg", "src.js"),
|
||||||
filename: fixture("pkg", "src.js"),
|
},
|
||||||
});
|
"foo",
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -676,9 +694,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("js-config", function() {
|
it("js-config", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("js-config", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-config", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -711,9 +732,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("js-config-function", function() {
|
it("js-config-function", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("js-config-function", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-config-function", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -746,9 +770,12 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("js-config-default - should read transpiled export default", function() {
|
it("js-config-default - should read transpiled export default", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("js-config-default", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-config-default", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -780,9 +807,12 @@ describe("buildConfigChain", function() {
|
|||||||
assert.deepEqual(chain, expected);
|
assert.deepEqual(chain, expected);
|
||||||
});
|
});
|
||||||
it("js-config-extended", function() {
|
it("js-config-extended", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("js-config-extended", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-config-extended", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -827,9 +857,12 @@ describe("buildConfigChain", function() {
|
|||||||
"json-pkg-config-no-babel - should not throw if" +
|
"json-pkg-config-no-babel - should not throw if" +
|
||||||
" package.json doesn't contain a `babel` field",
|
" package.json doesn't contain a `babel` field",
|
||||||
function() {
|
function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("json-pkg-config-no-babel", "src.js"),
|
{
|
||||||
});
|
filename: fixture("json-pkg-config-no-babel", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -863,9 +896,12 @@ describe("buildConfigChain", function() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it("should not ignore file matching negated file pattern", function() {
|
it("should not ignore file matching negated file pattern", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("ignore-negate", "src.js"),
|
{
|
||||||
});
|
filename: fixture("ignore-negate", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -896,17 +932,23 @@ describe("buildConfigChain", function() {
|
|||||||
|
|
||||||
assert.deepEqual(chain, expected);
|
assert.deepEqual(chain, expected);
|
||||||
|
|
||||||
const chain2 = buildConfigChain({
|
const chain2 = buildConfigChain(
|
||||||
filename: fixture("ignore-negate", "src2.js"),
|
{
|
||||||
});
|
filename: fixture("ignore-negate", "src2.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(chain2, null);
|
assert.equal(chain2, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not ignore file matching negated folder pattern", function() {
|
it("should not ignore file matching negated folder pattern", function() {
|
||||||
const chain = buildConfigChain({
|
const chain = buildConfigChain(
|
||||||
filename: fixture("ignore-negate-folder", "folder", "src.js"),
|
{
|
||||||
});
|
filename: fixture("ignore-negate-folder", "folder", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{
|
{
|
||||||
@ -937,9 +979,12 @@ describe("buildConfigChain", function() {
|
|||||||
|
|
||||||
assert.deepEqual(chain, expected);
|
assert.deepEqual(chain, expected);
|
||||||
|
|
||||||
const chain2 = buildConfigChain({
|
const chain2 = buildConfigChain(
|
||||||
filename: fixture("ignore-negate-folder", "src2.js"),
|
{
|
||||||
});
|
filename: fixture("ignore-negate-folder", "src2.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
|
|
||||||
assert.equal(chain2, null);
|
assert.equal(chain2, null);
|
||||||
});
|
});
|
||||||
@ -949,9 +994,12 @@ describe("buildConfigChain", function() {
|
|||||||
" and a .babelrc.js are present",
|
" and a .babelrc.js are present",
|
||||||
function() {
|
function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
buildConfigChain({
|
buildConfigChain(
|
||||||
filename: fixture("js-json-config", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-json-config", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
}, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/);
|
}, /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",
|
" and a package.json with a babel field are present",
|
||||||
function() {
|
function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
buildConfigChain({
|
buildConfigChain(
|
||||||
filename: fixture("js-pkg-config", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-pkg-config", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
}, /Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/);
|
}, /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",
|
" and a package.json with a babel field are present",
|
||||||
function() {
|
function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
buildConfigChain({
|
buildConfigChain(
|
||||||
filename: fixture("json-pkg-config", "src.js"),
|
{
|
||||||
});
|
filename: fixture("json-pkg-config", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
}, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/);
|
}, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
it("js-config-error", function() {
|
it("js-config-error", function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
buildConfigChain({
|
buildConfigChain(
|
||||||
filename: fixture("js-config-error", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-config-error", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
}, /Error while loading config/);
|
}, /Error while loading config/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("js-config-error2", function() {
|
it("js-config-error2", function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
buildConfigChain({
|
buildConfigChain(
|
||||||
filename: fixture("js-config-error2", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-config-error2", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
}, /Configuration should be an exported JavaScript object/);
|
}, /Configuration should be an exported JavaScript object/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("js-config-error3", function() {
|
it("js-config-error3", function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
buildConfigChain({
|
buildConfigChain(
|
||||||
filename: fixture("js-config-error3", "src.js"),
|
{
|
||||||
});
|
filename: fixture("js-config-error3", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
}, /Configuration should be an exported JavaScript object/);
|
}, /Configuration should be an exported JavaScript object/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("json-config-error", function() {
|
it("json-config-error", function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
buildConfigChain({
|
buildConfigChain(
|
||||||
filename: fixture("json-config-error", "src.js"),
|
{
|
||||||
});
|
filename: fixture("json-config-error", "src.js"),
|
||||||
|
},
|
||||||
|
DEFAULT_ENV,
|
||||||
|
);
|
||||||
}, /Error while parsing config/);
|
}, /Error while parsing config/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user