@@ -64,23 +64,36 @@ type Mounted = {
64
64
65
65
// for debugging purpose only
66
66
type StateListener = ( updatedAtom : AnyAtom , isNewAtom : boolean ) => void
67
+ type MountedAtoms = Set < AnyAtom >
67
68
68
69
// store methods
69
70
export const READ_ATOM = 'r'
70
71
export const WRITE_ATOM = 'w'
71
72
export const FLUSH_PENDING = 'f'
72
73
export const SUBSCRIBE_ATOM = 's'
73
74
export const RESTORE_ATOMS = 'h'
75
+
76
+ // store dev methods (these are tentative and subject to change)
77
+ export const DEV_SUBSCRIBE_STATE = 'n'
78
+ export const DEV_GET_MOUNTED_ATOMS = 'l'
74
79
export const DEV_GET_ATOM_STATE = 'a'
75
80
export const DEV_GET_MOUNTED = 'm'
76
81
77
82
export const createStore = (
78
- initialValues ?: Iterable < readonly [ AnyAtom , unknown ] > ,
79
- stateListener ?: StateListener
83
+ initialValues ?: Iterable < readonly [ AnyAtom , unknown ] >
80
84
) => {
81
85
const atomStateMap = new WeakMap < AnyAtom , AtomState > ( )
82
86
const mountedMap = new WeakMap < AnyAtom , Mounted > ( )
83
- const pendingMap = new Map < AnyAtom , ReadDependencies | undefined > ( )
87
+ const pendingMap = new Map <
88
+ AnyAtom ,
89
+ [ dependencies : ReadDependencies | undefined , isNewAtom : boolean ]
90
+ > ( )
91
+ let stateListeners : Set < StateListener >
92
+ let mountedAtoms : MountedAtoms
93
+ if ( typeof process === 'object' && process . env . NODE_ENV !== 'production' ) {
94
+ stateListeners = new Set ( )
95
+ mountedAtoms = new Set ( )
96
+ }
84
97
85
98
if ( initialValues ) {
86
99
for ( const [ atom , value ] of initialValues ) {
@@ -144,7 +157,7 @@ export const createStore = (
144
157
atomState . d . set ( atom , atomState . r )
145
158
}
146
159
}
147
- commitAtomState ( atom , atomState , dependencies && prevDependencies )
160
+ setAtomState ( atom , atomState , dependencies && prevDependencies )
148
161
}
149
162
150
163
const setAtomReadError = < Value > (
@@ -163,7 +176,7 @@ export const createStore = (
163
176
delete atomState . c // cancel read promise
164
177
delete atomState . i // invalidated revision
165
178
atomState . e = error // read error
166
- commitAtomState ( atom , atomState , prevDependencies )
179
+ setAtomState ( atom , atomState , prevDependencies )
167
180
}
168
181
169
182
const setAtomReadPromise = < Value > (
@@ -186,13 +199,13 @@ export const createStore = (
186
199
atomState . p = interruptablePromise // read promise
187
200
atomState . c = interruptablePromise [ INTERRUPT_PROMISE ]
188
201
}
189
- commitAtomState ( atom , atomState , prevDependencies )
202
+ setAtomState ( atom , atomState , prevDependencies )
190
203
}
191
204
192
205
const setAtomInvalidated = < Value > ( atom : Atom < Value > ) : void => {
193
206
const [ atomState ] = wipAtomState ( atom )
194
207
atomState . i = atomState . r // invalidated revision
195
- commitAtomState ( atom , atomState )
208
+ setAtomState ( atom , atomState )
196
209
}
197
210
198
211
const setAtomWritePromise = < Value > (
@@ -207,7 +220,7 @@ export const createStore = (
207
220
// delete it only if it's not overwritten
208
221
delete atomState . w // write promise
209
222
}
210
- commitAtomState ( atom , atomState )
223
+ setAtomState ( atom , atomState )
211
224
}
212
225
213
226
const scheduleReadAtomState = < Value > (
@@ -483,6 +496,9 @@ export const createStore = (
483
496
u : undefined ,
484
497
}
485
498
mountedMap . set ( atom , mounted )
499
+ if ( typeof process === 'object' && process . env . NODE_ENV !== 'production' ) {
500
+ mountedAtoms . add ( atom )
501
+ }
486
502
if ( isActuallyWritableAtom ( atom ) && atom . onMount ) {
487
503
const setAtom = ( update : unknown ) => writeAtom ( atom , update )
488
504
mounted . u = atom . onMount ( setAtom )
@@ -497,6 +513,9 @@ export const createStore = (
497
513
onUnmount ( )
498
514
}
499
515
mountedMap . delete ( atom )
516
+ if ( typeof process === 'object' && process . env . NODE_ENV !== 'production' ) {
517
+ mountedAtoms . delete ( atom )
518
+ }
500
519
// unmount read dependencies afterward
501
520
const atomState = getAtomState ( atom )
502
521
if ( atomState ) {
@@ -550,7 +569,7 @@ export const createStore = (
550
569
} )
551
570
}
552
571
553
- const commitAtomState = < Value > (
572
+ const setAtomState = < Value > (
554
573
atom : Atom < Value > ,
555
574
atomState : AtomState < Value > ,
556
575
prevDependencies ?: ReadDependencies
@@ -560,31 +579,29 @@ export const createStore = (
560
579
}
561
580
const isNewAtom = ! atomStateMap . has ( atom )
562
581
atomStateMap . set ( atom , atomState )
563
- if ( stateListener ) {
564
- stateListener ( atom , isNewAtom )
565
- }
566
582
if ( ! pendingMap . has ( atom ) ) {
567
- pendingMap . set ( atom , prevDependencies )
583
+ pendingMap . set ( atom , [ prevDependencies , isNewAtom ] )
568
584
}
569
585
}
570
586
571
587
const flushPending = ( ) : void => {
572
588
const pending = Array . from ( pendingMap )
573
589
pendingMap . clear ( )
574
- pending . forEach ( ( [ atom , prevDependencies ] ) => {
575
- const atomState = getAtomState ( atom )
576
- if ( atomState ) {
577
- if ( prevDependencies ) {
590
+ pending . forEach ( ( [ atom , [ prevDependencies , isNewAtom ] ] ) => {
591
+ if ( prevDependencies ) {
592
+ const atomState = getAtomState ( atom )
593
+ if ( atomState ) {
578
594
mountDependencies ( atom , atomState , prevDependencies )
579
595
}
580
- } else if (
596
+ }
597
+ const mounted = mountedMap . get ( atom )
598
+ mounted ?. l . forEach ( ( listener ) => listener ( ) )
599
+ if (
581
600
typeof process === 'object' &&
582
601
process . env . NODE_ENV !== 'production'
583
602
) {
584
- console . warn ( '[Bug] atom state not found in flush' , atom )
603
+ stateListeners . forEach ( ( l ) => l ( atom , isNewAtom ) )
585
604
}
586
- const mounted = mountedMap . get ( atom )
587
- mounted ?. l . forEach ( ( listener ) => listener ( ) )
588
605
} )
589
606
}
590
607
@@ -617,6 +634,13 @@ export const createStore = (
617
634
[ FLUSH_PENDING ] : flushPending ,
618
635
[ SUBSCRIBE_ATOM ] : subscribeAtom ,
619
636
[ RESTORE_ATOMS ] : restoreAtoms ,
637
+ [ DEV_SUBSCRIBE_STATE ] : ( l : StateListener ) => {
638
+ stateListeners . add ( l )
639
+ return ( ) => {
640
+ stateListeners . delete ( l )
641
+ }
642
+ } ,
643
+ [ DEV_GET_MOUNTED_ATOMS ] : ( ) => mountedAtoms . values ( ) ,
620
644
[ DEV_GET_ATOM_STATE ] : ( a : AnyAtom ) => atomStateMap . get ( a ) ,
621
645
[ DEV_GET_MOUNTED ] : ( a : AnyAtom ) => mountedMap . get ( a ) ,
622
646
}
0 commit comments