diff options
Diffstat (limited to 'node_modules/webpack/lib/CacheFacade.js')
| -rw-r--r-- | node_modules/webpack/lib/CacheFacade.js | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/CacheFacade.js b/node_modules/webpack/lib/CacheFacade.js new file mode 100644 index 00000000..eece9631 --- /dev/null +++ b/node_modules/webpack/lib/CacheFacade.js @@ -0,0 +1,349 @@ +/* + 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 {(Error | null)=} err + * @param {(T | null)=} 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; + // eslint-disable-next-line no-constructor-return + 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() { + /** + * @param {number} i index + * @returns {Promise<T>} promise with the data + */ + const next = i => + 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; |
