@@ -177,14 +177,6 @@ export class Batch {
177177 /** @type {Map<Source, { v: unknown, wv: number }> | null } */
178178 var current_values = null ;
179179
180- /**
181- * A batch is superseded if all of its sources are also in the current batch.
182- * If the current batch commits, we don't need the old batch anymore.
183- * This also prevents memory leaks since the old batch will never be committed.
184- * @type {Batch[] }
185- */
186- var superseded_batches = [ ] ;
187-
188180 // if there are multiple batches, we are 'time travelling' —
189181 // we need to undo the changes belonging to any batch
190182 // other than the current one
@@ -197,25 +189,17 @@ export class Batch {
197189 source . v = current ;
198190 }
199191
200- let is_prior_batch = true ;
201-
202192 for ( const batch of batches ) {
203193 if ( batch === this ) {
204- is_prior_batch = false ;
205194 continue ;
206195 }
207196
208- let superseded = is_prior_batch ;
209-
210197 for ( const [ source , previous ] of batch . #previous) {
211198 if ( ! current_values . has ( source ) ) {
212- superseded = false ;
213199 current_values . set ( source , { v : source . v , wv : source . wv } ) ;
214200 source . v = previous ;
215201 }
216202 }
217-
218- if ( superseded ) superseded_batches . push ( batch ) ;
219203 }
220204 }
221205
@@ -226,21 +210,21 @@ export class Batch {
226210 // if we didn't start any new async work, and no async work
227211 // is outstanding from a previous flush, commit
228212 if ( this . #async_effects. length === 0 && this . #pending === 0 ) {
229- if ( superseded_batches . length > 0 ) {
230- const own = [ ...this . #callbacks. keys ( ) ] ;
231- // A superseded batch could have callbacks for e.g. destroying if blocks
232- // that are not part of the current batch because it already happened in the prior one,
233- // and the corresponding block effect therefore returning early because nothing was changed from its
234- // point of view, therefore not adding a callback to the current batch, so we gotta call them here.
235- // We do it from newest to oldest to ensure the correct callback is applied.
236- for ( const batch of superseded_batches . reverse ( ) ) {
237- for ( const [ effect , cb ] of batch . #callbacks) {
238- if ( ! own . includes ( effect ) ) {
239- cb ( ) ;
240- own . push ( effect ) ;
213+ for ( const batch of batches ) {
214+ if ( batch === this ) break ;
215+
216+ for ( const effects of [ batch . #dirty_effects, batch . #maybe_dirty_effects] ) {
217+ let i = effects . length ;
218+ while ( i -- ) {
219+ // if an effect in an earlier batch only depends on state that
220+ // is part of this batch, we can delete it from the other batch
221+ const effect = effects [ i ] ;
222+ const has_other_deps = effect . deps ?. some ( ( value ) => ! this . current . has ( value ) ) ;
223+
224+ if ( ! has_other_deps ) {
225+ effects . splice ( i , 1 ) ; // TODO should probably be a `Set` if we're going to do this
241226 }
242227 }
243- batch . remove ( ) ;
244228 }
245229 }
246230
0 commit comments