reselect
Version:
Selectors for Redux.
1 lines • 76.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/devModeChecks/setGlobalDevModeChecks.ts","../src/weakMapMemoize.ts","../src/utils.ts","../src/createSelectorCreator.ts","../src/createStructuredSelector.ts","../src/lruMemoize.ts"],"sourcesContent":["import type { DevModeChecks } from '../types'\n\n/**\n * Global configuration for development mode checks. This specifies the default\n * frequency at which each development mode check should be performed.\n *\n * @since 5.0.0\n * @internal\n */\nexport const globalDevModeChecks: DevModeChecks = {\n inputStabilityCheck: 'once',\n identityFunctionCheck: 'once',\n cacheSizeCheck: 'once'\n}\n\n/**\n * Overrides the development mode checks settings for all selectors.\n *\n * Reselect performs additional checks in development mode to help identify and\n * warn about potential issues in selector behavior. This function allows you to\n * customize the behavior of these checks across all selectors in your application.\n *\n * **Note**: This setting can still be overridden per selector inside `createSelector`'s `options` object.\n * See {@link https://reselect.js.org/api/development-only-checks#per-selector-with-the-devmodechecks-option per-selector-configuration}\n * and {@linkcode CreateSelectorOptions.identityFunctionCheck identityFunctionCheck} for more details.\n *\n * _The development mode checks do not run in production builds._\n *\n * @param devModeChecks - An object specifying the desired settings for development mode checks. You can provide partial overrides. Unspecified settings will retain their current values.\n *\n * @example\n * ```ts\n * import { setGlobalDevModeChecks } from 'reselect'\n * import { DevModeChecks } from '../types'\n *\n * // Run only the first time the selector is called. (default)\n * setGlobalDevModeChecks({ inputStabilityCheck: 'once' })\n *\n * // Run every time the selector is called.\n * setGlobalDevModeChecks({ inputStabilityCheck: 'always' })\n *\n * // Never run the input stability check.\n * setGlobalDevModeChecks({ inputStabilityCheck: 'never' })\n *\n * // Run only the first time the selector is called. (default)\n * setGlobalDevModeChecks({ identityFunctionCheck: 'once' })\n *\n * // Run every time the selector is called.\n * setGlobalDevModeChecks({ identityFunctionCheck: 'always' })\n *\n * // Never run the identity function check.\n * setGlobalDevModeChecks({ identityFunctionCheck: 'never' })\n *\n * // Warn only the first time a `weakMapMemoize` cache passes the size threshold. (default)\n * setGlobalDevModeChecks({ cacheSizeCheck: 'once' })\n *\n * // Warn on every cache insertion past the size threshold.\n * setGlobalDevModeChecks({ cacheSizeCheck: 'always' })\n *\n * // Never run the cache size check.\n * setGlobalDevModeChecks({ cacheSizeCheck: 'never' })\n * ```\n * @see {@link https://reselect.js.org/api/development-only-checks Development-Only Checks}\n * @see {@link https://reselect.js.org/api/development-only-checks#globally-with-setglobaldevmodechecks global-configuration}\n *\n * @since 5.0.0\n * @public\n */\nexport const setGlobalDevModeChecks = (\n devModeChecks: Partial<DevModeChecks>\n) => {\n Object.assign(globalDevModeChecks, devModeChecks)\n}\n","// Original source:\n// - https://github.com/facebook/react/blob/0b974418c9a56f6c560298560265dcf4b65784bc/packages/react/src/ReactCache.js\n\nimport {\n CACHE_SIZE_CHECK_THRESHOLD,\n runCacheSizeCheck\n} from './devModeChecks/cacheSizeCheck'\nimport { globalDevModeChecks } from './devModeChecks/setGlobalDevModeChecks'\nimport type {\n AnyFunction,\n DefaultMemoizeFields,\n EqualityFn,\n Simplify\n} from './types'\n\nclass StrongRef<T> {\n constructor(private value: T) {}\n deref() {\n return this.value\n }\n}\n\n/**\n * @returns The {@linkcode StrongRef} if {@linkcode WeakRef} is not available.\n *\n * @since 5.1.2\n * @internal\n */\nconst getWeakRef = () =>\n typeof WeakRef === 'undefined'\n ? (StrongRef as unknown as typeof WeakRef)\n : WeakRef\n\nconst Ref = /* @__PURE__ */ getWeakRef()\n\nconst UNTERMINATED = 0\nconst TERMINATED = 1\n\ninterface UnterminatedCacheNode<T> {\n /**\n * Status, represents whether the cached computation returned a value or threw an error.\n */\n s: 0\n /**\n * Value, either the cached result or an error, depending on status.\n */\n v: void\n /**\n * Object cache, a `WeakMap` where non-primitive arguments are stored.\n */\n o: null | WeakMap<Function | Object, CacheNode<T>>\n /**\n * Primitive cache, a regular Map where primitive arguments are stored.\n */\n p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>\n}\n\ninterface TerminatedCacheNode<T> {\n /**\n * Status, represents whether the cached computation returned a value or threw an error.\n */\n s: 1\n /**\n * Value, either the cached result or an error, depending on status.\n */\n v: T\n /**\n * Object cache, a `WeakMap` where non-primitive arguments are stored.\n */\n o: null | WeakMap<Function | Object, CacheNode<T>>\n /**\n * Primitive cache, a regular `Map` where primitive arguments are stored.\n */\n p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>\n}\n\ntype CacheNode<T> = TerminatedCacheNode<T> | UnterminatedCacheNode<T>\n\nfunction createCacheNode<T>(): CacheNode<T> {\n return {\n s: UNTERMINATED,\n v: undefined,\n o: null,\n p: null\n }\n}\n\n/**\n * Configuration options for a memoization function utilizing `WeakMap` for\n * its caching mechanism.\n *\n * @template Result - The type of the return value of the memoized function.\n *\n * @since 5.0.0\n * @public\n */\nexport interface WeakMapMemoizeOptions<Result = any> {\n /**\n * If provided, used to compare a newly generated output value against previous values in the cache.\n * If a match is found, the old value is returned. This addresses the common\n * ```ts\n * todos.map(todo => todo.id)\n * ```\n * use case, where an update to another field in the original data causes a recalculation\n * due to changed references, but the output is still effectively the same.\n *\n * @since 5.0.0\n */\n resultEqualityCheck?: EqualityFn<Result>\n /**\n * Bounds how many results are retained for primitive arguments. By default\n * the cache grows without limit: object arguments are held in `WeakMap`s\n * and released by garbage collection, but primitive arguments are held in\n * regular `Map`s and are retained until {@linkcode DefaultMemoizeFields.clearCache clearCache}\n * is called. A selector that keeps seeing new primitive values (IDs,\n * pagination offsets, timestamps) therefore grows without bound.\n *\n * The bound is generational, not an LRU: after `maxSize` results have been\n * cached, the entire cache becomes the \"previous generation\" and a fresh\n * cache becomes current. Lookups that miss the current cache probe the\n * previous one, and a hit there is copied forward so it survives the next\n * generation change. When the generation changes again, the previous cache\n * is dropped wholesale. In practice this means:\n * - total retention is bounded at roughly `2 * maxSize` results\n * - a result that keeps getting used stays cached indefinitely\n * - a result that goes unused for a full generation is dropped with it,\n * in one batch, rather than entry by entry\n *\n * Must be a positive integer. There is no cost to the memoized function\n * when this option is not passed.\n *\n * Note that to bound a selector created by `createSelector`, `maxSize`\n * needs to be passed in both `memoizeOptions` and `argsMemoizeOptions` —\n * the arguments cache and the results cache are separate `weakMapMemoize`\n * instances.\n *\n * @since 5.3.0\n */\n maxSize?: number\n}\n\n/**\n * Derefences the argument if it is a Ref. Else if it is a value already, return it.\n *\n * @param r - the object to maybe deref\n * @returns The derefenced value if the argument is a Ref, else the argument value itself.\n */\nfunction maybeDeref(r: any) {\n if (r instanceof Ref) {\n return r.deref()\n }\n\n return r\n}\n\n/**\n * Creates a tree of `WeakMap`-based cache nodes based on the identity of the\n * arguments it's been called with (in this case, the extracted values from your input selectors).\n * This allows `weakMapMemoize` to have an effectively infinite cache size.\n * Cache results will be kept in memory as long as references to the arguments still exist,\n * and then cleared out as the arguments are garbage-collected.\n *\n * __Design Tradeoffs for `weakMapMemoize`:__\n * - Pros:\n * - It has an effectively infinite cache size by default, but you have no control over\n * how long values are kept in cache as it's based on garbage collection and `WeakMap`s.\n * Results cached for primitive arguments are retained until `clearCache` is called;\n * the {@linkcode WeakMapMemoizeOptions.maxSize maxSize} option bounds that growth.\n * - Cons:\n * - There's currently no way to alter the argument comparisons.\n * They're based on strict reference equality.\n * - It's roughly the same speed as `lruMemoize`, although likely a fraction slower.\n *\n * __Use Cases for `weakMapMemoize`:__\n * - This memoizer is likely best used for cases where you need to call the\n * same selector instance with many different arguments, such as a single\n * selector instance that is used in a list item component and called with\n * item IDs like:\n * ```ts\n * useSelector(state => selectSomeData(state, props.category))\n * ```\n * @param func - The function to be memoized.\n * @returns A memoized function with a `.clearCache()` method attached.\n *\n * @example\n * <caption>Using `createSelector`</caption>\n * ```ts\n * import { createSelector, weakMapMemoize } from 'reselect'\n *\n * interface RootState {\n * items: { id: number; category: string; name: string }[]\n * }\n *\n * const selectItemsByCategory = createSelector(\n * [\n * (state: RootState) => state.items,\n * (state: RootState, category: string) => category\n * ],\n * (items, category) => items.filter(item => item.category === category),\n * {\n * memoize: weakMapMemoize,\n * argsMemoize: weakMapMemoize\n * }\n * )\n * ```\n *\n * @example\n * <caption>Using `createSelectorCreator`</caption>\n * ```ts\n * import { createSelectorCreator, weakMapMemoize } from 'reselect'\n *\n * const createSelectorWeakMap = createSelectorCreator({ memoize: weakMapMemoize, argsMemoize: weakMapMemoize })\n *\n * const selectItemsByCategory = createSelectorWeakMap(\n * [\n * (state: RootState) => state.items,\n * (state: RootState, category: string) => category\n * ],\n * (items, category) => items.filter(item => item.category === category)\n * )\n * ```\n *\n * @template Func - The type of the function that is memoized.\n *\n * @see {@link https://reselect.js.org/api/weakMapMemoize `weakMapMemoize`}\n *\n * @since 5.0.0\n * @public\n * @experimental\n */\nexport function weakMapMemoize<Func extends AnyFunction>(\n func: Func,\n options: WeakMapMemoizeOptions<ReturnType<Func>> = {}\n) {\n let fnNode = createCacheNode()\n const { resultEqualityCheck, maxSize } = options\n\n // Generational bounding for `maxSize`: `prevNode` holds the demoted cache\n // tree, `insertionCount` counts primitive-Map insertions into the current\n // tree. Reaching `maxSize` flips generations at the end of that call.\n const useGenerations = maxSize !== undefined\n if (useGenerations && (!Number.isInteger(maxSize) || maxSize < 1)) {\n throw new TypeError(\n `maxSize must be a positive integer, received: ${maxSize}`\n )\n }\n let prevNode: CacheNode<any> | null = null\n let insertionCount = 0\n\n let lastResult: WeakRef<object> | undefined\n\n let resultsCount = 0\n\n let hasWarnedAboutCacheSize = false\n\n // Flip generations at the end of a call that cached something, never during\n // a walk, so a flip can never happen while pointers into the tree being\n // demoted are still live. The hit path never reaches this.\n function maybeFlipGenerations() {\n if (insertionCount >= (maxSize as number)) {\n prevNode = fnNode\n fnNode = createCacheNode()\n insertionCount = 0\n }\n }\n\n function memoized() {\n let cacheNode = fnNode\n const { length } = arguments\n for (let i = 0, l = length; i < l; i++) {\n const arg = arguments[i]\n if (\n typeof arg === 'function' ||\n (typeof arg === 'object' && arg !== null)\n ) {\n // Objects go into a WeakMap\n let objectCache = cacheNode.o\n if (objectCache === null) {\n cacheNode.o = objectCache = new WeakMap()\n }\n const objectNode = objectCache.get(arg)\n if (objectNode === undefined) {\n cacheNode = createCacheNode()\n objectCache.set(arg, cacheNode)\n } else {\n cacheNode = objectNode\n }\n } else {\n // Primitives go into a regular Map\n let primitiveCache = cacheNode.p\n if (primitiveCache === null) {\n cacheNode.p = primitiveCache = new Map()\n }\n const primitiveNode = primitiveCache.get(arg)\n if (primitiveNode === undefined) {\n cacheNode = createCacheNode()\n primitiveCache.set(arg, cacheNode)\n insertionCount++\n\n if (process.env.NODE_ENV !== 'production') {\n // A single primitive `Map` growing past the threshold means this\n // function keeps seeing new primitive values in the same argument\n // position, which is the unbounded-growth pattern from #635. The\n // size of one `Map` is checked rather than a total across the\n // tree: `Map`s nested under an object argument's `WeakMap` node\n // are released when that object is collected, so a total would\n // keep phantom counts for entries that are already gone and warn\n // about usage that is actually healthy.\n if (primitiveCache.size > CACHE_SIZE_CHECK_THRESHOLD) {\n const { cacheSizeCheck } = globalDevModeChecks\n if (\n cacheSizeCheck === 'always' ||\n (cacheSizeCheck === 'once' && !hasWarnedAboutCacheSize)\n ) {\n hasWarnedAboutCacheSize = true\n runCacheSizeCheck(primitiveCache.size, func.name)\n }\n }\n }\n } else {\n cacheNode = primitiveNode\n }\n }\n }\n\n // Return here rather than falling through to the writes below. Both would be\n // no-ops — `s` is already `TERMINATED` and `v` already holds this result —\n // but `v` stores a pointer, so re-storing it costs a GC write barrier on a\n // call that had nothing to record.\n if (cacheNode.s === TERMINATED) {\n return cacheNode.v\n }\n\n // The current tree has no result, but the previous generation might.\n // This probe only runs on a miss, so the hit path above is untouched.\n // A hit here is copied forward into the current node so it survives the\n // next flip, and returned without recomputing.\n if (prevNode !== null) {\n let prevCacheNode: CacheNode<any> | null = prevNode\n for (let i = 0, l = length; i < l; i++) {\n const arg = arguments[i]\n let next: CacheNode<any> | undefined\n if (\n typeof arg === 'function' ||\n (typeof arg === 'object' && arg !== null)\n ) {\n const prevObjectCache: CacheNode<any>['o'] = prevCacheNode.o\n next = prevObjectCache !== null ? prevObjectCache.get(arg) : undefined\n } else {\n const prevPrimitiveCache: CacheNode<any>['p'] = prevCacheNode.p\n next =\n prevPrimitiveCache !== null\n ? prevPrimitiveCache.get(arg)\n : undefined\n }\n if (next === undefined) {\n prevCacheNode = null\n break\n }\n prevCacheNode = next\n }\n if (prevCacheNode !== null && prevCacheNode.s === TERMINATED) {\n const promotedNode = cacheNode as unknown as TerminatedCacheNode<any>\n promotedNode.s = TERMINATED\n promotedNode.v = prevCacheNode.v\n maybeFlipGenerations()\n return prevCacheNode.v\n }\n }\n\n const terminatedNode = cacheNode as unknown as TerminatedCacheNode<any>\n\n // Allow errors to propagate\n let result = func.apply(null, arguments as unknown as any[])\n resultsCount++\n\n if (resultEqualityCheck) {\n // Deref lastResult if it is a Ref\n const lastResultValue = maybeDeref(lastResult)\n\n if (\n lastResultValue != null &&\n resultEqualityCheck(lastResultValue as ReturnType<Func>, result)\n ) {\n result = lastResultValue\n\n resultsCount !== 0 && resultsCount--\n }\n\n const needsWeakRef =\n (typeof result === 'object' && result !== null) ||\n typeof result === 'function'\n\n lastResult = needsWeakRef ? /* @__PURE__ */ new Ref(result) : result\n }\n\n terminatedNode.s = TERMINATED\n terminatedNode.v = result\n if (useGenerations) {\n maybeFlipGenerations()\n }\n return result\n }\n\n memoized.clearCache = () => {\n fnNode = createCacheNode()\n prevNode = null\n insertionCount = 0\n memoized.resetResultsCount()\n if (process.env.NODE_ENV !== 'production') {\n hasWarnedAboutCacheSize = false\n }\n }\n\n memoized.resultsCount = () => resultsCount\n\n memoized.resetResultsCount = () => {\n resultsCount = 0\n }\n\n return memoized as Func & Simplify<DefaultMemoizeFields>\n}\n","import type { Selector, SelectorArray } from './types'\n\nexport const NOT_FOUND = /* @__PURE__ */ Symbol('NOT_FOUND')\nexport type NOT_FOUND_TYPE = typeof NOT_FOUND\n\n/**\n * Assert that the provided value is a function. If the assertion fails,\n * a `TypeError` is thrown with an optional custom error message.\n *\n * @param func - The value to be checked.\n * @param errorMessage - An optional custom error message to use if the assertion fails.\n * @throws A `TypeError` if the assertion fails.\n */\nexport function assertIsFunction<FunctionType extends Function>(\n func: unknown,\n errorMessage = `expected a function, instead received ${typeof func}`\n): asserts func is FunctionType {\n if (typeof func !== 'function') {\n throw new TypeError(errorMessage)\n }\n}\n\n/**\n * Assert that the provided value is an object. If the assertion fails,\n * a `TypeError` is thrown with an optional custom error message.\n *\n * @param object - The value to be checked.\n * @param errorMessage - An optional custom error message to use if the assertion fails.\n * @throws A `TypeError` if the assertion fails.\n */\nexport function assertIsObject<ObjectType extends Record<string, unknown>>(\n object: unknown,\n errorMessage = `expected an object, instead received ${typeof object}`\n): asserts object is ObjectType {\n if (typeof object !== 'object') {\n throw new TypeError(errorMessage)\n }\n}\n\n/**\n * Assert that the provided array is an array of functions. If the assertion fails,\n * a `TypeError` is thrown with an optional custom error message.\n *\n * @param array - The array to be checked.\n * @param errorMessage - An optional custom error message to use if the assertion fails.\n * @throws A `TypeError` if the assertion fails.\n */\nexport function assertIsArrayOfFunctions<FunctionType extends Function>(\n array: unknown[],\n errorMessage = `expected all items to be functions, instead received the following types: `\n): asserts array is FunctionType[] {\n if (\n !array.every((item): item is FunctionType => typeof item === 'function')\n ) {\n const itemTypes = array\n .map(item =>\n typeof item === 'function'\n ? `function ${item.name || 'unnamed'}()`\n : typeof item\n )\n .join(', ')\n throw new TypeError(`${errorMessage}[${itemTypes}]`)\n }\n}\n\n/**\n * Ensure that the input is an array. If it's already an array, it's returned as is.\n * If it's not an array, it will be wrapped in a new array.\n *\n * @param item - The item to be checked.\n * @returns An array containing the input item. If the input is already an array, it's returned without modification.\n */\nexport const ensureIsArray = (item: unknown) => {\n return Array.isArray(item) ? item : [item]\n}\n\n/**\n * Extracts the \"dependencies\" / \"input selectors\" from the arguments of `createSelector`.\n *\n * @param createSelectorArgs - Arguments passed to `createSelector` as an array.\n * @returns An array of \"input selectors\" / \"dependencies\".\n * @throws A `TypeError` if any of the input selectors is not function.\n */\nexport function getDependencies(createSelectorArgs: unknown[]) {\n const dependencies = Array.isArray(createSelectorArgs[0])\n ? createSelectorArgs[0]\n : createSelectorArgs\n\n assertIsArrayOfFunctions<Selector>(\n dependencies,\n `createSelector expects all input-selectors to be functions, but received the following types: `\n )\n\n return dependencies as SelectorArray\n}\n\n/**\n * Runs each input selector and returns their collective results as an array.\n *\n * @param dependencies - An array of \"dependencies\" or \"input selectors\".\n * @param inputSelectorArgs - An array of arguments being passed to the input selectors.\n * @returns An array of input selector results.\n */\nexport function collectInputSelectorResults(\n dependencies: SelectorArray,\n inputSelectorArgs: unknown[] | IArguments\n) {\n const inputSelectorResults = []\n const { length } = dependencies\n for (let i = 0; i < length; i++) {\n // @ts-ignore\n // apply arguments instead of spreading and mutate a local list of params for performance.\n inputSelectorResults.push(dependencies[i].apply(null, inputSelectorArgs))\n }\n return inputSelectorResults\n}\n","import { weakMapMemoize } from './weakMapMemoize'\n\nimport type {\n Combiner,\n CreateSelectorOptions,\n DropFirstParameter,\n ExtractMemoizerFields,\n GetParamsFromSelectors,\n GetStateFromSelectors,\n InterruptRecursion,\n OutputSelector,\n Selector,\n SelectorArray,\n SetRequired,\n Simplify,\n UnknownMemoizer\n} from './types'\n\nimport { runIdentityFunctionCheck } from './devModeChecks/identityFunctionCheck'\nimport { runInputStabilityCheck } from './devModeChecks/inputStabilityCheck'\nimport { globalDevModeChecks } from './devModeChecks/setGlobalDevModeChecks'\nimport {\n assertIsFunction,\n collectInputSelectorResults,\n ensureIsArray,\n getDependencies\n} from './utils'\n\n/**\n * An instance of `createSelector`, customized with a given memoize implementation.\n *\n * @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).\n * @template ArgsMemoizeFunction - The type of the optional memoize function that is used to memoize the arguments passed into the output selector generated by `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.\n * @template StateType - The type of state that the selectors created with this selector creator will operate on.\n *\n * @public\n */\nexport interface CreateSelectorFunction<\n MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,\n ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,\n StateType = any\n> {\n /**\n * Creates a memoized selector function.\n *\n * @param createSelectorArgs - An arbitrary number of input selectors as separate inline arguments and a `combiner` function.\n * @returns A memoized output selector.\n *\n * @template InputSelectors - The type of the input selectors as an array.\n * @template Result - The return type of the `combiner` as well as the output selector.\n * @template OverrideMemoizeFunction - The type of the optional `memoize` function that could be passed into the options object to override the original `memoize` function that was initially passed into `createSelectorCreator`.\n * @template OverrideArgsMemoizeFunction - The type of the optional `argsMemoize` function that could be passed into the options object to override the original `argsMemoize` function that was initially passed into `createSelectorCreator`.\n *\n * @see {@link https://reselect.js.org/api/createselector `createSelector`}\n */\n <InputSelectors extends SelectorArray<StateType>, Result>(\n ...createSelectorArgs: [\n ...inputSelectors: InputSelectors,\n combiner: Combiner<InputSelectors, Result>\n ]\n ): OutputSelector<\n InputSelectors,\n Result,\n MemoizeFunction,\n ArgsMemoizeFunction\n > &\n InterruptRecursion\n\n /**\n * Creates a memoized selector function.\n *\n * @param createSelectorArgs - An arbitrary number of input selectors as separate inline arguments, a `combiner` function and an `options` object.\n * @returns A memoized output selector.\n *\n * @template InputSelectors - The type of the input selectors as an array.\n * @template Result - The return type of the `combiner` as well as the output selector.\n * @template OverrideMemoizeFunction - The type of the optional `memoize` function that could be passed into the options object to override the original `memoize` function that was initially passed into `createSelectorCreator`.\n * @template OverrideArgsMemoizeFunction - The type of the optional `argsMemoize` function that could be passed into the options object to override the original `argsMemoize` function that was initially passed into `createSelectorCreator`.\n *\n * @see {@link https://reselect.js.org/api/createselector `createSelector`}\n */\n <\n InputSelectors extends SelectorArray<StateType>,\n Result,\n OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,\n OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction\n >(\n ...createSelectorArgs: [\n ...inputSelectors: InputSelectors,\n combiner: Combiner<InputSelectors, Result>,\n createSelectorOptions: Simplify<\n CreateSelectorOptions<\n MemoizeFunction,\n ArgsMemoizeFunction,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n >\n >\n ]\n ): OutputSelector<\n InputSelectors,\n Result,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n > &\n InterruptRecursion\n\n /**\n * Creates a memoized selector function.\n *\n * @param inputSelectors - An array of input selectors.\n * @param combiner - A function that Combines the input selectors and returns an output selector. Otherwise known as the result function.\n * @param createSelectorOptions - An optional options object that allows for further customization per selector.\n * @returns A memoized output selector.\n *\n * @template InputSelectors - The type of the input selectors array.\n * @template Result - The return type of the `combiner` as well as the output selector.\n * @template OverrideMemoizeFunction - The type of the optional `memoize` function that could be passed into the options object to override the original `memoize` function that was initially passed into `createSelectorCreator`.\n * @template OverrideArgsMemoizeFunction - The type of the optional `argsMemoize` function that could be passed into the options object to override the original `argsMemoize` function that was initially passed into `createSelectorCreator`.\n *\n * @see {@link https://reselect.js.org/api/createselector `createSelector`}\n */\n <\n InputSelectors extends SelectorArray<StateType>,\n Result,\n OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,\n OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction\n >(\n inputSelectors: [...InputSelectors],\n combiner: Combiner<InputSelectors, Result>,\n createSelectorOptions?: Simplify<\n CreateSelectorOptions<\n MemoizeFunction,\n ArgsMemoizeFunction,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n >\n >\n ): OutputSelector<\n InputSelectors,\n Result,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n > &\n InterruptRecursion\n\n /**\n * Creates a \"pre-typed\" version of {@linkcode createSelector createSelector}\n * where the `state` type is predefined.\n *\n * This allows you to set the `state` type once, eliminating the need to\n * specify it with every {@linkcode createSelector createSelector} call.\n *\n * @returns A pre-typed `createSelector` with the state type already defined.\n *\n * @example\n * ```ts\n * import { createSelector } from 'reselect'\n *\n * export interface RootState {\n * todos: { id: number; completed: boolean }[]\n * alerts: { id: number; read: boolean }[]\n * }\n *\n * export const createAppSelector = createSelector.withTypes<RootState>()\n *\n * const selectTodoIds = createAppSelector(\n * [\n * // Type of `state` is set to `RootState`, no need to manually set the type\n * state => state.todos\n * ],\n * todos => todos.map(({ id }) => id)\n * )\n * ```\n * @template OverrideStateType - The specific type of state used by all selectors created with this selector creator.\n *\n * @see {@link https://reselect.js.org/api/createselector#defining-a-pre-typed-createselector `createSelector.withTypes`}\n *\n * @since 5.1.0\n */\n withTypes: <OverrideStateType extends StateType>() => CreateSelectorFunction<\n MemoizeFunction,\n ArgsMemoizeFunction,\n OverrideStateType\n >\n}\n\n/**\n * Creates a selector creator function with the specified memoization function\n * and options for customizing memoization behavior.\n *\n * @param options - An options object containing the `memoize` function responsible for memoizing the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`). It also provides additional options for customizing memoization. While the `memoize` property is mandatory, the rest are optional.\n * @returns A customized `createSelector` function.\n *\n * @example\n * ```ts\n * const customCreateSelector = createSelectorCreator({\n * memoize: customMemoize, // Function to be used to memoize `resultFunc`\n * memoizeOptions: [memoizeOption1, memoizeOption2], // Options passed to `customMemoize` as the second argument onwards\n * argsMemoize: customArgsMemoize, // Function to be used to memoize the selector's arguments\n * argsMemoizeOptions: [argsMemoizeOption1, argsMemoizeOption2] // Options passed to `customArgsMemoize` as the second argument onwards\n * })\n *\n * const customSelector = customCreateSelector(\n * [inputSelector1, inputSelector2],\n * resultFunc // `resultFunc` will be passed as the first argument to `customMemoize`\n * )\n *\n * customSelector(\n * ...selectorArgs // Will be memoized by `customArgsMemoize`\n * )\n * ```\n *\n * @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).\n * @template ArgsMemoizeFunction - The type of the optional memoize function that is used to memoize the arguments passed into the output selector generated by `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.\n *\n * @see {@link https://reselect.js.org/api/createSelectorCreator#using-options-since-500 `createSelectorCreator`}\n *\n * @since 5.0.0\n * @public\n */\nexport function createSelectorCreator<\n MemoizeFunction extends UnknownMemoizer,\n ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize\n>(\n options: Simplify<\n SetRequired<\n CreateSelectorOptions<\n typeof weakMapMemoize,\n typeof weakMapMemoize,\n MemoizeFunction,\n ArgsMemoizeFunction\n >,\n 'memoize'\n >\n >\n): CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>\n\n/**\n * Creates a selector creator function with the specified memoization function\n * and options for customizing memoization behavior.\n *\n * @param memoize - The `memoize` function responsible for memoizing the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).\n * @param memoizeOptionsFromArgs - Optional configuration options for the memoization function. These options are then passed to the memoize function as the second argument onwards.\n * @returns A customized `createSelector` function.\n *\n * @example\n * ```ts\n * const customCreateSelector = createSelectorCreator(customMemoize, // Function to be used to memoize `resultFunc`\n * option1, // Will be passed as second argument to `customMemoize`\n * option2, // Will be passed as third argument to `customMemoize`\n * option3 // Will be passed as fourth argument to `customMemoize`\n * )\n *\n * const customSelector = customCreateSelector(\n * [inputSelector1, inputSelector2],\n * resultFunc // `resultFunc` will be passed as the first argument to `customMemoize`\n * )\n * ```\n *\n * @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).\n *\n * @see {@link https://reselect.js.org/api/createSelectorCreator#using-memoize-and-memoizeoptions `createSelectorCreator`}\n *\n * @public\n */\nexport function createSelectorCreator<MemoizeFunction extends UnknownMemoizer>(\n memoize: MemoizeFunction,\n ...memoizeOptionsFromArgs: DropFirstParameter<MemoizeFunction>\n): CreateSelectorFunction<MemoizeFunction>\n\n/**\n * Creates a selector creator function with the specified memoization\n * function and options for customizing memoization behavior.\n *\n * @param memoizeOrOptions - Either A `memoize` function or an `options` object containing the `memoize` function.\n * @param memoizeOptionsFromArgs - Optional configuration options for the memoization function. These options are then passed to the memoize function as the second argument onwards.\n * @returns A customized `createSelector` function.\n *\n * @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).\n * @template ArgsMemoizeFunction - The type of the optional memoize function that is used to memoize the arguments passed into the output selector generated by `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.\n * @template MemoizeOrOptions - The type of the first argument. It can either be a `memoize` function or an `options` object containing the `memoize` function.\n */\nexport function createSelectorCreator<\n MemoizeFunction extends UnknownMemoizer,\n ArgsMemoizeFunction extends UnknownMemoizer,\n MemoizeOrOptions extends\n | MemoizeFunction\n | SetRequired<\n CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,\n 'memoize'\n >\n>(\n memoizeOrOptions: MemoizeOrOptions,\n ...memoizeOptionsFromArgs: MemoizeOrOptions extends SetRequired<\n CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,\n 'memoize'\n >\n ? never\n : DropFirstParameter<MemoizeFunction>\n) {\n /** options initially passed into `createSelectorCreator`. */\n const createSelectorCreatorOptions: SetRequired<\n CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,\n 'memoize'\n > = typeof memoizeOrOptions === 'function'\n ? {\n memoize: memoizeOrOptions as MemoizeFunction,\n memoizeOptions: memoizeOptionsFromArgs\n }\n : memoizeOrOptions\n\n const createSelector = <\n InputSelectors extends SelectorArray,\n Result,\n OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,\n OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction\n >(\n ...createSelectorArgs: [\n ...inputSelectors: [...InputSelectors],\n combiner: Combiner<InputSelectors, Result>,\n createSelectorOptions?: CreateSelectorOptions<\n MemoizeFunction,\n ArgsMemoizeFunction,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n >\n ]\n ) => {\n let recomputations = 0\n let dependencyRecomputations = 0\n let lastResult: Result\n\n // Due to the intricacies of rest params, we can't do an optional arg after `...createSelectorArgs`.\n // So, start by declaring the default value here.\n // (And yes, the words 'memoize' and 'options' appear too many times in this next sequence.)\n let directlyPassedOptions: CreateSelectorOptions<\n MemoizeFunction,\n ArgsMemoizeFunction,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n > = {}\n\n // Normally, the result func or \"combiner\" is the last arg\n let resultFunc = createSelectorArgs.pop() as\n | Combiner<InputSelectors, Result>\n | CreateSelectorOptions<\n MemoizeFunction,\n ArgsMemoizeFunction,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n >\n\n // If the result func is actually an _object_, assume it's our options object\n if (typeof resultFunc === 'object') {\n directlyPassedOptions = resultFunc\n // and pop the real result func off\n resultFunc = createSelectorArgs.pop() as Combiner<InputSelectors, Result>\n }\n\n assertIsFunction(\n resultFunc,\n `createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]`\n )\n\n // Determine which set of options we're using. Prefer options passed directly,\n // but fall back to options given to `createSelectorCreator`.\n const combinedOptions = {\n ...createSelectorCreatorOptions,\n ...directlyPassedOptions\n }\n\n const {\n memoize,\n memoizeOptions = [],\n argsMemoize = weakMapMemoize,\n argsMemoizeOptions = []\n } = combinedOptions\n\n // Simplifying assumption: it's unlikely that the first options arg of the provided memoizer\n // is an array. In most libs I've looked at, it's an equality function or options object.\n // Based on that, if `memoizeOptions` _is_ an array, we assume it's a full\n // user-provided array of options. Otherwise, it must be just the _first_ arg, and so\n // we wrap it in an array so we can apply it.\n const finalMemoizeOptions = ensureIsArray(memoizeOptions)\n const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions)\n const dependencies = getDependencies(createSelectorArgs) as InputSelectors\n\n const memoizedResultFunc = memoize(function recomputationWrapper() {\n recomputations++\n // apply arguments instead of spreading for performance.\n // @ts-ignore\n return (resultFunc as Combiner<InputSelectors, Result>).apply(\n null,\n arguments as unknown as Parameters<Combiner<InputSelectors, Result>>\n )\n }, ...finalMemoizeOptions) as Combiner<InputSelectors, Result> &\n ExtractMemoizerFields<OverrideMemoizeFunction>\n\n let firstRun = true\n\n // If a selector is called with the exact same arguments we don't need to traverse our dependencies again.\n const selector = argsMemoize(function dependenciesChecker() {\n dependencyRecomputations++\n /** Return values of input selectors which the `resultFunc` takes as arguments. */\n // Inlined instead of calling `collectInputSelectorResults`: handing\n // `arguments` to another function makes it escape, which forces V8 to\n // materialize it on the heap every call. As an operand of `.apply` it stays\n // in the frame. (The dev block below still passes it, but that is compiled\n // out of production builds.)\n //\n // Sizing the array up front instead of growing it from `[]` by `push` is\n // the larger half of the win. Arity-specialized literals measured no better\n // than this, so one path serves every dependency count.\n const { length } = dependencies\n const inputSelectorResults = new Array(length)\n for (let i = 0; i < length; i++) {\n // @ts-ignore\n inputSelectorResults[i] = dependencies[i].apply(null, arguments)\n }\n\n // apply arguments instead of spreading for performance.\n // @ts-ignore\n lastResult = memoizedResultFunc.apply(null, inputSelectorResults)\n\n if (process.env.NODE_ENV !== 'production') {\n // Resolved without building the four objects `getDevModeChecksExecutionInfo`\n // returns. This runs on every dependency recomputation, and by default both\n // checks are `'once'` — so from the second one onwards those objects were\n // allocated only to be read for two booleans and discarded.\n //\n // `hasOwnProperty` rather than `??`, to keep the semantics of the spread\n // this replaces: an override that explicitly sets a check to `undefined`\n // silences it, where `??` would fall back to the global setting. The\n // common case has no overrides at all and reads the global directly.\n const { devModeChecks } = combinedOptions\n const identityFunctionCheck =\n devModeChecks !== undefined &&\n Object.prototype.hasOwnProperty.call(\n devModeChecks,\n 'identityFunctionCheck'\n )\n ? devModeChecks.identityFunctionCheck\n : globalDevModeChecks.identityFunctionCheck\n const inputStabilityCheck =\n devModeChecks !== undefined &&\n Object.prototype.hasOwnProperty.call(\n devModeChecks,\n 'inputStabilityCheck'\n )\n ? devModeChecks.inputStabilityCheck\n : globalDevModeChecks.inputStabilityCheck\n\n if (\n identityFunctionCheck === 'always' ||\n (identityFunctionCheck === 'once' && firstRun)\n ) {\n runIdentityFunctionCheck(\n resultFunc as Combiner<InputSelectors, Result>,\n inputSelectorResults,\n lastResult\n )\n }\n\n if (\n inputStabilityCheck === 'always' ||\n (inputStabilityCheck === 'once' && firstRun)\n ) {\n // make a second copy of the params, to check if we got the same results\n const inputSelectorResultsCopy = collectInputSelectorResults(\n dependencies,\n arguments\n )\n\n runInputStabilityCheck(\n { inputSelectorResults, inputSelectorResultsCopy },\n { memoize, memoizeOptions: finalMemoizeOptions },\n arguments\n )\n }\n\n if (firstRun) firstRun = false\n }\n\n return lastResult\n }, ...finalArgsMemoizeOptions) as unknown as Selector<\n GetStateFromSelectors<InputSelectors>,\n Result,\n GetParamsFromSelectors<InputSelectors>\n > &\n ExtractMemoizerFields<OverrideArgsMemoizeFunction>\n\n return Object.assign(selector, {\n resultFunc,\n memoizedResultFunc,\n dependencies,\n dependencyRecomputations: () => dependencyRecomputations,\n resetDependencyRecomputations: () => {\n dependencyRecomputations = 0\n },\n lastResult: () => lastResult,\n recomputations: () => recomputations,\n resetRecomputations: () => {\n recomputations = 0\n },\n memoize,\n argsMemoize\n }) as OutputSelector<\n InputSelectors,\n Result,\n OverrideMemoizeFunction,\n OverrideArgsMemoizeFunction\n >\n }\n\n Object.assign(createSelector, {\n withTypes: () => createSelector\n })\n\n return createSelector as CreateSelectorFunction<\n MemoizeFunction,\n ArgsMemoizeFunction\n >\n}\n\n/**\n * Accepts one or more \"input selectors\" (either as separate arguments or a single array),\n * a single \"result function\" / \"combiner\", and an optional options object, and\n * generates a memoized selector function.\n *\n * @see {@link https://reselect.js.org/api/createSelector `createSelector`}\n *\n * @public\n */\nexport const createSelector =\n /* #__PURE__ */ createSelectorCreator(weakMapMemoize)\n","import { createSelector } from './createSelectorCreator'\n\nimport type { CreateSelectorFunction } from './createSelectorCreator'\nimport type {\n InterruptRecursion,\n ObjectValuesToTuple,\n OutputSelector,\n Selector,\n Simplify,\n UnknownMemoizer\n} from './types'\nimport { assertIsObject } from './utils'\nimport type { weakMapMemoize } from './weakMapMemoize'\n\n/**\n * Represents a mapping of selectors to their return types.\n *\n * @template TObject - An object type where each property is a selector function.\n *\n * @public\n */\nexport type SelectorResultsMap<TObject extends SelectorsObject> = {\n [Key in keyof TObject]: ReturnType<TObject[Key]>\n}\n\n/**\n * Represents a mapping of selectors for each key in a given root state.\n *\n * This type is a utility that takes a root state object type and\n * generates a corresponding set of selectors. Each selector is associated\n * with a key in the root state, allowing for the selection\n * of specific parts of the state.\n *\n * @template RootState - The type of the root state object.\n *\n * @since 5.0.0\n * @public\n */\nexport type RootStateSelectors<RootState = any> = {\n [Key in keyof RootState]: Selector<RootState, RootState[Key], []>\n}\n\n/**\n * @deprecated Please use {@linkcode StructuredSelectorCreator.withTypes createStructuredSelector.withTypes<RootState>()} instead. This type will be removed in the future.\n * @template RootState - The type of the root state object.\n *\n * @since 5.0.0\n * @public\n */\nexport type TypedStructuredSelectorCreator<RootState = any> =\n /**\n * A convenience function that simplifies returning an object\n * made up of selector results.\n *\n * @param inputSelectorsObject - A key value pair consisting of input selectors.\n * @param selectorCreator - A custom selector creator function. It defaults to `createSelector`.\n * @returns A memoized structured selector.\n *\n * @example\n * <caption>Modern Use Case</caption>\n * ```ts\n * import { createSelector, createStructuredSelector } from 'reselect'\n *\n * interface RootState {\n * todos: {\n * id: number\n * completed: boolean\n * title: string\n * description: string\n * }[]\n * alerts: { id: number; read: boolean }[]\n * }\n *\n * // This:\n * const structuredSelector = createStructuredSelector(\n * {\n * todos: (state: RootState) => state.todos,\n * alerts: (state: RootState) => state.alerts,\n * todoById: (state: RootState, id: number) => state.todos[id]\n * },\n * createSelector\n * )\n *\n * // Is essentially the same as this:\n * const selector = createSelector(\n * [\n * (state: RootState) => state.todos,\n * (state: RootState) => state.alerts,\n * (state: RootState, id: number) => state.todos[id]\n * ],\n * (todos, alerts, todoById) => {\n * return {\n * todos,\n * alerts,\n * todoById\n * }\n * }\n * )\n * ```\n *\n * @example\n * <caption>In your component:</caption>\n * ```tsx\n * import type { RootState } from 'createStructuredSelector/modernUseCase'\n * import { structuredSelector } from 'createStructuredSelector/modernUseCase'\n * import type { FC } from 'react'\n * import { useSelector } from 'react-redux'\n *\n * interface Props {\n * id: number\n * }\n *\n * const MyComponent: FC<Props> = ({ id }) => {\n * const { todos, alerts, todoById } = useSelector((state: RootState) =>\n * structuredSelector(state, id)\n * )\n *\n * return (\n * <div>\n * Next to do is:\n * <h2>{todoById.title}</h2>\n * <p>Description: {todoById.description}</p>\n * <ul>\n * <h3>All other to dos:</h3>\n * {todos.map(todo => (\n * <li key={todo.id}>{todo.title}</li>\n * ))}\n * </ul>\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * <caption>Simple Use Case</caption>\n * ```ts\n * const selectA = state => state.a\n * const selectB = state => state.b\n *\n * // The result function in the following selector\n * // is simply building an object from the input selectors\n * const structuredSelector = createSelector(selectA, selectB, (a, b) => ({\n * a,\n * b\n * }))\n *\n * const result = structuredSelector({ a: 1, b: 2 }) // will produce { x: 1, y: 2 }\n * ```\n *\n * @template InputSelectorsObject - The shape of the input selectors object.\n * @template MemoizeFunction - The type of the memoize function that is used to create the structured selector. It defaults to `weakMapMemoize`.\n * @template ArgsMemoizeFunction - The type of the of the memoize function that is used to memoize the arguments passed into the generated structured selector. It defaults to `weakMapMemoize`.\n *\n * @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`}\n */\n <\n InputSelectorsObject extends RootStateSelectors<RootState> = RootStateSelectors<RootState>,\n MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,\n ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize\n >(\n inputSelectorsObject: InputSelectorsObject,\n selectorCreator?: CreateSelectorFunction<\n MemoizeFunction,\n ArgsMemoizeFunction\n >\n ) => OutputSelector<\n ObjectValuesToTuple<InputSelectorsObject>,\n Simplify<SelectorResultsMap<InputSelectorsObject>>,\n MemoizeFunction,\n ArgsMemoizeFunction\n > &\n InterruptRecursion\n\n/**\n * Represents an object where each property is a selector function.\n *\n * @template StateType - The type of state that all the selectors operate on.\n *\n * @public\n */\nexport type SelectorsObject<StateType = any> = Record<\n string,\n Selector<StateType>\n>\n\n/**\n * It provides a way to create structured selectors.\n * The structured selector can take multiple input selectors\n * and map their output to an object with specific keys.\n *\n * @template StateType - The type of state that the structured selectors created with this structured selector creator will operate on.\n *\n * @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`}\n *\n * @public\n */\nexport interface StructuredSelectorCreator<StateType = any> {\n /**\n * A convenience function that simplifies returning an object\n * made up of selector results.\n *\n * @param inputSelectorsObject - A key value pair consisting of input selectors.\n * @param selectorCreator - A custom selector creator function. It defaults to `createSelector`.\n * @returns A memoized structured selector.\n *\n * @example\n * <caption>Modern Use Case</caption>\n * ```ts\n * import { createSelector, createStructuredSelector } from 'reselect'\n *\n * interface RootState {\n * todos: {\n * id: number\n * completed: boolean\n * title: string\n * description: string\n * }[]\n * alerts: { id: number; read: boolean }[]\n * }\n *\n * // This:\n * const structuredSelector = createStructuredSelector(\n * {\n * todos: (state: RootState) => state.todos,\n * alerts: (state: RootState) => state.alerts,\n * todoById: (state: RootState, id: number) => state.todos[id]\n * },\n * createSelector\n * )\n *\n * // Is essentially the same as this:\n * const selector = createSelector(\n * [\n * (state: RootState) => state.todos,\n * (state: RootState) => state.alerts,\n * (state: RootState, id: number) => state.todos[id]\n * ],\n * (todos, alerts, todoById) => {\n * return {\n * todos,\n * alerts,\n * todoById\n * }\n * }\n * )\n * ```\n *\n * @example\n * <caption>In your component:</caption>\n * ```tsx\n * import type { RootState } from 'createStructuredSelector/modernUseCase'\n * import { structuredSelector } from 'createStructuredSelector/modernUseCase'\n * import type { FC } from 'react'\n * import { useSelector } from 'react-redux'\n *\n * interface Props {\n * id: number\n * }\n *\n * const MyComponent: FC<Props> = ({ id }) => {\n * const { todos, alerts, todoById } = useSelector((state: RootState) =>\n * structuredSelector(state, id)\n * )\n *\n * return (\n * <div>\n * Next to do is:\n * <h2>{todoById.title}</h2>\n * <p>Description: {todoById.description}</p>\n * <ul>\n * <h3>All other to dos:</h3>\n * {todos.map(todo => (\n * <li key={todo.id}>{todo.title}</li>\n * ))}\n * </ul>\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * <caption>Simple Use Case</caption>\n * ```ts\n * const selectA = state => state.a\n * const selectB = state => state.b\n *\n * // The result function in the following selector\n * // is simply building an object from the input selectors\n * const structuredSelector = createSelector(selectA, selectB, (a, b) => ({\n * a,\n * b\n * }))\n *\n * const result = structuredSelector({ a: 1, b: 2 }) // will produce { x: 1, y: 2 }\n * ```\n *\n * @template InputSelectorsObject - The shape of the input selectors object.\n * @template MemoizeFunction - The type of the memoize function that is used to create the structured selector. It defaults to `weakMapMemoize`.\n * @template ArgsMemoizeFunction - The type of the of the memoize function that is used to memoize the arguments passed into the generated structured selector. It defaults to `weakMapMemoize`.\n *\n * @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`}\n */\n <\n InputSelectorsObject extends SelectorsObject<StateType>,\n MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,\n ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize\n >(\n inputSelectorsObject: InputSelectorsObject,\n selectorCreator?: CreateSelectorFunction<\n MemoizeFunction,\n ArgsMemoizeFunction\n >\n ): OutputSelector<\n ObjectValuesToTuple<InputSelectorsObject>,\n Simplify<SelectorResultsMap<InputSelectorsObject>>,\n MemoizeFunction,\n ArgsMemoizeFunction\n > &\n InterruptRecursion\n\n /**\n * Creates a \"pre-typed\" version of\n * {@linkcode createStructuredSelector createStructuredSelector}\n * where the `state` type is predefined.\n *\n * This allows you to set the `state` type once, eliminating the need to\n * specify it with every\n * {@linkcode createStructuredSelector createStructuredSelector} call.\n *\n * @returns A pre-typed `createStructuredSelector` with the state type already defined.\n *\n * @example\n * ```ts\n * import { createStructuredSelector } from 'reselect'\n *\n * export interface RootState {\n * todos: { id: number; completed: boolean }[]\n * alerts: { id: number; read: boolean }[]\n * }\n *\n * export const createStructuredAppSelector =\n * createStructuredSelector.withTypes<RootState>()\n *\n * const structuredAppSelector = createStructuredAppSelector({\n * // Type of `state` is set to `RootState`, no need to manually set the type\n * todos: state => state.todos,\n * alerts: state => state.alerts,\n * todoById: (state, id: number) => state.todos[id]\n * })\n *\n * ```\n * @template OverrideStateType - The specific type of state used by all structured selectors created with this structured selector creator.\n *\n * @see {@link https://reselect.js.org/api/createstructuredselector#defining-a-pre-typed-createstructuredselector `createSelector.withTypes`}\n *\n * @since 5.1.0\n */\n withTypes: <\n OverrideStateType extends StateType\n >() => StructuredSelectorCreator<OverrideStateType>\n}\n\n/**\n * A convenience function that simplifies returning an object\n * made up of selector results.\n *\n * @param inputSelectorsObject - A key value pair consisting of input selectors.\n * @param selectorCreator - A custom selector creator function. It defaults to `createSelector`.\n * @returns A memoized structured selector.\n *\n * @example\n * <caption>Modern Use Case</caption>\n * ```ts\n * import { createSelector, createStructuredSelector } from 'reselect'\n *\n * interface RootState {\n * todos: {\n * id: number\n * completed: boolean\n * title: string\n * description: string\n * }[]\n * alerts: { id: number; read: boolean }[]\n * }\n *\n * // This:\n * const structuredSelector = createStructuredSelector(\n * {\n * todos: (state: RootState) => state.todos,\n * alerts: (state: RootState) => state.alerts,\n * todoById: (state: RootState, id: number) => state.todos[id]\n * },\n * createSelector\n * )\n *\n * // Is essentially the same as this:\n * const selector = createSelector(\n * [\n * (state: RootState) => state.todos,\n * (state: RootState) => state.alerts,\n * (state: RootState, id: number) => state.todos[id]\n * ],\n * (todos, alerts, todoById) => {\n * return {\n * todos,\n * alerts,\n * todoById\n * }\n * }\n * )\n * ```\n *\n * @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`}\n *\n * @public\n */\nexport const createStructuredSelector: StructuredSelectorCreator =\n /* @__PURE__ */ Object.assign(\n <\n InputSelectorsObject extends SelectorsObject,\n MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,\n ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize\n >(\n inputSelectorsObject: InputSelectorsObject,\n selectorCreator: CreateSelectorFunction<\n MemoizeFunction,\n ArgsMemoizeFunction\n > = createSelector as CreateSelectorFunction<\n MemoizeFunction,\n ArgsMemoizeFunction\n >\n ) => {\n assertIsObject(\n inputSelectorsObject,\n 'createStructuredSelector expects first argument to be an object ' +\n `where each property is a selector, instead received a ${typeof inputSelectorsObject}`\n )\n const inputSelectorKeys = Object.keys(inputSelectorsObject)\n const dependencies = inputSelectorKeys.map(\n key => inputSelectorsObject[key]\n )\n const structuredSelector = selectorCreator(\n dependencies,\n (...inputSelectorResults: any[]) => {\n return inputSelectorResults.reduce((composition, value, index) => {\n composition[inputSelectorKeys[index]] = value\n return composition\n }, {})\n }\n )\n return structuredSelector\n },\n { withTypes: () => createStructuredSelector }\n ) as StructuredSelectorCreator\n","import type {\n AnyFunction,\n DefaultMemoizeFields,\n EqualityFn,\n Simplify\n} from './types'\n\nimport type { NOT_FOUND_TYPE } from './utils'\nimport { NOT_FOUND } from './utils'\n\n// Cache implementation based on Erik Rasmussen's `lru-memoize`:\n// https://github.com/erikras/lru-memoize\n\ninterface Entry {\n key: unknown\n value: unknown\n}\n\ninterface Cache {\n get(key: unknown): unknown | NOT_FOUND_TYPE\n put(key: unknown, value: unknown): void\n /**\n * Returns the first cached entry whose value `resultEqualityCheck` accepts, or\n * `undefined`.\n *\n * Searching inside the cache rather than handing out an array of entries is\n * what lets the caller drop its `entries.find(entry => ...)` callback, and\n * that callback was expensive in a way that does not look like it from the\n * source. It captured `value`, a local of `memoized`, so V8 had to allocate\n * that local in a heap context rather than a register — on every call,\n * including the cache hits that never reach this code at all. Removing it\n * measured 1.12x on the hit path. Keep this signature callback-free.\n *\n * Searching in place also avoids the one-element array the singleton cache\n * used to build per miss, which is worth a further ~10% on the miss path when\n * `resultEqualityCheck` is set.\n */\n findMatchingEntry(\n value: unknown,\n resultEqualityCheck: EqualityFn\n ): Entry | undefined\n clear(): void\n}\n\nfunction createSingletonCache(equals: EqualityFn): Cache {\n let entry: Entry | undefined\n return {\n get(key: unknown) {\n if (entry && equals(entry.key, key)) {\n return entry.value\n }\n\n return NOT_FOUND\n },\n\n put(key: unknown, value: unknown) {\n entry = { key, value }\n },\n\n findMatchingEntry(value: unknown, resultEqualityCheck: EqualityFn) {\n const current = entry\n\n return current !== undefined && resultEqualityCheck(current.value, value)\n ? current\n : undefined\n },\n\n clear() {\n entry = undefined\n }\n }\n}\n\nfunction createLruCache(maxSize: number, equals: EqualityFn): Cache {\n let entries: Entry[] = []\n\n function get(key: unknown) {\n const cacheIndex = entries.findIndex(entry => equals(entry.key, key))\n\n // We found a cached entry\n if (cacheIndex > -1) {\n const entry = entries[cacheIndex]\n\n // Cached entry not at top of cache, move it to the top\n if (cacheIndex > 0) {\n entries.splice(cacheIndex, 1)\n entries.unshift(entry)\n }\n\n return entry.value\n }\n\n // No entry found in cache, return sentinel\n return NOT_FOUND\n }\n\n // Only ever called after `get` has returned `NOT_FOUND` for the same key,\n // so there is no need to search the entries again here.\n function put(key: unknown, value: unknown) {\n // TODO Is unshift slow?\n entries.unshift({ key, value })\n if (entries.length > maxSize) {\n entries.pop()\n }\n }\n\n function findMatchingEntry(value: unknown, resultEqualityCheck: EqualityFn) {\n // Read the array once up front, the way `Array.prototype.find` would, so a\n // `resultEqualityCheck` that clears the cache mid-search behaves as before\n // instead of walking off the end of a replaced array.\n const currentEntries = entries\n const { length } = currentEntries\n\n for (let i = 0; i < length; i++) {\n const entry = currentEntries[i]\n\n if (resultEqualityCheck(entry.value, value)) {\n return entry\n }\n }\n\n return undefined\n }\n\n function clear() {\n entries = []\n }\n\n return { get, put, findMatchingEntry, clear }\n}\n\n/**\n * Runs a simple reference equality check.\n * What {@linkcode lruMemoize lruMemoize} uses by default.\n *\n * **Note**: This function was previously known as `defaultEqualityCheck`.\n *\n * @public\n */\nexport const referenceEqualityCheck: EqualityFn = (a, b) => a === b\n\nexport function createCacheKeyComparator(equalityCheck: EqualityFn) {\n return function areArgumentsShallowlyEqual(\n prev: unknown[] | IArguments | null,\n next: unknown[] | IArguments | null\n ): boolean {\n if (prev === null || next === null || prev.length !== next.length) {\n return false\n }\n\n // Do this in a for loop (and not a `forEach` or an `every`) so we can determine equality as fast as possible.\n const { length } = prev\n for (let i = 0; i < length; i++) {\n if (!equalityCheck(prev[i], next[i])) {\n return false\n }\n }\n\n return true\n }\n}\n\n/**\n * Options for configuring the behavior of a function memoized with\n * LRU (Least Recently Used) caching.\n *\n * @template Result - The type of the return value of the memoized function.\n *\n * @public\n */\nexport interface LruMemoizeOptions<Result = any> {\n /**\n * Function used to compare the individual arguments of the\n * provided calculation function.\n *\n * @default referenceEqualityCheck\n */\n equalityCheck?: EqualityFn\n\n /**\n * If provided, used to compare a newly generated output value against\n * previous values in the cache. If a match is found,\n * the old value is returned. This addresses the common\n * ```ts\n * todos.map(todo => todo.id)\n * ```\n * use case, where an update to another field in the original data causes\n * a recalculation due to changed references, but the output is still\n * effectively the same.\n *\n * @since 4.1.0\n */\n resultEqualityCheck?: EqualityFn<Result>\n\n /**\n * The maximum size of the cache used by the selector.\n * A size greater than 1 means the selector will use an\n * LRU (Least Recently Used) cache, allowing for the caching of multiple\n * results based on different sets of arguments.\n *\n * @default 1\n */\n maxSize?: number\n}\n\n/**\n * Creates a memoized version of a function with an optional\n * LRU (Least Recently Used) cache. The memoized function uses a cache to\n * store computed values. Depending on the `maxSize` option, it will use\n * either a singleton cache (for a single entry) or an\n * LRU cache (for multiple entries).\n *\n * **Note**: This function was previously known as `defaultMemoize`.\n *\n * @param func - The function to be memoized.\n * @param equalityCheckOrOptions - Either an equality check function or an options object.\n * @returns A memoized function with a `.clearCache()` method attached.\n *\n * @template Func - The type of the function that is memoized.\n *\n * @see {@link https://reselect.js.org/api/lruMemoize `lruMemoize`}\n *\n * @public\n */\nexport function lruMemoize<Func extends AnyFunction>(\n func: Func,\n equalityCheckOrOptions?: EqualityFn | LruMemoizeOptions<ReturnType<Func>>\n) {\n const providedOptions =\n typeof equalityCheckOrOptions === 'object'\n ? equalityCheckOrOptions\n : { equalityCheck: equalityCheckOrOptions }\n\n const {\n equalityCheck = referenceEqualityCheck,\n maxSize = 1,\n resultEqualityCheck\n } = providedOptions\n\n const comparator = createCacheKeyComparator(equalityCheck)\n\n let resultsCount = 0\n\n const cache =\n maxSize <= 1\n ? createSingletonCache(comparator)\n : createLruCache(maxSize, comparator)\n\n function memoized() {\n let value = cache.get(arguments) as ReturnType<Func>\n if (value === NOT_FOUND) {\n // apply arguments instead of spreading for performance.\n // @ts-ignore\n value = func.apply(null, arguments) as ReturnType<Func>\n resultsCount++\n\n if (resultEqualityCheck) {\n const matchingEntry = cache.findMatchingEntry(\n value,\n resultEqualityCheck as EqualityFn\n )\n\n if (matchingEntry) {\n value = matchingEntry.value as ReturnType<Func>\n resultsCount !== 0 && resultsCount--\n }\n }\n\n cache.put(arguments, value)\n }\n return value\n }\n\n memoized.clearCache = () => {\n cache.clear()\n memoized.resetResultsCount()\n }\n\n memoized.resultsCount = () => resultsCount\n\n memoized.resetResultsCount = () => {\n resultsCount = 0\n }\n\n return memoized as Func & Simplify<DefaultMemoizeFields>\n}\n"],"mappings":"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","names":["globalDevModeChecks","setGlobalDevModeChecks","devModeChecks","StrongRef","value","getWeakRef","Ref","UNTERMINATED","TERMINATED","createCacheNode","maybeDeref","r","weakMapMemoize","func","options","fnNode","resultEqualityCheck","maxSize","useGenerations","prevNode","insertionCount","lastResult","resultsCount","hasWarnedAboutCacheSize","maybeFlipGenerations","memoized","cacheNode","length","i","l","arg","objectCache","objectNode","primitiveCache","primitiveNode","prevCacheNode","next","prevObjectCache","prevPrimitiveCache","promotedNode","terminatedNode","result","lastResultValue","NOT_FOUND","assertIsFunction","func","errorMessage","assertIsObject","object","assertIsArrayOfFunctions","array","item","itemTypes","ensureIsArray","getDependencies","createSelectorArgs","dependencies","createSelectorCreator","memoizeOrOptions","memoizeOptionsFromArgs","createSelectorCreatorOptions","createSelector","createSelectorArgs","recomputations","dependencyRecomputations","lastResult","directlyPassedOptions","resultFunc","assertIsFunction","combinedOptions","memoize","memoizeOptions","argsMemoize","weakMapMemoize","argsMemoizeOptions","finalMemoizeOptions","ensureIsArray","finalArgsMemoizeOptions","dependencies","getDependencies","memoizedResultFunc","firstRun","selector","length","inputSelectorResults","i","createStructuredSelector","inputSelectorsObject","selectorCreator","createSelector","assertIsObject","inputSelectorKeys","dependencies","key","inputSelectorResults","composition","value","index","createSingletonCache","equals","entry","key","NOT_FOUND","value","resultEqualityCheck","current","createLruCache","maxSize","entries","get","cacheIndex","put","findMatchingEntry","currentEntries","length","i","clear","referenceEqualityCheck","a","b","createCacheKeyComparator","equalityCheck","prev","next","lruMemoize","func","equalityCheckOrOptions","providedOptions","comparator","resultsCount","cache","memoized","matchingEntry"]}