
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { forEachBail } = require("enhanced-resolve");
const asyncLib = require("neo-async");
const getLazyHashedEtag = require("./cache/getLazyHashedEtag");
const mergeEtags = require("./cache/mergeEtags");
/** @typedef {import("./Cache")} Cache */
/** @typedef {import("./Cache").Etag} Etag */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./cache/getLazyHashedEtag").HashableObject} HashableObject */
/** @typedef {typeof import("./util/Hash")} HashConstructor */
/**
* @template T
* @callback CallbackCache
* @param {(WebpackError | null)=} err
* @param {T=} result
* @returns {void}
*/
/**
* @template T
* @callback CallbackNormalErrorCache
* @param {(Error | null)=} err
* @param {T=} result
* @returns {void}
*/
class MultiItemCache {
/**
* @param {ItemCacheFacade[]} items item caches
*/
constructor(items) {
this._items = items;
if (items.length === 1) return /** @type {any} */ (items[0]);
}
/**
* @template T
* @param {CallbackCache<T>} callback signals when the value is retrieved
* @returns {void}
*/
get(callback) {
forEachBail(this._items, (item, callback) => item.get(callback), callback);
}
/**
* @template T
* @returns {Promise<T>} promise with the data
*/
getPromise() {
const next = i => {
return this._items[i].getPromise().then(result => {
if (result !== undefined) return result;
if (++i < this._items.length) return next(i);
});
};
return next(0);
}
/**
* @template T
* @param {T} data the value to store
* @param {CallbackCache<void>} callback signals when the value is stored
* @returns {void}
*/
store(data, callback) {
asyncLib.each(
this._items,
(item, callback) => item.store(data, callback),
callback
);
}
/**
* @template T
* @param {T} data the value to store
* @returns {Promise<void>} promise signals when the value is stored
*/
storePromise(data) {
return Promise.all(this._items.map(item => item.storePromise(data))).then(
() => {}
);
}
}
class ItemCacheFacade {
/**
* @param {Cache} cache the root cache
* @param {string} name the child cache item name
* @param {Etag | null} etag the etag
*/
constructor(cache, name, etag) {
this._cache = cache;
this._name = name;
this._etag = etag;
}
/**
* @template T
* @param {CallbackCache<T>} callback signals when the value is retrieved
* @returns {void}
*/
get(callback) {
this._cache.get(this._name, this._etag, callback);
}
/**
* @template T
* @returns {Promise<T>} promise with the data
*/
getPromise() {
return new Promise((resolve, reject) => {
this._cache.get(this._name, this._etag, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
/**
* @template T
* @param {T} data the value to store
* @param {CallbackCache<void>} callback signals when the value is stored
* @returns {void}
*/
store(data, callback) {
this._cache.store(this._name, this._etag, data, callback);
}
/**
* @template T
* @param {T} data the value to store
* @returns {Promise<void>} promise signals when the value is stored
*/
storePromise(data) {
return new Promise((resolve, reject) => {
this._cache.store(this._name, this._etag, data, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
/**
* @template T
* @param {function(CallbackNormalErrorCache<T>): void} computer function to compute the value if not cached
* @param {CallbackNormalErrorCache<T>} callback signals when the value is retrieved
* @returns {void}
*/
provide(computer, callback) {
this.get((err, cacheEntry) => {
if (err) return callback(err);
if (cacheEntry !== undefined) return cacheEntry;
computer((err, result) => {
if (err) return callback(err);
this.store(result, err => {
if (err) return callback(err);
callback(null, result);
});
});
});
}
/**
* @template T
* @param {function(): Promise<T> | T} computer function to compute the value if not cached
* @returns {Promise<T>} promise with the data
*/
async providePromise(computer) {
const cacheEntry = await this.getPromise();
if (cacheEntry !== undefined) return cacheEntry;
const result = await computer();
await this.storePromise(result);
return result;
}
}
class CacheFacade {
/**
* @param {Cache} cache the root cache
* @param {string} name the child cache name
* @param {string | HashConstructor} hashFunction the hash function to use
*/
constructor(cache, name, hashFunction) {
this._cache = cache;
this._name = name;
this._hashFunction = hashFunction;
}
/**
* @param {string} name the child cache name#
* @returns {CacheFacade} child cache
*/
getChildCache(name) {
return new CacheFacade(
this._cache,
`${this._name}|${name}`,
this._hashFunction
);
}
/**
* @param {string} identifier the cache identifier
* @param {Etag | null} etag the etag
* @returns {ItemCacheFacade} item cache
*/
getItemCache(identifier, etag) {
return new ItemCacheFacade(
this._cache,
`${this._name}|${identifier}`,
etag
);
}
/**
* @param {HashableObject} obj an hashable object
* @returns {Etag} an etag that is lazy hashed
*/
getLazyHashedEtag(obj) {
return getLazyHashedEtag(obj, this._hashFunction);
}
/**
* @param {Etag} a an etag
* @param {Etag} b another etag
* @returns {Etag} an etag that represents both
*/
mergeEtags(a, b) {
return mergeEtags(a, b);
}
/**
* @template T
* @param {string} identifier the cache identifier
* @param {Etag | null} etag the etag
* @param {CallbackCache<T>} callback signals when the value is retrieved
* @returns {void}
*/
get(identifier, etag, callback) {
this._cache.get(`${this._name}|${identifier}`, etag, callback);
}
/**
* @template T
* @param {string} identifier the cache identifier
* @param {Etag | null} etag the etag
* @returns {Promise<T>} promise with the data
*/
getPromise(identifier, etag) {
return new Promise((resolve, reject) => {
this._cache.get(`${this._name}|${identifier}`, etag, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
/**
* @template T
* @param {string} identifier the cache identifier
* @param {Etag | null} etag the etag
* @param {T} data the value to store
* @param {CallbackCache<void>} callback signals when the value is stored
* @returns {void}
*/
store(identifier, etag, data, callback) {
this._cache.store(`${this._name}|${identifier}`, etag, data, callback);
}
/**
* @template T
* @param {string} identifier the cache identifier
* @param {Etag | null} etag the etag
* @param {T} data the value to store
* @returns {Promise<void>} promise signals when the value is stored
*/
storePromise(identifier, etag, data) {
return new Promise((resolve, reject) => {
this._cache.store(`${this._name}|${identifier}`, etag, data, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
/**
* @template T
* @param {string} identifier the cache identifier
* @param {Etag | null} etag the etag
* @param {function(CallbackNormalErrorCache<T>): void} computer function to compute the value if not cached
* @param {CallbackNormalErrorCache<T>} callback signals when the value is retrieved
* @returns {void}
*/
provide(identifier, etag, computer, callback) {
this.get(identifier, etag, (err, cacheEntry) => {
if (err) return callback(err);
if (cacheEntry !== undefined) return cacheEntry;
computer((err, result) => {
if (err) return callback(err);
this.store(identifier, etag, result, err => {
if (err) return callback(err);
callback(null, result);
});
});
});
}
/**
* @template T
* @param {string} identifier the cache identifier
* @param {Etag | null} etag the etag
* @param {function(): Promise<T> | T} computer function to compute the value if not cached
* @returns {Promise<T>} promise with the data
*/
async providePromise(identifier, etag, computer) {
const cacheEntry = await this.getPromise(identifier, etag);
if (cacheEntry !== undefined) return cacheEntry;
const result = await computer();
await this.storePromise(identifier, etag, result);
return result;
}
}
module.exports = CacheFacade;
module.exports.ItemCacheFacade = ItemCacheFacade;
module.exports.MultiItemCache = MultiItemCache;
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346/*MIT License http://www.opensource.org/licenses/mit-license.phpAuthor Tobias Koppers @sokra*/"use strict";const { forEachBail } = require("enhanced-resolve");const asyncLib = require("neo-async");const getLazyHashedEtag = require("./cache/getLazyHashedEtag");const mergeEtags = require("./cache/mergeEtags");/** @typedef {import("./Cache")} Cache *//** @typedef {import("./Cache").Etag} Etag *//** @typedef {import("./WebpackError")} WebpackError *//** @typedef {import("./cache/getLazyHashedEtag").HashableObject} HashableObject *//** @typedef {typeof import("./util/Hash")} HashConstructor *//*** @template T* @callback CallbackCache* @param {(WebpackError | null)=} err* @param {T=} result* @returns {void}*//*** @template T* @callback CallbackNormalErrorCache* @param {(Error | null)=} err* @param {T=} result* @returns {void}*/class MultiItemCache {/*** @param {ItemCacheFacade[]} items item caches*/constructor(items) {this._items = items;if (items.length === 1) return /** @type {any} */ (items[0]);}/*** @template T* @param {CallbackCache<T>} callback signals when the value is retrieved* @returns {void}*/get(callback) {forEachBail(this._items, (item, callback) => item.get(callback), callback);}/*** @template T* @returns {Promise<T>} promise with the data*/getPromise() {const next = i => {return this._items[i].getPromise().then(result => {if (result !== undefined) return result;if (++i < this._items.length) return next(i);});};return next(0);}/*** @template T* @param {T} data the value to store* @param {CallbackCache<void>} callback signals when the value is stored* @returns {void}*/store(data, callback) {asyncLib.each(this._items,(item, callback) => item.store(data, callback),callback);}/*** @template T* @param {T} data the value to store* @returns {Promise<void>} promise signals when the value is stored*/storePromise(data) {return Promise.all(this._items.map(item => item.storePromise(data))).then(() => {});}}class ItemCacheFacade {/*** @param {Cache} cache the root cache* @param {string} name the child cache item name* @param {Etag | null} etag the etag*/constructor(cache, name, etag) {this._cache = cache;this._name = name;this._etag = etag;}/*** @template T* @param {CallbackCache<T>} callback signals when the value is retrieved* @returns {void}*/get(callback) {this._cache.get(this._name, this._etag, callback);}/*** @template T* @returns {Promise<T>} promise with the data*/getPromise() {return new Promise((resolve, reject) => {this._cache.get(this._name, this._etag, (err, data) => {if (err) {reject(err);} else {resolve(data);}});});}/*** @template T* @param {T} data the value to store* @param {CallbackCache<void>} callback signals when the value is stored* @returns {void}*/store(data, callback) {this._cache.store(this._name, this._etag, data, callback);}/*** @template T* @param {T} data the value to store* @returns {Promise<void>} promise signals when the value is stored*/storePromise(data) {return new Promise((resolve, reject) => {this._cache.store(this._name, this._etag, data, err => {if (err) {reject(err);} else {resolve();}});});}/*** @template T* @param {function(CallbackNormalErrorCache<T>): void} computer function to compute the value if not cached* @param {CallbackNormalErrorCache<T>} callback signals when the value is retrieved* @returns {void}*/provide(computer, callback) {this.get((err, cacheEntry) => {if (err) return callback(err);if (cacheEntry !== undefined) return cacheEntry;computer((err, result) => {if (err) return callback(err);this.store(result, err => {if (err) return callback(err);callback(null, result);});});});}/*** @template T* @param {function(): Promise<T> | T} computer function to compute the value if not cached* @returns {Promise<T>} promise with the data*/async providePromise(computer) {const cacheEntry = await this.getPromise();if (cacheEntry !== undefined) return cacheEntry;const result = await computer();await this.storePromise(result);return result;}}class CacheFacade {/*** @param {Cache} cache the root cache* @param {string} name the child cache name* @param {string | HashConstructor} hashFunction the hash function to use*/constructor(cache, name, hashFunction) {this._cache = cache;this._name = name;this._hashFunction = hashFunction;}/*** @param {string} name the child cache name#* @returns {CacheFacade} child cache*/getChildCache(name) {return new CacheFacade(this._cache,`${this._name}|${name}`,this._hashFunction);}/*** @param {string} identifier the cache identifier* @param {Etag | null} etag the etag* @returns {ItemCacheFacade} item cache*/getItemCache(identifier, etag) {return new ItemCacheFacade(this._cache,`${this._name}|${identifier}`,etag);}/*** @param {HashableObject} obj an hashable object* @returns {Etag} an etag that is lazy hashed*/getLazyHashedEtag(obj) {return getLazyHashedEtag(obj, this._hashFunction);}/*** @param {Etag} a an etag* @param {Etag} b another etag* @returns {Etag} an etag that represents both*/mergeEtags(a, b) {return mergeEtags(a, b);}/*** @template T* @param {string} identifier the cache identifier* @param {Etag | null} etag the etag* @param {CallbackCache<T>} callback signals when the value is retrieved* @returns {void}*/get(identifier, etag, callback) {this._cache.get(`${this._name}|${identifier}`, etag, callback);}/*** @template T* @param {string} identifier the cache identifier* @param {Etag | null} etag the etag* @returns {Promise<T>} promise with the data*/getPromise(identifier, etag) {return new Promise((resolve, reject) => {this._cache.get(`${this._name}|${identifier}`, etag, (err, data) => {if (err) {reject(err);} else {resolve(data);}});});}/*** @template T* @param {string} identifier the cache identifier* @param {Etag | null} etag the etag* @param {T} data the value to store* @param {CallbackCache<void>} callback signals when the value is stored* @returns {void}*/store(identifier, etag, data, callback) {this._cache.store(`${this._name}|${identifier}`, etag, data, callback);}/*** @template T* @param {string} identifier the cache identifier* @param {Etag | null} etag the etag* @param {T} data the value to store* @returns {Promise<void>} promise signals when the value is stored*/storePromise(identifier, etag, data) {return new Promise((resolve, reject) => {this._cache.store(`${this._name}|${identifier}`, etag, data, err => {if (err) {reject(err);} else {resolve();}});});}/*** @template T* @param {string} identifier the cache identifier* @param {Etag | null} etag the etag* @param {function(CallbackNormalErrorCache<T>): void} computer function to compute the value if not cached* @param {CallbackNormalErrorCache<T>} callback signals when the value is retrieved* @returns {void}*/provide(identifier, etag, computer, callback) {this.get(identifier, etag, (err, cacheEntry) => {if (err) return callback(err);if (cacheEntry !== undefined) return cacheEntry;computer((err, result) => {if (err) return callback(err);this.store(identifier, etag, result, err => {if (err) return callback(err);callback(null, result);});});});}/*** @template T* @param {string} identifier the cache identifier* @param {Etag | null} etag the etag* @param {function(): Promise<T> | T} computer function to compute the value if not cached* @returns {Promise<T>} promise with the data*/async providePromise(identifier, etag, computer) {const cacheEntry = await this.getPromise(identifier, etag);if (cacheEntry !== undefined) return cacheEntry;const result = await computer();await this.storePromise(identifier, etag, result);return result;}}module.exports = CacheFacade;module.exports.ItemCacheFacade = ItemCacheFacade;module.exports.MultiItemCache = MultiItemCache;