Build NapCat Artifacts / Windows Loader Test (push) Canceled after 0s
Build NapCat Artifacts / Type Check & Test (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Framework (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Shell (push) Canceled after 0s
494 lines
20 KiB
Plaintext
494 lines
20 KiB
Plaintext
import { weakMapMemoize } from './weakMapMemoize'
|
|
|
|
import type {
|
|
Combiner,
|
|
CreateSelectorOptions,
|
|
DropFirstParameter,
|
|
ExtractMemoizerFields,
|
|
GetParamsFromSelectors,
|
|
GetStateFromSelectors,
|
|
InterruptRecursion,
|
|
OutputSelector,
|
|
Selector,
|
|
SelectorArray,
|
|
SetRequired,
|
|
Simplify,
|
|
UnknownMemoizer
|
|
} from './types'
|
|
|
|
import {
|
|
assertIsFunction,
|
|
collectInputSelectorResults,
|
|
ensureIsArray,
|
|
getDependencies,
|
|
getDevModeChecksExecutionInfo
|
|
} from './utils'
|
|
|
|
/**
|
|
* An instance of `createSelector`, customized with a given memoize implementation.
|
|
*
|
|
* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).
|
|
* @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.
|
|
* @template StateType - The type of state that the selectors created with this selector creator will operate on.
|
|
*
|
|
* @public
|
|
*/
|
|
export interface CreateSelectorFunction<
|
|
MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
|
|
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
|
|
StateType = any
|
|
> {
|
|
/**
|
|
* Creates a memoized selector function.
|
|
*
|
|
* @param createSelectorArgs - An arbitrary number of input selectors as separate inline arguments and a `combiner` function.
|
|
* @returns A memoized output selector.
|
|
*
|
|
* @template InputSelectors - The type of the input selectors as an array.
|
|
* @template Result - The return type of the `combiner` as well as the output selector.
|
|
* @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`.
|
|
* @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`.
|
|
*
|
|
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
|
|
*/
|
|
<InputSelectors extends SelectorArray<StateType>, Result>(
|
|
...createSelectorArgs: [
|
|
...inputSelectors: InputSelectors,
|
|
combiner: Combiner<InputSelectors, Result>
|
|
]
|
|
): OutputSelector<
|
|
InputSelectors,
|
|
Result,
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction
|
|
> &
|
|
InterruptRecursion
|
|
|
|
/**
|
|
* Creates a memoized selector function.
|
|
*
|
|
* @param createSelectorArgs - An arbitrary number of input selectors as separate inline arguments, a `combiner` function and an `options` object.
|
|
* @returns A memoized output selector.
|
|
*
|
|
* @template InputSelectors - The type of the input selectors as an array.
|
|
* @template Result - The return type of the `combiner` as well as the output selector.
|
|
* @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`.
|
|
* @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`.
|
|
*
|
|
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
|
|
*/
|
|
<
|
|
InputSelectors extends SelectorArray<StateType>,
|
|
Result,
|
|
OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,
|
|
OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction
|
|
>(
|
|
...createSelectorArgs: [
|
|
...inputSelectors: InputSelectors,
|
|
combiner: Combiner<InputSelectors, Result>,
|
|
createSelectorOptions: Simplify<
|
|
CreateSelectorOptions<
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
>
|
|
>
|
|
]
|
|
): OutputSelector<
|
|
InputSelectors,
|
|
Result,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
> &
|
|
InterruptRecursion
|
|
|
|
/**
|
|
* Creates a memoized selector function.
|
|
*
|
|
* @param inputSelectors - An array of input selectors.
|
|
* @param combiner - A function that Combines the input selectors and returns an output selector. Otherwise known as the result function.
|
|
* @param createSelectorOptions - An optional options object that allows for further customization per selector.
|
|
* @returns A memoized output selector.
|
|
*
|
|
* @template InputSelectors - The type of the input selectors array.
|
|
* @template Result - The return type of the `combiner` as well as the output selector.
|
|
* @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`.
|
|
* @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`.
|
|
*
|
|
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
|
|
*/
|
|
<
|
|
InputSelectors extends SelectorArray<StateType>,
|
|
Result,
|
|
OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,
|
|
OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction
|
|
>(
|
|
inputSelectors: [...InputSelectors],
|
|
combiner: Combiner<InputSelectors, Result>,
|
|
createSelectorOptions?: Simplify<
|
|
CreateSelectorOptions<
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
>
|
|
>
|
|
): OutputSelector<
|
|
InputSelectors,
|
|
Result,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
> &
|
|
InterruptRecursion
|
|
|
|
/**
|
|
* Creates a "pre-typed" version of {@linkcode createSelector createSelector}
|
|
* where the `state` type is predefined.
|
|
*
|
|
* This allows you to set the `state` type once, eliminating the need to
|
|
* specify it with every {@linkcode createSelector createSelector} call.
|
|
*
|
|
* @returns A pre-typed `createSelector` with the state type already defined.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import { createSelector } from 'reselect'
|
|
*
|
|
* export interface RootState {
|
|
* todos: { id: number; completed: boolean }[]
|
|
* alerts: { id: number; read: boolean }[]
|
|
* }
|
|
*
|
|
* export const createAppSelector = createSelector.withTypes<RootState>()
|
|
*
|
|
* const selectTodoIds = createAppSelector(
|
|
* [
|
|
* // Type of `state` is set to `RootState`, no need to manually set the type
|
|
* state => state.todos
|
|
* ],
|
|
* todos => todos.map(({ id }) => id)
|
|
* )
|
|
* ```
|
|
* @template OverrideStateType - The specific type of state used by all selectors created with this selector creator.
|
|
*
|
|
* @see {@link https://reselect.js.org/api/createselector#defining-a-pre-typed-createselector `createSelector.withTypes`}
|
|
*
|
|
* @since 5.1.0
|
|
*/
|
|
withTypes: <OverrideStateType extends StateType>() => CreateSelectorFunction<
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction,
|
|
OverrideStateType
|
|
>
|
|
}
|
|
|
|
/**
|
|
* Creates a selector creator function with the specified memoization function
|
|
* and options for customizing memoization behavior.
|
|
*
|
|
* @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.
|
|
* @returns A customized `createSelector` function.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const customCreateSelector = createSelectorCreator({
|
|
* memoize: customMemoize, // Function to be used to memoize `resultFunc`
|
|
* memoizeOptions: [memoizeOption1, memoizeOption2], // Options passed to `customMemoize` as the second argument onwards
|
|
* argsMemoize: customArgsMemoize, // Function to be used to memoize the selector's arguments
|
|
* argsMemoizeOptions: [argsMemoizeOption1, argsMemoizeOption2] // Options passed to `customArgsMemoize` as the second argument onwards
|
|
* })
|
|
*
|
|
* const customSelector = customCreateSelector(
|
|
* [inputSelector1, inputSelector2],
|
|
* resultFunc // `resultFunc` will be passed as the first argument to `customMemoize`
|
|
* )
|
|
*
|
|
* customSelector(
|
|
* ...selectorArgs // Will be memoized by `customArgsMemoize`
|
|
* )
|
|
* ```
|
|
*
|
|
* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).
|
|
* @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.
|
|
*
|
|
* @see {@link https://reselect.js.org/api/createSelectorCreator#using-options-since-500 `createSelectorCreator`}
|
|
*
|
|
* @since 5.0.0
|
|
* @public
|
|
*/
|
|
export function createSelectorCreator<
|
|
MemoizeFunction extends UnknownMemoizer,
|
|
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize
|
|
>(
|
|
options: Simplify<
|
|
SetRequired<
|
|
CreateSelectorOptions<
|
|
typeof weakMapMemoize,
|
|
typeof weakMapMemoize,
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction
|
|
>,
|
|
'memoize'
|
|
>
|
|
>
|
|
): CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>
|
|
|
|
/**
|
|
* Creates a selector creator function with the specified memoization function
|
|
* and options for customizing memoization behavior.
|
|
*
|
|
* @param memoize - The `memoize` function responsible for memoizing the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).
|
|
* @param memoizeOptionsFromArgs - Optional configuration options for the memoization function. These options are then passed to the memoize function as the second argument onwards.
|
|
* @returns A customized `createSelector` function.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const customCreateSelector = createSelectorCreator(customMemoize, // Function to be used to memoize `resultFunc`
|
|
* option1, // Will be passed as second argument to `customMemoize`
|
|
* option2, // Will be passed as third argument to `customMemoize`
|
|
* option3 // Will be passed as fourth argument to `customMemoize`
|
|
* )
|
|
*
|
|
* const customSelector = customCreateSelector(
|
|
* [inputSelector1, inputSelector2],
|
|
* resultFunc // `resultFunc` will be passed as the first argument to `customMemoize`
|
|
* )
|
|
* ```
|
|
*
|
|
* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).
|
|
*
|
|
* @see {@link https://reselect.js.org/api/createSelectorCreator#using-memoize-and-memoizeoptions `createSelectorCreator`}
|
|
*
|
|
* @public
|
|
*/
|
|
export function createSelectorCreator<MemoizeFunction extends UnknownMemoizer>(
|
|
memoize: MemoizeFunction,
|
|
...memoizeOptionsFromArgs: DropFirstParameter<MemoizeFunction>
|
|
): CreateSelectorFunction<MemoizeFunction>
|
|
|
|
/**
|
|
* Creates a selector creator function with the specified memoization
|
|
* function and options for customizing memoization behavior.
|
|
*
|
|
* @param memoizeOrOptions - Either A `memoize` function or an `options` object containing the `memoize` function.
|
|
* @param memoizeOptionsFromArgs - Optional configuration options for the memoization function. These options are then passed to the memoize function as the second argument onwards.
|
|
* @returns A customized `createSelector` function.
|
|
*
|
|
* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`).
|
|
* @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.
|
|
* @template MemoizeOrOptions - The type of the first argument. It can either be a `memoize` function or an `options` object containing the `memoize` function.
|
|
*/
|
|
export function createSelectorCreator<
|
|
MemoizeFunction extends UnknownMemoizer,
|
|
ArgsMemoizeFunction extends UnknownMemoizer,
|
|
MemoizeOrOptions extends
|
|
| MemoizeFunction
|
|
| SetRequired<
|
|
CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,
|
|
'memoize'
|
|
>
|
|
>(
|
|
memoizeOrOptions: MemoizeOrOptions,
|
|
...memoizeOptionsFromArgs: MemoizeOrOptions extends SetRequired<
|
|
CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,
|
|
'memoize'
|
|
>
|
|
? never
|
|
: DropFirstParameter<MemoizeFunction>
|
|
) {
|
|
/** options initially passed into `createSelectorCreator`. */
|
|
const createSelectorCreatorOptions: SetRequired<
|
|
CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,
|
|
'memoize'
|
|
> = typeof memoizeOrOptions === 'function'
|
|
? {
|
|
memoize: memoizeOrOptions as MemoizeFunction,
|
|
memoizeOptions: memoizeOptionsFromArgs
|
|
}
|
|
: memoizeOrOptions
|
|
|
|
const createSelector = <
|
|
InputSelectors extends SelectorArray,
|
|
Result,
|
|
OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,
|
|
OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction
|
|
>(
|
|
...createSelectorArgs: [
|
|
...inputSelectors: [...InputSelectors],
|
|
combiner: Combiner<InputSelectors, Result>,
|
|
createSelectorOptions?: CreateSelectorOptions<
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
>
|
|
]
|
|
) => {
|
|
let recomputations = 0
|
|
let dependencyRecomputations = 0
|
|
let lastResult: Result
|
|
|
|
// Due to the intricacies of rest params, we can't do an optional arg after `...createSelectorArgs`.
|
|
// So, start by declaring the default value here.
|
|
// (And yes, the words 'memoize' and 'options' appear too many times in this next sequence.)
|
|
let directlyPassedOptions: CreateSelectorOptions<
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
> = {}
|
|
|
|
// Normally, the result func or "combiner" is the last arg
|
|
let resultFunc = createSelectorArgs.pop() as
|
|
| Combiner<InputSelectors, Result>
|
|
| CreateSelectorOptions<
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
>
|
|
|
|
// If the result func is actually an _object_, assume it's our options object
|
|
if (typeof resultFunc === 'object') {
|
|
directlyPassedOptions = resultFunc
|
|
// and pop the real result func off
|
|
resultFunc = createSelectorArgs.pop() as Combiner<InputSelectors, Result>
|
|
}
|
|
|
|
assertIsFunction(
|
|
resultFunc,
|
|
`createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]`
|
|
)
|
|
|
|
// Determine which set of options we're using. Prefer options passed directly,
|
|
// but fall back to options given to `createSelectorCreator`.
|
|
const combinedOptions = {
|
|
...createSelectorCreatorOptions,
|
|
...directlyPassedOptions
|
|
}
|
|
|
|
const {
|
|
memoize,
|
|
memoizeOptions = [],
|
|
argsMemoize = weakMapMemoize,
|
|
argsMemoizeOptions = [],
|
|
devModeChecks = {}
|
|
} = combinedOptions
|
|
|
|
// Simplifying assumption: it's unlikely that the first options arg of the provided memoizer
|
|
// is an array. In most libs I've looked at, it's an equality function or options object.
|
|
// Based on that, if `memoizeOptions` _is_ an array, we assume it's a full
|
|
// user-provided array of options. Otherwise, it must be just the _first_ arg, and so
|
|
// we wrap it in an array so we can apply it.
|
|
const finalMemoizeOptions = ensureIsArray(memoizeOptions)
|
|
const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions)
|
|
const dependencies = getDependencies(createSelectorArgs) as InputSelectors
|
|
|
|
const memoizedResultFunc = memoize(function recomputationWrapper() {
|
|
recomputations++
|
|
// apply arguments instead of spreading for performance.
|
|
// @ts-ignore
|
|
return (resultFunc as Combiner<InputSelectors, Result>).apply(
|
|
null,
|
|
arguments as unknown as Parameters<Combiner<InputSelectors, Result>>
|
|
)
|
|
}, ...finalMemoizeOptions) as Combiner<InputSelectors, Result> &
|
|
ExtractMemoizerFields<OverrideMemoizeFunction>
|
|
|
|
let firstRun = true
|
|
|
|
// If a selector is called with the exact same arguments we don't need to traverse our dependencies again.
|
|
const selector = argsMemoize(function dependenciesChecker() {
|
|
dependencyRecomputations++
|
|
/** Return values of input selectors which the `resultFunc` takes as arguments. */
|
|
const inputSelectorResults = collectInputSelectorResults(
|
|
dependencies,
|
|
arguments
|
|
)
|
|
|
|
// apply arguments instead of spreading for performance.
|
|
// @ts-ignore
|
|
lastResult = memoizedResultFunc.apply(null, inputSelectorResults)
|
|
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
const { identityFunctionCheck, inputStabilityCheck } =
|
|
getDevModeChecksExecutionInfo(firstRun, devModeChecks)
|
|
if (identityFunctionCheck.shouldRun) {
|
|
identityFunctionCheck.run(
|
|
resultFunc as Combiner<InputSelectors, Result>,
|
|
inputSelectorResults,
|
|
lastResult
|
|
)
|
|
}
|
|
|
|
if (inputStabilityCheck.shouldRun) {
|
|
// make a second copy of the params, to check if we got the same results
|
|
const inputSelectorResultsCopy = collectInputSelectorResults(
|
|
dependencies,
|
|
arguments
|
|
)
|
|
|
|
inputStabilityCheck.run(
|
|
{ inputSelectorResults, inputSelectorResultsCopy },
|
|
{ memoize, memoizeOptions: finalMemoizeOptions },
|
|
arguments
|
|
)
|
|
}
|
|
|
|
if (firstRun) firstRun = false
|
|
}
|
|
|
|
return lastResult
|
|
}, ...finalArgsMemoizeOptions) as unknown as Selector<
|
|
GetStateFromSelectors<InputSelectors>,
|
|
Result,
|
|
GetParamsFromSelectors<InputSelectors>
|
|
> &
|
|
ExtractMemoizerFields<OverrideArgsMemoizeFunction>
|
|
|
|
return Object.assign(selector, {
|
|
resultFunc,
|
|
memoizedResultFunc,
|
|
dependencies,
|
|
dependencyRecomputations: () => dependencyRecomputations,
|
|
resetDependencyRecomputations: () => {
|
|
dependencyRecomputations = 0
|
|
},
|
|
lastResult: () => lastResult,
|
|
recomputations: () => recomputations,
|
|
resetRecomputations: () => {
|
|
recomputations = 0
|
|
},
|
|
memoize,
|
|
argsMemoize
|
|
}) as OutputSelector<
|
|
InputSelectors,
|
|
Result,
|
|
OverrideMemoizeFunction,
|
|
OverrideArgsMemoizeFunction
|
|
>
|
|
}
|
|
|
|
Object.assign(createSelector, {
|
|
withTypes: () => createSelector
|
|
})
|
|
|
|
return createSelector as CreateSelectorFunction<
|
|
MemoizeFunction,
|
|
ArgsMemoizeFunction
|
|
>
|
|
}
|
|
|
|
/**
|
|
* Accepts one or more "input selectors" (either as separate arguments or a single array),
|
|
* a single "result function" / "combiner", and an optional options object, and
|
|
* generates a memoized selector function.
|
|
*
|
|
* @see {@link https://reselect.js.org/api/createSelector `createSelector`}
|
|
*
|
|
* @public
|
|
*/
|
|
export const createSelector =
|
|
/* #__PURE__ */ createSelectorCreator(weakMapMemoize)
|