@@ -147,7 +147,7 @@ type PrdStore = {
147
147
...args : Args
148
148
) => Result
149
149
sub : ( atom : AnyAtom , listener : ( ) => void ) => ( ) => void
150
- unstable_resolve ?: < Value > ( atom : Atom < Value > ) => Atom < Value >
150
+ unstable_resolve ?: < A extends Atom < unknown > > ( atom : A ) => A
151
151
}
152
152
type Store = PrdStore & Partial < DevStoreRev2 >
153
153
@@ -182,10 +182,12 @@ export const createStore = (): Store => {
182
182
mountedAtoms = new Set ( )
183
183
}
184
184
185
+ const resolveAtom = < A extends Atom < unknown > > ( atom : A ) : A => {
186
+ return store . unstable_resolve ?.( atom ) ?? atom
187
+ }
188
+
185
189
const getAtomState = < Value > ( atom : Atom < Value > ) =>
186
- atomStateMap . get ( store . unstable_resolve ?.( atom ) || atom ) as
187
- | AtomState < Value >
188
- | undefined
190
+ atomStateMap . get ( atom ) as AtomState < Value > | undefined
189
191
190
192
const addPendingDependent = ( atom : AnyAtom , atomState : AtomState ) => {
191
193
atomState . d . forEach ( ( _ , a ) => {
@@ -208,7 +210,8 @@ export const createStore = (): Store => {
208
210
Object . freeze ( atomState )
209
211
}
210
212
const prevAtomState = getAtomState ( atom )
211
- atomStateMap . set ( store . unstable_resolve ?.( atom ) || atom , atomState )
213
+ atomStateMap . set ( atom , atomState )
214
+ pendingStack [ pendingStack . length - 1 ] ?. add ( atom )
212
215
if ( ! pendingMap . has ( atom ) ) {
213
216
pendingMap . set ( atom , [ prevAtomState , new Set ( ) ] )
214
217
addPendingDependent ( atom , atomState )
@@ -425,22 +428,23 @@ export const createStore = (): Store => {
425
428
const nextDependencies : NextDependencies = new Map ( )
426
429
let isSync = true
427
430
const getter : Getter = < V > ( a : Atom < V > ) => {
428
- if ( a === ( atom as AnyAtom ) ) {
429
- const aState = getAtomState ( a )
431
+ const resolvedA = resolveAtom ( a )
432
+ if ( resolvedA === ( atom as AnyAtom ) ) {
433
+ const aState = getAtomState ( resolvedA )
430
434
if ( aState ) {
431
- nextDependencies . set ( a , aState )
435
+ nextDependencies . set ( resolvedA , aState )
432
436
return returnAtomValue ( aState )
433
437
}
434
- if ( hasInitialValue ( a ) ) {
435
- nextDependencies . set ( a , undefined )
436
- return a . init
438
+ if ( hasInitialValue ( resolvedA ) ) {
439
+ nextDependencies . set ( resolvedA , undefined )
440
+ return resolvedA . init
437
441
}
438
442
// NOTE invalid derived atoms can reach here
439
443
throw new Error ( 'no atom init' )
440
444
}
441
- // a !== atom
442
- const aState = readAtomState ( a , force )
443
- nextDependencies . set ( a , aState )
445
+ // resolvedA !== atom
446
+ const aState = readAtomState ( resolvedA , force )
447
+ nextDependencies . set ( resolvedA , aState )
444
448
return returnAtomValue ( aState )
445
449
}
446
450
let controller : AbortController | undefined
@@ -485,7 +489,7 @@ export const createStore = (): Store => {
485
489
}
486
490
487
491
const readAtom = < Value > ( atom : Atom < Value > ) : Value =>
488
- returnAtomValue ( readAtomState ( atom ) )
492
+ returnAtomValue ( readAtomState ( resolveAtom ( atom ) ) )
489
493
490
494
const recomputeDependents = ( atom : AnyAtom ) : void => {
491
495
const getDependents = ( a : AnyAtom ) : Dependents => {
@@ -556,28 +560,30 @@ export const createStore = (): Store => {
556
560
atom : WritableAtom < Value , Args , Result > ,
557
561
...args : Args
558
562
) : Result => {
559
- const getter : Getter = < V > ( a : Atom < V > ) => returnAtomValue ( readAtomState ( a ) )
563
+ const getter : Getter = < V > ( a : Atom < V > ) =>
564
+ returnAtomValue ( readAtomState ( resolveAtom ( a ) ) )
560
565
const setter : Setter = < V , As extends unknown [ ] , R > (
561
566
a : WritableAtom < V , As , R > ,
562
567
...args : As
563
568
) => {
569
+ const resolvedA = resolveAtom ( a )
564
570
const isSync = pendingStack . length > 0
565
571
if ( ! isSync ) {
566
- pendingStack . push ( new Set ( [ a ] ) )
572
+ pendingStack . push ( new Set ( [ resolvedA ] ) )
567
573
}
568
574
let r : R | undefined
569
- if ( a === ( atom as AnyAtom ) ) {
570
- if ( ! hasInitialValue ( a ) ) {
575
+ if ( resolvedA === ( atom as AnyAtom ) ) {
576
+ if ( ! hasInitialValue ( resolvedA ) ) {
571
577
// NOTE technically possible but restricted as it may cause bugs
572
578
throw new Error ( 'atom not writable' )
573
579
}
574
- const prevAtomState = getAtomState ( a )
575
- const nextAtomState = setAtomValueOrPromise ( a , args [ 0 ] as V )
580
+ const prevAtomState = getAtomState ( resolvedA )
581
+ const nextAtomState = setAtomValueOrPromise ( resolvedA , args [ 0 ] as V )
576
582
if ( ! isEqualAtomValue ( prevAtomState , nextAtomState ) ) {
577
- recomputeDependents ( a )
583
+ recomputeDependents ( resolvedA )
578
584
}
579
585
} else {
580
- r = writeAtomState ( a as AnyWritableAtom , ...args ) as R
586
+ r = writeAtomState ( resolvedA as AnyWritableAtom , ...args ) as R
581
587
}
582
588
if ( ! isSync ) {
583
589
const flushed = flushPending ( pendingStack . pop ( ) ! )
@@ -597,8 +603,10 @@ export const createStore = (): Store => {
597
603
atom : WritableAtom < Value , Args , Result > ,
598
604
...args : Args
599
605
) : Result => {
600
- pendingStack . push ( new Set ( [ atom ] ) )
601
- const result = writeAtomState ( atom , ...args )
606
+ const resolvedAtom = resolveAtom ( atom )
607
+ pendingStack . push ( new Set ( [ resolvedAtom ] ) )
608
+ const result = writeAtomState ( resolvedAtom , ...args )
609
+
602
610
const flushed = flushPending ( pendingStack . pop ( ) ! )
603
611
if ( import . meta. env ?. MODE !== 'production' ) {
604
612
devListenersRev2 . forEach ( ( l ) => l ( { type : 'write' , flushed : flushed ! } ) )
@@ -781,8 +789,9 @@ export const createStore = (): Store => {
781
789
}
782
790
783
791
const subscribeAtom = ( atom : AnyAtom , listener : ( ) => void ) => {
784
- const mounted = mountAtom ( atom )
785
- const flushed = flushPending ( [ atom ] )
792
+ const resolvedAtom = resolveAtom ( atom )
793
+ const mounted = mountAtom ( resolvedAtom )
794
+ const flushed = flushPending ( [ resolvedAtom ] )
786
795
const listeners = mounted . l
787
796
listeners . add ( listener )
788
797
if ( import . meta. env ?. MODE !== 'production' ) {
@@ -792,52 +801,48 @@ export const createStore = (): Store => {
792
801
}
793
802
return ( ) => {
794
803
listeners . delete ( listener )
795
- tryUnmountAtom ( atom , mounted )
804
+ tryUnmountAtom ( resolvedAtom , mounted )
796
805
if ( import . meta. env ?. MODE !== 'production' ) {
797
806
// devtools uses this to detect if it _can_ unmount or not
798
807
devListenersRev2 . forEach ( ( l ) => l ( { type : 'unsub' } ) )
799
808
}
800
809
}
801
810
}
802
811
803
- const store : Store =
804
- import . meta. env ?. MODE !== 'production'
805
- ? {
806
- get : readAtom ,
807
- set : writeAtom ,
808
- sub : subscribeAtom ,
809
- // store dev methods (these are tentative and subject to change without notice)
810
- dev_subscribe_store : ( l : DevListenerRev2 ) => {
811
- devListenersRev2 . add ( l )
812
- return ( ) => {
813
- devListenersRev2 . delete ( l )
814
- }
815
- } ,
816
- dev_get_mounted_atoms : ( ) => mountedAtoms . values ( ) ,
817
- dev_get_atom_state : getAtomState ,
818
- dev_get_mounted : ( a : AnyAtom ) => mountedMap . get ( a ) ,
819
- dev_restore_atoms : (
820
- values : Iterable < readonly [ AnyAtom , AnyValue ] > ,
821
- ) => {
822
- pendingStack . push ( new Set ( ) )
823
- for ( const [ atom , valueOrPromise ] of values ) {
824
- if ( hasInitialValue ( atom ) ) {
825
- setAtomValueOrPromise ( atom , valueOrPromise )
826
- recomputeDependents ( atom )
827
- }
828
- }
829
- const flushed = flushPending ( pendingStack . pop ( ) ! )
830
- devListenersRev2 . forEach ( ( l ) =>
831
- l ( { type : 'restore' , flushed : flushed ! } ) ,
832
- )
833
- } ,
812
+ const store : Store = {
813
+ get : readAtom ,
814
+ set : writeAtom ,
815
+ sub : subscribeAtom ,
816
+ }
817
+ if ( import . meta. env ?. MODE !== 'production' ) {
818
+ const devStore : DevStoreRev2 = {
819
+ // store dev methods (these are tentative and subject to change without notice)
820
+ dev_subscribe_store : ( l ) => {
821
+ devListenersRev2 . add ( l )
822
+ return ( ) => {
823
+ devListenersRev2 . delete ( l )
834
824
}
835
- : {
836
- get : readAtom ,
837
- set : writeAtom ,
838
- sub : subscribeAtom ,
825
+ } ,
826
+ dev_get_mounted_atoms : ( ) => mountedAtoms . values ( ) ,
827
+ dev_get_atom_state : getAtomState ,
828
+ dev_get_mounted : ( a ) => mountedMap . get ( a ) ,
829
+ dev_restore_atoms : ( values ) => {
830
+ pendingStack . push ( new Set ( ) )
831
+ for ( const [ atom , valueOrPromise ] of values ) {
832
+ if ( hasInitialValue ( atom ) ) {
833
+ setAtomValueOrPromise ( atom , valueOrPromise )
834
+ recomputeDependents ( atom )
835
+ }
839
836
}
840
- return store
837
+ const flushed = flushPending ( pendingStack . pop ( ) ! )
838
+ devListenersRev2 . forEach ( ( l ) =>
839
+ l ( { type : 'restore' , flushed : flushed ! } ) ,
840
+ )
841
+ } ,
842
+ }
843
+ Object . assign ( store , devStore )
844
+ }
845
+ return store as Store
841
846
}
842
847
843
848
let defaultStore : Store | undefined
0 commit comments