Buckets:
| import type { | |
| AnyFunction, | |
| DefaultMemoizeFields, | |
| EqualityFn, | |
| Simplify | |
| } from './types' | |
| import type { NOT_FOUND_TYPE } from './utils' | |
| import { NOT_FOUND } from './utils' | |
| // Cache implementation based on Erik Rasmussen's `lru-memoize`: | |
| // https://github.com/erikras/lru-memoize | |
| interface Entry { | |
| key: unknown | |
| value: unknown | |
| } | |
| interface Cache { | |
| get(key: unknown): unknown | NOT_FOUND_TYPE | |
| put(key: unknown, value: unknown): void | |
| getEntries(): Entry[] | |
| clear(): void | |
| } | |
| function createSingletonCache(equals: EqualityFn): Cache { | |
| let entry: Entry | undefined | |
| return { | |
| get(key: unknown) { | |
| if (entry && equals(entry.key, key)) { | |
| return entry.value | |
| } | |
| return NOT_FOUND | |
| }, | |
| put(key: unknown, value: unknown) { | |
| entry = { key, value } | |
| }, | |
| getEntries() { | |
| return entry ? [entry] : [] | |
| }, | |
| clear() { | |
| entry = undefined | |
| } | |
| } | |
| } | |
| function createLruCache(maxSize: number, equals: EqualityFn): Cache { | |
| let entries: Entry[] = [] | |
| function get(key: unknown) { | |
| const cacheIndex = entries.findIndex(entry => equals(key, entry.key)) | |
| // We found a cached entry | |
| if (cacheIndex > -1) { | |
| const 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: unknown, value: unknown) { | |
| if (get(key) === NOT_FOUND) { | |
| // TODO Is unshift slow? | |
| entries.unshift({ key, value }) | |
| if (entries.length > maxSize) { | |
| entries.pop() | |
| } | |
| } | |
| } | |
| function getEntries() { | |
| return entries | |
| } | |
| function clear() { | |
| entries = [] | |
| } | |
| return { get, put, getEntries, clear } | |
| } | |
| /** | |
| * Runs a simple reference equality check. | |
| * What {@linkcode lruMemoize lruMemoize} uses by default. | |
| * | |
| * **Note**: This function was previously known as `defaultEqualityCheck`. | |
| * | |
| * @public | |
| */ | |
| export const referenceEqualityCheck: EqualityFn = (a, b) => a === b | |
| export function createCacheKeyComparator(equalityCheck: EqualityFn) { | |
| return function areArgumentsShallowlyEqual( | |
| prev: unknown[] | IArguments | null, | |
| next: unknown[] | IArguments | null | |
| ): boolean { | |
| 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. | |
| const { length } = prev | |
| for (let i = 0; i < length; i++) { | |
| if (!equalityCheck(prev[i], next[i])) { | |
| return false | |
| } | |
| } | |
| return true | |
| } | |
| } | |
| /** | |
| * Options for configuring the behavior of a function memoized with | |
| * LRU (Least Recently Used) caching. | |
| * | |
| * @template Result - The type of the return value of the memoized function. | |
| * | |
| * @public | |
| */ | |
| export interface LruMemoizeOptions<Result = any> { | |
| /** | |
| * Function used to compare the individual arguments of the | |
| * provided calculation function. | |
| * | |
| * @default referenceEqualityCheck | |
| */ | |
| equalityCheck?: EqualityFn | |
| /** | |
| * If provided, used to compare a newly generated output value against | |
| * previous values in the cache. If a match is found, | |
| * the old value is returned. This addresses the common | |
| * ```ts | |
| * todos.map(todo => todo.id) | |
| * ``` | |
| * use case, where an update to another field in the original data causes | |
| * a recalculation due to changed references, but the output is still | |
| * effectively the same. | |
| * | |
| * @since 4.1.0 | |
| */ | |
| resultEqualityCheck?: EqualityFn<Result> | |
| /** | |
| * The maximum size of the cache used by the selector. | |
| * A size greater than 1 means the selector will use an | |
| * LRU (Least Recently Used) cache, allowing for the caching of multiple | |
| * results based on different sets of arguments. | |
| * | |
| * @default 1 | |
| */ | |
| maxSize?: number | |
| } | |
| /** | |
| * Creates a memoized version of a function with an optional | |
| * LRU (Least Recently Used) cache. The memoized function uses a cache to | |
| * store computed values. Depending on the `maxSize` option, it will use | |
| * either a singleton cache (for a single entry) or an | |
| * LRU cache (for multiple entries). | |
| * | |
| * **Note**: This function was previously known as `defaultMemoize`. | |
| * | |
| * @param func - The function to be memoized. | |
| * @param equalityCheckOrOptions - Either an equality check function or an options object. | |
| * @returns A memoized function with a `.clearCache()` method attached. | |
| * | |
| * @template Func - The type of the function that is memoized. | |
| * | |
| * @see {@link https://reselect.js.org/api/lruMemoize `lruMemoize`} | |
| * | |
| * @public | |
| */ | |
| export function lruMemoize<Func extends AnyFunction>( | |
| func: Func, | |
| equalityCheckOrOptions?: EqualityFn | LruMemoizeOptions<ReturnType<Func>> | |
| ) { | |
| const providedOptions = | |
| typeof equalityCheckOrOptions === 'object' | |
| ? equalityCheckOrOptions | |
| : { equalityCheck: equalityCheckOrOptions } | |
| const { | |
| equalityCheck = referenceEqualityCheck, | |
| maxSize = 1, | |
| resultEqualityCheck | |
| } = providedOptions | |
| const comparator = createCacheKeyComparator(equalityCheck) | |
| let resultsCount = 0 | |
| const cache = | |
| maxSize <= 1 | |
| ? createSingletonCache(comparator) | |
| : createLruCache(maxSize, comparator) | |
| function memoized() { | |
| let value = cache.get(arguments) as ReturnType<Func> | |
| if (value === NOT_FOUND) { | |
| // apply arguments instead of spreading for performance. | |
| // @ts-ignore | |
| value = func.apply(null, arguments) as ReturnType<Func> | |
| resultsCount++ | |
| if (resultEqualityCheck) { | |
| const entries = cache.getEntries() | |
| const matchingEntry = entries.find(entry => | |
| resultEqualityCheck(entry.value as ReturnType<Func>, value) | |
| ) | |
| if (matchingEntry) { | |
| value = matchingEntry.value as ReturnType<Func> | |
| resultsCount !== 0 && resultsCount-- | |
| } | |
| } | |
| cache.put(arguments, value) | |
| } | |
| return value | |
| } | |
| memoized.clearCache = () => { | |
| cache.clear() | |
| memoized.resetResultsCount() | |
| } | |
| memoized.resultsCount = () => resultsCount | |
| memoized.resetResultsCount = () => { | |
| resultsCount = 0 | |
| } | |
| return memoized as Func & Simplify<DefaultMemoizeFields> | |
| } | |
Xet Storage Details
- Size:
- 6.54 kB
- Xet hash:
- 600e12e2a097f10d74bb13736dfa93f18770e8980e3ac634fae73877d0c8bc79
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.