    /** * This class is used to manage simple, LRU caches. It provides an absolutely minimal * container interface. It is created like this: * *      this.itemCache = new Ext.util.Cache({ *          miss: function (key) { *              return new CacheItem(key); *          } *      }); * * The `{@link #miss}` abstract method must be implemented by either a derived class or * at the instance level as shown above. * * Once the cache exists and it can handle cache misses, the cache is used like so: * *      var item = this.itemCache.get(key); * * The `key` is some value that uniquely identifies the cached item. * * In some cases, creating the cache item may require more than just the lookup key. In * that case, any extra arguments passed to `get` will be passed to `miss`. * *      this.otherCache = new Ext.util.Cache({ *          miss: function (key, extra) { *              return new CacheItem(key, extra); *          } *      }); * *      var item = this.otherCache.get(key, extra); * * To process items as they are removed, you can provide an `{@link #evict}` method. The * stock method is `Ext.emptyFn` and so does nothing. * * For example: * *      this.itemCache = new Ext.util.Cache({ *          miss: function (key) { *              return new CacheItem(key); *          }, * *          evict: function (key, cacheItem) { *              cacheItem.destroy(); *          } *      }); * * @class Ext.util.Cache * @private * @since 5.1.0 */(function (Cache, prototype) {// @define Ext.util.Cache      // NOTE: We have to implement this class old-school because it is used by the     // platformConfig class processor (so Ext.define is not yet ready for action).     (Ext.util || (Ext.util = {})).Cache = Cache = function (config) {        var me = this,            head;         if (config) {            Ext.apply(me, config);        }         // Give all entries the same object shape.         me.head = head = {            //<debug>             id: (me.seed = 0),            //</debug>             key: null,            value: null        };         me.map = {};         head.next = head.prev = head;    };     Cache.prototype = prototype = {        /**         * @cfg {Number} maxSize The maximum size the cache is allowed to grow to before         * further additions cause removal of the least recently used entry.         */        maxSize: 100,         /**         * @property {Number} count          * The number of items in this cache.         * @readonly         */        count: 0,         /**         * This method is called by `{@link #get}` when the key is not found in the cache.         * The implementation of this method should create the (expensive) value and return         * it. Whatever arguments were passed to `{@link #get}` will be passed on to this         * method.         *         * @param {String} key The cache lookup key for the item.         * @param {Object...} args Any other arguments originally passed to `{@link #get}`.         * @method miss         * @abstract         * @protected         */         /**         * Removes all items from this cache.         */        clear: function () {            var me = this,                head = me.head,                entry = head.next;             head.next = head.prev = head;             if (!me.evict.$nullFn) {                for ( ; entry !== head; entry = entry.next) {                    me.evict(entry.key, entry.value);                }            }             me.count = 0;        },         /**         * Calls the given function `fn` for each item in the cache. The items will be passed         * to `fn` from most-to-least recently used.         * @param {Function} fn The function to call for each cache item.         * @param {String} fn.key The cache key for the item.         * @param {Object} fn.value The value in the cache for the item.         * @param {Object} [scope] The `this` pointer to use for `fn`.         */        each: function (fn, scope) {            scope = scope || this;             for (var head = this.head, ent = head.next; ent !== head; ent = ent.next) {                if (fn.call(scope, ent.key, ent.value)) {                    break;                }            }        },         /**         * Finds an item in this cache and returns its value. If the item is present, it is         * shuffled into the MRU (most-recently-used) position as necessary. If the item is         * missing, the `{@link #miss}` method is called to create the item.         *         * @param {String} key The cache key of the item.         * @param {Object...} args Arguments for the `miss` method should it be needed.         * @return {Object} The cached object.         */        get: function (key) {            var me = this,                head = me.head,                map = me.map,                entry = map[key];             if (entry) {                if (entry.prev !== head) {                    // The entry is not at the front, so remove it and insert it at the front                     // (to make it the MRU - Most Recently Used).                     me.unlinkEntry(entry);                    me.linkEntry(entry);                }            } else {                map[key] = entry = {                    //<debug>                     id: ++me.seed,                    //</debug>                     key: key,                    value: me.miss.apply(me, arguments)                };                 me.linkEntry(entry);                ++me.count;                 while (me.count > me.maxSize) {                    me.unlinkEntry(head.prev, true);                    --me.count;                }            }             return entry.value;        },         //-------------------------------------------------------------------------         // Internals          /**         * This method is called internally from `{@link #get}` when the cache is full and         * the least-recently-used (LRU) item has been removed.         *         * @param {String} key The cache lookup key for the item being removed.         * @param {Object} value The cache value (returned by `{@link #miss}`) for the item         * being removed.         * @method evict         * @template         * @protected         */        evict: Ext.emptyFn,         /**         * Inserts the given entry at the front (MRU) end of the entry list.         * @param {Object} entry The cache item entry.         * @private         */        linkEntry: function (entry) {            var head = this.head,                first = head.next;             entry.next = first;            entry.prev = head;            head.next = entry;            first.prev = entry;        },         /**         * Removes the given entry from the entry list.         * @param {Object} entry The cache item entry.         * @param {Boolean} evicted Pass `true` if `{@link #evict}` should be called.         * @private         */        unlinkEntry: function (entry, evicted) {            var next = entry.next,                prev = entry.prev;             prev.next = next;            next.prev = prev;             if (evicted) {                this.evict(entry.key, entry.value);            }        }    };     prototype.destroy = prototype.clear;}());