Skip to content

Commit 99515ad

Browse files
committed
refactor: pass recompute as arg to flushBatch
1 parent 0fc4d6e commit 99515ad

File tree

2 files changed

+26
-54
lines changed

2 files changed

+26
-54
lines changed

src/vanilla/store.ts

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,10 @@ const registerBatchAtom = (
209209
}
210210
}
211211

212-
const flushBatch = (batch: Batch) => {
212+
const flushBatch = (
213+
batch: Batch,
214+
recomputeDependents: (batch: Batch) => void,
215+
) => {
213216
let error: AnyError
214217
let hasError = false
215218
const call = (fn: () => void) => {
@@ -223,6 +226,7 @@ const flushBatch = (batch: Batch) => {
223226
}
224227
}
225228
while (batch.C.size || batch.some((channel) => channel.size)) {
229+
recomputeDependents(batch)
226230
batch.C.clear()
227231
for (const channel of batch) {
228232
channel.forEach(call)
@@ -377,7 +381,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
377381
const batch = createBatch()
378382
addDependency(atom, atomState, a, aState)
379383
mountDependencies(batch, atom, atomState)
380-
flushBatch(batch)
384+
recomputeAndFlushBatch(batch)
381385
}
382386
}
383387
}
@@ -419,7 +423,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
419423
if (atomState.m) {
420424
const batch = createBatch()
421425
mountDependencies(batch, atom, atomState)
422-
flushBatch(batch)
426+
recomputeAndFlushBatch(batch)
423427
}
424428
}
425429
valueOrPromise.then(complete, complete)
@@ -458,24 +462,20 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
458462
return dependents
459463
}
460464

461-
const dirtyDependents = <Value>(
462-
batch: Batch,
463-
atom: Atom<Value>,
464-
atomState: AtomState<Value>,
465-
) => {
466-
const dependents = new Map<AnyAtom, AtomState>([[atom, atomState]])
467-
const stack: [AnyAtom, AtomState][] = [[atom, atomState]]
465+
const dirtyDependents = <Value>(atomState: AtomState<Value>) => {
466+
const dependents = new Set<AtomState>([atomState])
467+
const stack: AtomState[] = [atomState]
468468
while (stack.length > 0) {
469-
const [a, aState] = stack.pop()!
469+
const aState = stack.pop()!
470470
if (aState.x) {
471471
// already dirty
472472
continue
473473
}
474474
aState.x = true
475-
for (const [d, s] of getMountedOrBatchDependents(batch, a, aState)) {
476-
if (!dependents.has(d)) {
477-
dependents.set(d, s)
478-
stack.push([d, s])
475+
for (const [, s] of getMountedOrBatchDependents(aState)) {
476+
if (!dependents.has(s)) {
477+
dependents.add(s)
478+
stack.push(s)
479479
}
480480
}
481481
}
@@ -497,7 +497,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
497497
// Visit the root atom. This is the only atom in the dependency graph
498498
// without incoming edges, which is one reason we can simplify the algorithm
499499
const stack: [a: AnyAtom, aState: AtomState][] = Array.from(
500-
batch.D.keys(),
500+
batch.C,
501501
(atom) => [atom, ensureAtomState(atom)],
502502
)
503503
while (stack.length > 0) {
@@ -532,7 +532,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
532532
const [a, aState, prevEpochNumber] = topSortedReversed[i]!
533533
let hasChangedDeps = false
534534
for (const dep of aState.d.keys()) {
535-
if (dep !== a && batch.D.has(dep)) {
535+
if (dep !== a && batch.C.has(dep)) {
536536
hasChangedDeps = true
537537
break
538538
}
@@ -548,6 +548,9 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
548548
}
549549
}
550550

551+
const recomputeAndFlushBatch = (batch: Batch) =>
552+
flushBatch(batch, recomputeDependents)
553+
551554
const writeAtomState = <Value, Args extends unknown[], Result>(
552555
batch: Batch,
553556
atom: WritableAtom<Value, Args, Result>,
@@ -572,8 +575,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
572575
setAtomStateValueOrPromise(a, aState, v)
573576
mountDependencies(batch, a, aState)
574577
if (prevEpochNumber !== aState.n) {
575-
dirtyDependents(batch, a, aState)
576-
batch.R = recomputeDependents
578+
dirtyDependents(aState)
577579
registerBatchAtom(batch, a, aState)
578580
}
579581
return undefined as R
@@ -582,7 +584,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
582584
}
583585
} finally {
584586
if (!isSync) {
585-
flushBatch(batch)
587+
recomputeAndFlushBatch(batch)
586588
}
587589
}
588590
}
@@ -601,7 +603,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
601603
try {
602604
return writeAtomState(batch, atom, ...args)
603605
} finally {
604-
flushBatch(batch)
606+
recomputeAndFlushBatch(batch)
605607
}
606608
}
607609

@@ -658,7 +660,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
658660
return writeAtomState(batch, atom, ...args)
659661
} finally {
660662
if (!isSync) {
661-
flushBatch(batch)
663+
recomputeAndFlushBatch(batch)
662664
}
663665
}
664666
}
@@ -715,12 +717,12 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
715717
const mounted = mountAtom(batch, atom, atomState)
716718
const listeners = mounted.l
717719
listeners.add(listener)
718-
flushBatch(batch)
720+
recomputeAndFlushBatch(batch)
719721
return () => {
720722
listeners.delete(listener)
721723
const batch = createBatch()
722724
unmountAtom(batch, atom, atomState)
723-
flushBatch(batch)
725+
recomputeAndFlushBatch(batch)
724726
}
725727
}
726728

tests/vanilla/store.test.tsx

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,36 +1109,6 @@ it('recomputes dependents of unmounted atoms', () => {
11091109
expect(bRead).not.toHaveBeenCalled()
11101110
})
11111111

1112-
it('runs recomputeDependents on atoms in the correct order', async () => {
1113-
let i = 0
1114-
function createHistoryAtoms<T>(initialValue: T) {
1115-
const historyStackAtom = atom<T[]>([initialValue])
1116-
historyStackAtom.debugLabel = `${i}:historyStackAtom`
1117-
1118-
const valueAtom = atom((get) => {
1119-
const entry = get(historyStackAtom)[0]
1120-
return entry
1121-
})
1122-
valueAtom.debugLabel = `${i}:valueAtom`
1123-
1124-
const resetAtom = atom(null, (_, set, value: T) => {
1125-
set(historyStackAtom, [value])
1126-
})
1127-
resetAtom.debugLabel = `${i}:resetAtom`
1128-
i++
1129-
return { valueAtom, resetAtom }
1130-
}
1131-
1132-
const val1Atoms = createHistoryAtoms('foo')
1133-
const val2Atoms = createHistoryAtoms<string | null>(null)
1134-
1135-
const initAtom = atom(null, (_get, set) => {
1136-
// if comment out this line, the test will pass
1137-
set(val2Atoms.resetAtom, null)
1138-
set(val1Atoms.resetAtom, 'bar')
1139-
}
1140-
})
1141-
11421112
it('recomputes all changed atom dependents together', async () => {
11431113
const a = atom([0])
11441114
const b = atom([0])

0 commit comments

Comments
 (0)