import type { ConsumerContext } from './types' ; import type { DependsOnOwnProps } from './toProps/types' ; import { verifyMapToProps } from './utils/verifyMapToProps' ; export function impureFinalPropsSelectorFactory ( mapStateToProps , mapContextToProps , mergeProps , context ) { return function impureFinalPropsSelector ( state , ownProps ) { return mergeProps ( mapStateToProps ( state , ownProps ) , mapContextToProps ( context , ownProps ) , ownProps ) ; } ; } export function pureFinalPropsSelectorFactory ( mapStateToProps , mapContextToProps , mergeProps , context , { areStatesEqual , areOwnPropsEqual , areStatePropsEqual , WrappedComponent : { defaultProps } } ) { let hasRunAtLeastOnce = false ; let state ; let ownProps ; let ownPropsWithDefault ; let stateProps ; let contextProps ; let mergedProps ; function handleFirstCall ( firstState , firstOwnProps ) { state = firstState ; ownProps = firstOwnProps ; ownPropsWithDefault = { ... defaultProps , ... firstOwnProps } ; stateProps = mapStateToProps ( state , ownPropsWithDefault ) ; contextProps = mapContextToProps ( context , ownPropsWithDefault ) ; mergedProps = mergeProps ( stateProps , contextProps , ownProps ) ; hasRunAtLeastOnce = true ; return mergedProps ; } function handleNewPropsAndNewState ( ) { stateProps = mapStateToProps ( state , ownPropsWithDefault ) ; if ( mapContextToProps . dependsOnOwnProps ) { contextProps = mapContextToProps ( context , ownPropsWithDefault ) ; } mergedProps = mergeProps ( stateProps , contextProps , ownProps ) ; return mergedProps ; } function handleNewProps ( ) { if ( mapStateToProps . dependsOnOwnProps ) { stateProps = mapStateToProps ( state , ownPropsWithDefault ) ; } if ( mapContextToProps . dependsOnOwnProps ) { contextProps = mapContextToProps ( context , ownPropsWithDefault ) ; } mergedProps = mergeProps ( stateProps , contextProps , ownProps ) ; return mergedProps ; } function handleNewState ( ) { const nextStateProps = mapStateToProps ( state , ownPropsWithDefault ) ; const statePropsChanged = ! areStatePropsEqual ( nextStateProps , stateProps ) ; stateProps = nextStateProps ; if ( statePropsChanged ) { mergedProps = mergeProps ( stateProps , contextProps , ownProps ) ; } return mergedProps ; } function handleSubsequentCalls ( nextState , nextOwnProps ) { const propsChanged = ! areOwnPropsEqual ( nextOwnProps , ownProps ) ; const stateChanged = ! areStatesEqual ( nextState , state ) ; state = nextState ; ownProps = nextOwnProps ; ownPropsWithDefault = { ... defaultProps , ... nextOwnProps } ; if ( propsChanged && stateChanged ) { return handleNewPropsAndNewState ( ) ; } if ( propsChanged ) { return handleNewProps ( ) ; } if ( stateChanged ) { return handleNewState ( ) ; } return mergedProps ; } return function pureFinalPropsSelector ( nextState , nextOwnProps ) { return hasRunAtLeastOnce ? handleSubsequentCalls ( nextState , nextOwnProps ) : handleFirstCall ( nextState , nextOwnProps ) ; } ; } export function finalPropsSelectorFactory ( context , { initMapStateToProps , initMapContextToProps , initMergeProps , ... options } ) { let mapStateToProps = initMapStateToProps ( context , options ) ; const mapContextToProps = initMapContextToProps ( context , options ) ; const mergeProps = initMergeProps ( context , options ) ; if ( process . env . NODE_ENV !== 'production' ) { mapStateToProps = verifyMapToProps ( mapStateToProps , options . WrappedComponent . name ) ; } const selectorFactory = options . pure ? pureFinalPropsSelectorFactory : impureFinalPropsSelectorFactory ; return selectorFactory ( mapStateToProps , mapContextToProps , mergeProps , context , options as any ) ; }