Skip to content

Commit cc884cc

Browse files
committed
Merge branch 'master' of https://github.com/reduxjs/reselect into fix-weakMapMemoize-resultEqualityCheck
2 parents 197cba9 + b856266 commit cc884cc

File tree

2 files changed

+169
-1
lines changed

2 files changed

+169
-1
lines changed

src/lruMemoize.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ export function lruMemoize<Func extends AnyFunction>(
205205
let resultsCount = 0
206206

207207
const cache =
208-
maxSize === 1
208+
maxSize <= 1
209209
? createSingletonCache(comparator)
210210
: createLruCache(maxSize, comparator)
211211

test/lruMemoize.test.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,174 @@ describe(lruMemoize, () => {
420420
// @ts-expect-error
421421
expect(selector.resultFunc.clearCache).toBeUndefined()
422422
})
423+
424+
localTest(
425+
'maxSize should default to 1 when set to a number that is less than 1',
426+
({ state, store }) => {
427+
const createSelectorLru = createSelectorCreator({
428+
memoize: lruMemoize,
429+
argsMemoize: lruMemoize,
430+
memoizeOptions: { maxSize: 0 },
431+
argsMemoizeOptions: { maxSize: 0 }
432+
}).withTypes<RootState>()
433+
434+
const selectTodoIds = createSelectorLru([state => state.todos], todos =>
435+
todos.map(({ id }) => id)
436+
)
437+
438+
expect(selectTodoIds(store.getState())).toBe(
439+
selectTodoIds(store.getState())
440+
)
441+
442+
expect(selectTodoIds.recomputations()).toBe(1)
443+
444+
store.dispatch(toggleCompleted(0))
445+
446+
expect(selectTodoIds(store.getState())).toBe(
447+
selectTodoIds(store.getState())
448+
)
449+
450+
expect(selectTodoIds.recomputations()).toBe(2)
451+
452+
const selectTodoIdsLru = lruMemoize(
453+
(state: RootState) => state.todos.map(({ id }) => id),
454+
{ maxSize: -2 }
455+
)
456+
457+
expect(selectTodoIdsLru(state)).toBe(selectTodoIdsLru(state))
458+
}
459+
)
460+
})
461+
462+
describe('lruMemoize integration with resultEqualityCheck', () => {
463+
const createAppSelector = createSelectorLru.withTypes<RootState>()
464+
465+
const resultEqualityCheck = vi
466+
.fn(shallowEqual)
467+
.mockName('resultEqualityCheck')
468+
469+
afterEach(() => {
470+
resultEqualityCheck.mockClear()
471+
})
472+
473+
localTest(
474+
'resultEqualityCheck works when set to shallowEqual',
475+
({ store }) => {
476+
const selectTodoIds = lruMemoize(
477+
(state: RootState) => state.todos.map(({ id }) => id),
478+
{ resultEqualityCheck }
479+
)
480+
481+
const firstResult = selectTodoIds(store.getState())
482+
483+
store.dispatch(toggleCompleted(0))
484+
485+
const secondResult = selectTodoIds(store.getState())
486+
487+
expect(firstResult).toBe(secondResult)
488+
489+
expect(selectTodoIds.resultsCount()).toBe(1)
490+
}
491+
)
492+
493+
localTest(
494+
'resultEqualityCheck should not be called on the first output selector call',
495+
({ store }) => {
496+
const selectTodoIds = createAppSelector(
497+
[state => state.todos],
498+
todos => todos.map(({ id }) => id),
499+
{
500+
memoizeOptions: { resultEqualityCheck },
501+
devModeChecks: { inputStabilityCheck: 'once' }
502+
}
503+
)
504+
505+
expect(selectTodoIds(store.getState())).to.be.an('array').that.is.not
506+
.empty
507+
508+
expect(resultEqualityCheck).not.toHaveBeenCalled()
509+
510+
store.dispatch(toggleCompleted(0))
511+
512+
expect(selectTodoIds.lastResult()).toBe(selectTodoIds(store.getState()))
513+
514+
expect(resultEqualityCheck).toHaveBeenCalledOnce()
515+
516+
expect(selectTodoIds.memoizedResultFunc.resultsCount()).toBe(1)
517+
518+
expect(selectTodoIds.recomputations()).toBe(2)
519+
520+
expect(selectTodoIds.resultsCount()).toBe(2)
521+
522+
expect(selectTodoIds.dependencyRecomputations()).toBe(2)
523+
524+
store.dispatch(toggleCompleted(0))
525+
526+
expect(selectTodoIds.lastResult()).toBe(selectTodoIds(store.getState()))
527+
528+
expect(resultEqualityCheck).toHaveBeenCalledTimes(2)
529+
530+
expect(selectTodoIds.memoizedResultFunc.resultsCount()).toBe(1)
531+
532+
expect(selectTodoIds.recomputations()).toBe(3)
533+
534+
expect(selectTodoIds.resultsCount()).toBe(3)
535+
536+
expect(selectTodoIds.dependencyRecomputations()).toBe(3)
537+
}
538+
)
539+
540+
localTest(
541+
'lruMemoize with resultEqualityCheck set to referenceEqualityCheck works the same as lruMemoize without resultEqualityCheck',
542+
({ store }) => {
543+
const resultEqualityCheck = vi
544+
.fn(referenceEqualityCheck)
545+
.mockName('resultEqualityCheck')
546+
547+
const selectTodoIdsWithResultEqualityCheck = lruMemoize(
548+
(state: RootState) => state.todos.map(({ id }) => id),
549+
{ resultEqualityCheck }
550+
)
551+
552+
const firstResultWithResultEqualityCheck =
553+
selectTodoIdsWithResultEqualityCheck(store.getState())
554+
555+
expect(resultEqualityCheck).not.toHaveBeenCalled()
556+
557+
store.dispatch(toggleCompleted(0))
558+
559+
const secondResultWithResultEqualityCheck =
560+
selectTodoIdsWithResultEqualityCheck(store.getState())
561+
562+
expect(firstResultWithResultEqualityCheck).not.toBe(
563+
secondResultWithResultEqualityCheck
564+
)
565+
566+
expect(firstResultWithResultEqualityCheck).toStrictEqual(
567+
secondResultWithResultEqualityCheck
568+
)
569+
570+
expect(selectTodoIdsWithResultEqualityCheck.resultsCount()).toBe(2)
571+
572+
const selectTodoIds = lruMemoize((state: RootState) =>
573+
state.todos.map(({ id }) => id)
574+
)
575+
576+
const firstResult = selectTodoIds(store.getState())
577+
578+
store.dispatch(toggleCompleted(0))
579+
580+
const secondResult = selectTodoIds(store.getState())
581+
582+
expect(firstResult).not.toBe(secondResult)
583+
584+
expect(firstResult).toStrictEqual(secondResult)
585+
586+
expect(selectTodoIds.resultsCount()).toBe(2)
587+
588+
resultEqualityCheck.mockClear()
589+
}
590+
)
423591
})
424592

425593
describe('lruMemoize integration with resultEqualityCheck', () => {

0 commit comments

Comments
 (0)