Use expanded caching API to simplify usage.
This commit is contained in:
@@ -22,9 +22,8 @@ type CacheEntry<ResultT> = Array<[ResultT, () => boolean]>;
|
||||
*/
|
||||
export function makeStrongCache<ArgT, ResultT>(
|
||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
||||
autoPermacache?: boolean,
|
||||
): ArgT => ResultT {
|
||||
return makeCachedFunction(new Map(), handler, autoPermacache);
|
||||
return makeCachedFunction(new Map(), handler);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,9 +33,8 @@ export function makeStrongCache<ArgT, ResultT>(
|
||||
*/
|
||||
export function makeWeakCache<ArgT: {} | Array<*> | $ReadOnlyArray<*>, ResultT>(
|
||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
||||
autoPermacache?: boolean,
|
||||
): ArgT => ResultT {
|
||||
return makeCachedFunction(new WeakMap(), handler, autoPermacache);
|
||||
return makeCachedFunction(new WeakMap(), handler);
|
||||
}
|
||||
|
||||
type CacheMap<ArgT, ResultT> =
|
||||
@@ -46,7 +44,6 @@ type CacheMap<ArgT, ResultT> =
|
||||
function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
|
||||
callCache: Cache,
|
||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
||||
autoPermacache: boolean = true,
|
||||
): ArgT => ResultT {
|
||||
return function cachedFunction(arg) {
|
||||
let cachedValue: CacheEntry<ResultT> | void = callCache.get(arg);
|
||||
@@ -61,12 +58,10 @@ function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
|
||||
|
||||
const value = handler(arg, cache);
|
||||
|
||||
if (autoPermacache && !cache.configured()) cache.forever();
|
||||
if (!cache.configured()) cache.forever();
|
||||
|
||||
cache.deactivate();
|
||||
|
||||
cache.assertConfigured();
|
||||
|
||||
switch (cache.mode()) {
|
||||
case "forever":
|
||||
cachedValue = [[value, () => true]];
|
||||
@@ -177,49 +172,6 @@ class CacheConfigurator {
|
||||
configured() {
|
||||
return this._configured;
|
||||
}
|
||||
|
||||
assertConfigured() {
|
||||
if (this.configured()) return;
|
||||
|
||||
// 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"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function makeSimpleConfigurator(
|
||||
|
||||
@@ -144,8 +144,8 @@ const readConfigJS = makeStrongCache((filepath, cache) => {
|
||||
env: () => cache.using(() => getEnv()),
|
||||
async: () => false,
|
||||
});
|
||||
} else {
|
||||
cache.forever();
|
||||
|
||||
if (!cache.configured()) throwConfigError();
|
||||
}
|
||||
|
||||
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
||||
@@ -169,7 +169,7 @@ const readConfigJS = makeStrongCache((filepath, cache) => {
|
||||
dirname: path.dirname(filepath),
|
||||
options,
|
||||
};
|
||||
}, false /* autoPermacache */);
|
||||
});
|
||||
|
||||
const readConfigFile = makeStaticFileCache((filepath, content) => {
|
||||
let options;
|
||||
@@ -239,3 +239,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 { };
|
||||
};`);
|
||||
}
|
||||
|
||||
@@ -221,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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user