| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 | /*	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;
 |