Use expanded caching API to simplify usage.

This commit is contained in:
Logan Smyth
2017-11-14 17:26:50 -08:00
parent 3942862a2a
commit bbff566024
3 changed files with 43 additions and 60 deletions

View File

@@ -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(

View File

@@ -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 { };
};`);
}

View File

@@ -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;