@@ -177,14 +177,6 @@ export class Batch {
177
177
/** @type {Map<Source, { v: unknown, wv: number }> | null } */
178
178
var current_values = null ;
179
179
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
-
188
180
// if there are multiple batches, we are 'time travelling' —
189
181
// we need to undo the changes belonging to any batch
190
182
// other than the current one
@@ -197,25 +189,17 @@ export class Batch {
197
189
source . v = current ;
198
190
}
199
191
200
- let is_prior_batch = true ;
201
-
202
192
for ( const batch of batches ) {
203
193
if ( batch === this ) {
204
- is_prior_batch = false ;
205
194
continue ;
206
195
}
207
196
208
- let superseded = is_prior_batch ;
209
-
210
197
for ( const [ source , previous ] of batch . #previous) {
211
198
if ( ! current_values . has ( source ) ) {
212
- superseded = false ;
213
199
current_values . set ( source , { v : source . v , wv : source . wv } ) ;
214
200
source . v = previous ;
215
201
}
216
202
}
217
-
218
- if ( superseded ) superseded_batches . push ( batch ) ;
219
203
}
220
204
}
221
205
@@ -226,21 +210,21 @@ export class Batch {
226
210
// if we didn't start any new async work, and no async work
227
211
// is outstanding from a previous flush, commit
228
212
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
241
226
}
242
227
}
243
- batch . remove ( ) ;
244
228
}
245
229
}
246
230
0 commit comments