@@ -58,18 +58,37 @@ export function onReadAtom(atom: Atom) {
5858 CurrentComputation . sources ! . add ( atom ) ;
5959 atom . observers . add ( CurrentComputation ) ;
6060}
61+
6162export function onWriteAtom ( atom : Atom ) {
62- stackEffects ( ( ) => {
63+ collectEffects ( ( ) => {
6364 for ( const ctx of atom . observers ) {
6465 if ( ctx . state === ComputationState . EXECUTED ) {
65- ctx . state = ComputationState . STALE ;
6666 if ( ctx . isDerived ) markDownstream ( ctx as Derived < any , any > ) ;
6767 else Effects . push ( ctx ) ;
6868 }
69+ ctx . state = ComputationState . STALE ;
6970 }
7071 } ) ;
7172 batchProcessEffects ( ) ;
7273}
74+ function collectEffects ( fn : Function ) {
75+ if ( Effects ) return fn ( ) ;
76+ Effects = [ ] ;
77+ try {
78+ return fn ( ) ;
79+ } finally {
80+ // processEffects();
81+ true ;
82+ }
83+ }
84+ const batchProcessEffects = batched ( processEffects ) ;
85+ function processEffects ( ) {
86+ if ( ! Effects ) return ;
87+ for ( const computation of Effects ) {
88+ updateComputation ( computation ) ;
89+ }
90+ Effects = undefined ! ;
91+ }
7392
7493export function withoutReactivity < T extends ( ...args : any [ ] ) => any > ( fn : T ) : ReturnType < T > {
7594 return runWithComputation ( undefined ! , fn ) ;
@@ -98,6 +117,13 @@ function updateComputation(computation: Computation) {
98117 if ( state === ComputationState . EXECUTED ) return ;
99118 if ( state === ComputationState . PENDING ) {
100119 computeSources ( computation as Derived < any , any > ) ;
120+ // If the state is still not stale after processing the sources, it means
121+ // none of the dependencies have changed.
122+ // todo: test it
123+ if ( computation . state !== ComputationState . STALE ) {
124+ computation . state = ComputationState . EXECUTED ;
125+ return ;
126+ }
101127 }
102128 // todo: test performance. We might want to avoid removing the atoms to
103129 // directly re-add them at compute. Especially as we are making them stale.
@@ -108,42 +134,17 @@ function updateComputation(computation: Computation) {
108134 computation . state = ComputationState . EXECUTED ;
109135 CurrentComputation = previousComputation ;
110136}
111-
112137function removeSources ( computation : Computation ) {
113138 const sources = computation . sources ;
114139 for ( const source of sources ) {
115140 const observers = source . observers ;
116141 observers . delete ( computation ) ;
117- // if source has no observer anymore, remove its sources too
118- if ( observers . size === 0 && "sources" in source ) {
119- removeSources ( source as Derived < any , any > ) ;
120- if ( source . state !== ComputationState . STALE ) {
121- source . state = ComputationState . PENDING ;
122- }
123- }
142+ // todo: if source has no effect observer anymore, remove its sources too
143+ // todo: test it
124144 }
125145 sources . clear ( ) ;
126146}
127147
128- function stackEffects ( fn : Function ) {
129- if ( Effects ) return fn ( ) ;
130- Effects = [ ] ;
131- try {
132- return fn ( ) ;
133- } finally {
134- // processEffects();
135- true ;
136- }
137- }
138- const batchProcessEffects = batched ( processEffects ) ;
139- function processEffects ( ) {
140- if ( ! Effects ) return ;
141- for ( const computation of Effects ) {
142- updateComputation ( computation ) ;
143- }
144- Effects = undefined ! ;
145- }
146-
147148function unsubscribeEffect ( effectComputation : Computation ) {
148149 removeSources ( effectComputation ) ;
149150 cleanupEffect ( effectComputation ) ;
@@ -176,7 +177,7 @@ function markDownstream<A, B>(derived: Derived<A, B>) {
176177}
177178function computeSources ( derived : Derived < any , any > ) {
178179 for ( const source of derived . sources ) {
179- if ( "sources " in source ) continue ;
180+ if ( ! ( "compute " in source ) ) continue ;
180181 updateComputation ( source as Derived < any , any > ) ;
181182 }
182183}
0 commit comments