123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- // Cache implementation based on Erik Rasmussen's `lru-memoize`:
- // https://github.com/erikras/lru-memoize
- var NOT_FOUND = 'NOT_FOUND';
- function createSingletonCache(equals) {
- var entry;
- return {
- get: function get(key) {
- if (entry && equals(entry.key, key)) {
- return entry.value;
- }
- return NOT_FOUND;
- },
- put: function put(key, value) {
- entry = {
- key: key,
- value: value
- };
- },
- getEntries: function getEntries() {
- return entry ? [entry] : [];
- },
- clear: function clear() {
- entry = undefined;
- }
- };
- }
- function createLruCache(maxSize, equals) {
- var entries = [];
- function get(key) {
- var cacheIndex = entries.findIndex(function (entry) {
- return equals(key, entry.key);
- }); // We found a cached entry
- if (cacheIndex > -1) {
- var entry = entries[cacheIndex]; // Cached entry not at top of cache, move it to the top
- if (cacheIndex > 0) {
- entries.splice(cacheIndex, 1);
- entries.unshift(entry);
- }
- return entry.value;
- } // No entry found in cache, return sentinel
- return NOT_FOUND;
- }
- function put(key, value) {
- if (get(key) === NOT_FOUND) {
- // TODO Is unshift slow?
- entries.unshift({
- key: key,
- value: value
- });
- if (entries.length > maxSize) {
- entries.pop();
- }
- }
- }
- function getEntries() {
- return entries;
- }
- function clear() {
- entries = [];
- }
- return {
- get: get,
- put: put,
- getEntries: getEntries,
- clear: clear
- };
- }
- export var defaultEqualityCheck = function defaultEqualityCheck(a, b) {
- return a === b;
- };
- export function createCacheKeyComparator(equalityCheck) {
- return function areArgumentsShallowlyEqual(prev, next) {
- if (prev === null || next === null || prev.length !== next.length) {
- return false;
- } // Do this in a for loop (and not a `forEach` or an `every`) so we can determine equality as fast as possible.
- var length = prev.length;
- for (var i = 0; i < length; i++) {
- if (!equalityCheck(prev[i], next[i])) {
- return false;
- }
- }
- return true;
- };
- }
- // defaultMemoize now supports a configurable cache size with LRU behavior,
- // and optional comparison of the result value with existing values
- export function defaultMemoize(func, equalityCheckOrOptions) {
- var providedOptions = typeof equalityCheckOrOptions === 'object' ? equalityCheckOrOptions : {
- equalityCheck: equalityCheckOrOptions
- };
- var _providedOptions$equa = providedOptions.equalityCheck,
- equalityCheck = _providedOptions$equa === void 0 ? defaultEqualityCheck : _providedOptions$equa,
- _providedOptions$maxS = providedOptions.maxSize,
- maxSize = _providedOptions$maxS === void 0 ? 1 : _providedOptions$maxS,
- resultEqualityCheck = providedOptions.resultEqualityCheck;
- var comparator = createCacheKeyComparator(equalityCheck);
- var cache = maxSize === 1 ? createSingletonCache(comparator) : createLruCache(maxSize, comparator); // we reference arguments instead of spreading them for performance reasons
- function memoized() {
- var value = cache.get(arguments);
- if (value === NOT_FOUND) {
- // @ts-ignore
- value = func.apply(null, arguments);
- if (resultEqualityCheck) {
- var entries = cache.getEntries();
- var matchingEntry = entries.find(function (entry) {
- return resultEqualityCheck(entry.value, value);
- });
- if (matchingEntry) {
- value = matchingEntry.value;
- }
- }
- cache.put(arguments, value);
- }
- return value;
- }
- memoized.clearCache = function () {
- return cache.clear();
- };
- return memoized;
- }
|