@@ -172,12 +172,12 @@ const addDependency = <Value>(
172
172
type BatchPriority = 0 | 1 | 2
173
173
174
174
type Batch = [
175
- /** high priority listeners */
176
- priority0 : Set < ( ) => void > ,
175
+ /** finish recompute */
176
+ priority0 : Set < ( batch : Batch ) => void > ,
177
177
/** atom listeners */
178
- priority1 : Set < ( ) => void > ,
178
+ priority1 : Set < ( batch : Batch ) => void > ,
179
179
/** atom mount hooks */
180
- priority2 : Set < ( ) => void > ,
180
+ priority2 : Set < ( batch : Batch ) => void > ,
181
181
] & {
182
182
/** changed Atoms */
183
183
C : Set < AnyAtom >
@@ -189,7 +189,7 @@ const createBatch = (): Batch =>
189
189
const addBatchFunc = (
190
190
batch : Batch ,
191
191
priority : BatchPriority ,
192
- fn : ( ) => void ,
192
+ fn : ( batch : Batch ) => void ,
193
193
) => {
194
194
batch [ priority ] . add ( fn )
195
195
}
@@ -203,21 +203,20 @@ const registerBatchAtom = (
203
203
batch . C . add ( atom )
204
204
atomState . u ?.( batch )
205
205
const scheduleListeners = ( ) => {
206
- atomState . m ?. l . forEach ( ( listener ) => addBatchFunc ( batch , 1 , listener ) )
206
+ atomState . m ?. l . forEach ( ( listener ) =>
207
+ addBatchFunc ( batch , 1 , ( ) => listener ( ) ) ,
208
+ )
207
209
}
208
210
addBatchFunc ( batch , 1 , scheduleListeners )
209
211
}
210
212
}
211
213
212
- const flushBatch = (
213
- batch : Batch ,
214
- recomputeDependents : ( batch : Batch ) => void ,
215
- ) => {
214
+ const flushBatch = ( batch : Batch ) => {
216
215
let error : AnyError
217
216
let hasError = false
218
- const call = ( fn : ( ) => void ) => {
217
+ const call = ( fn : ( batch : Batch ) => void ) => {
219
218
try {
220
- fn ( )
219
+ fn ( batch )
221
220
} catch ( e ) {
222
221
if ( ! hasError ) {
223
222
error = e
@@ -226,8 +225,6 @@ const flushBatch = (
226
225
}
227
226
}
228
227
while ( batch . C . size || batch . some ( ( channel ) => channel . size ) ) {
229
- recomputeDependents ( batch )
230
- batch . C . clear ( )
231
228
for ( const channel of batch ) {
232
229
channel . forEach ( call )
233
230
channel . clear ( )
@@ -380,7 +377,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
380
377
const batch = createBatch ( )
381
378
addDependency ( atom , atomState , a , aState )
382
379
mountDependencies ( batch , atom , atomState )
383
- recomputeAndFlushBatch ( batch )
380
+ flushBatch ( batch )
384
381
}
385
382
}
386
383
}
@@ -422,7 +419,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
422
419
if ( atomState . m ) {
423
420
const batch = createBatch ( )
424
421
mountDependencies ( batch , atom , atomState )
425
- recomputeAndFlushBatch ( batch )
422
+ flushBatch ( batch )
426
423
}
427
424
}
428
425
valueOrPromise . then ( complete , complete )
@@ -441,18 +438,23 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
441
438
const readAtom = < Value > ( atom : Atom < Value > ) : Value =>
442
439
returnAtomValue ( readAtomState ( undefined , atom ) )
443
440
444
- const getMountedDependents = < Value > (
441
+ const getMountedOrBatchDependents = < Value > (
445
442
atomState : AtomState < Value > ,
446
443
) : Map < AnyAtom , AtomState > => {
447
- const mountedDependents = new Map < AnyAtom , AtomState > ( )
448
- const dependents = new Set ( [ ...( atomState . m ?. t || [ ] ) , ...atomState . p ] )
449
- for ( const a of dependents ) {
444
+ const dependents = new Map < AnyAtom , AtomState > ( )
445
+ for ( const a of atomState . m ?. t || [ ] ) {
450
446
const aState = ensureAtomState ( a )
451
447
if ( aState . m ) {
452
- mountedDependents . set ( a , aState )
448
+ dependents . set ( a , aState )
453
449
}
454
450
}
455
- return mountedDependents
451
+ for ( const atomWithPendingPromise of atomState . p ) {
452
+ dependents . set (
453
+ atomWithPendingPromise ,
454
+ ensureAtomState ( atomWithPendingPromise ) ,
455
+ )
456
+ }
457
+ return dependents
456
458
}
457
459
458
460
const dirtyDependents = < Value > ( atomState : AtomState < Value > ) => {
@@ -465,7 +467,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
465
467
continue
466
468
}
467
469
aState . x = true
468
- for ( const [ , s ] of getMountedDependents ( aState ) ) {
470
+ for ( const [ , s ] of getMountedOrBatchDependents ( aState ) ) {
469
471
if ( ! dependents . has ( s ) ) {
470
472
dependents . add ( s )
471
473
stack . push ( s )
@@ -512,7 +514,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
512
514
}
513
515
visiting . add ( a )
514
516
// Push unvisited dependents onto the stack
515
- for ( const [ d , s ] of getMountedDependents ( aState ) ) {
517
+ for ( const [ d , s ] of getMountedOrBatchDependents ( aState ) ) {
516
518
if ( a !== d && ! visiting . has ( d ) ) {
517
519
stack . push ( [ d , s ] )
518
520
}
@@ -539,11 +541,9 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
539
541
}
540
542
delete aState . x
541
543
}
544
+ batch . C . clear ( )
542
545
}
543
546
544
- const recomputeAndFlushBatch = ( batch : Batch ) =>
545
- flushBatch ( batch , recomputeDependents )
546
-
547
547
const writeAtomState = < Value , Args extends unknown [ ] , Result > (
548
548
batch : Batch ,
549
549
atom : WritableAtom < Value , Args , Result > ,
@@ -570,14 +570,15 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
570
570
if ( prevEpochNumber !== aState . n ) {
571
571
dirtyDependents ( aState )
572
572
registerBatchAtom ( batch , a , aState )
573
+ addBatchFunc ( batch , 0 , recomputeDependents )
573
574
}
574
575
return undefined as R
575
576
} else {
576
577
return writeAtomState ( batch , a , ...args )
577
578
}
578
579
} finally {
579
580
if ( ! isSync ) {
580
- recomputeAndFlushBatch ( batch )
581
+ flushBatch ( batch )
581
582
}
582
583
}
583
584
}
@@ -596,7 +597,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
596
597
try {
597
598
return writeAtomState ( batch , atom , ...args )
598
599
} finally {
599
- recomputeAndFlushBatch ( batch )
600
+ flushBatch ( batch )
600
601
}
601
602
}
602
603
@@ -653,7 +654,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
653
654
return writeAtomState ( batch , atom , ...args )
654
655
} finally {
655
656
if ( ! isSync ) {
656
- recomputeAndFlushBatch ( batch )
657
+ flushBatch ( batch )
657
658
}
658
659
}
659
660
}
@@ -690,7 +691,7 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
690
691
// unmount self
691
692
const onUnmount = atomState . m . u
692
693
if ( onUnmount ) {
693
- addBatchFunc ( batch , 2 , ( ) => onUnmount ( batch ) )
694
+ addBatchFunc ( batch , 2 , onUnmount )
694
695
}
695
696
delete atomState . m
696
697
atomState . h ?.( batch )
@@ -710,12 +711,12 @@ const buildStore = (...storeArgs: StoreArgs): Store => {
710
711
const mounted = mountAtom ( batch , atom , atomState )
711
712
const listeners = mounted . l
712
713
listeners . add ( listener )
713
- recomputeAndFlushBatch ( batch )
714
+ flushBatch ( batch )
714
715
return ( ) => {
715
716
listeners . delete ( listener )
716
717
const batch = createBatch ( )
717
718
unmountAtom ( batch , atom , atomState )
718
- recomputeAndFlushBatch ( batch )
719
+ flushBatch ( batch )
719
720
}
720
721
}
721
722
0 commit comments