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