@@ -48,6 +48,7 @@ let current_scheduler_mode = FLUSH_MICROTASK;
48
48
let is_micro_task_queued = false ;
49
49
let is_task_queued = false ;
50
50
let is_raf_queued = false ;
51
+ let is_flushing_effect = false ;
51
52
// Used for $inspect
52
53
export let is_batching_effect = false ;
53
54
@@ -295,7 +296,6 @@ function is_signal_dirty(signal) {
295
296
let i ;
296
297
for ( i = 0 ; i < length ; i ++ ) {
297
298
const dependency = dependencies [ i ] ;
298
-
299
299
if ( ( dependency . f & MAYBE_DIRTY ) !== 0 && ! is_signal_dirty ( dependency ) ) {
300
300
set_signal_status ( dependency , CLEAN ) ;
301
301
continue ;
@@ -343,7 +343,7 @@ function execute_signal_fn(signal) {
343
343
current_consumer = signal ;
344
344
current_block = signal . b ;
345
345
current_component_context = signal . x ;
346
- current_skip_consumer = current_effect === null && ( signal . f & UNOWNED ) !== 0 ;
346
+ current_skip_consumer = ! is_flushing_effect && ( signal . f & UNOWNED ) !== 0 ;
347
347
current_untracking = false ;
348
348
349
349
// Render effects are invoked when the UI is about to be updated - run beforeUpdate at that point
@@ -366,27 +366,28 @@ function execute_signal_fn(signal) {
366
366
res = /** @type {() => V } */ ( init ) ( ) ;
367
367
}
368
368
let dependencies = /** @type {import('./types.js').Signal<unknown>[] } **/ ( signal . d ) ;
369
-
370
369
if ( current_dependencies !== null ) {
371
370
let i ;
372
371
if ( dependencies !== null ) {
372
+ const deps_length = dependencies . length ;
373
373
// Include any dependencies up until the current_dependencies_index.
374
- const full_dependencies =
374
+ const full_current_dependencies =
375
375
current_dependencies_index === 0
376
- ? dependencies
376
+ ? current_dependencies
377
377
: dependencies . slice ( 0 , current_dependencies_index ) . concat ( current_dependencies ) ;
378
- const dep_length = full_dependencies . length ;
378
+ const current_dep_length = full_current_dependencies . length ;
379
379
// If we have more than 16 elements in the array then use a Set for faster performance
380
380
// TODO: evaluate if we should always just use a Set or not here?
381
- const current_dependencies_set = dep_length > 16 ? new Set ( full_dependencies ) : null ;
382
-
383
- for ( i = current_dependencies_index ; i < dep_length ; i ++ ) {
384
- const dependency = full_dependencies [ i ] ;
381
+ const full_current_dependencies_set =
382
+ current_dep_length > 16 ? new Set ( full_current_dependencies ) : null ;
383
+ for ( i = current_dependencies_index ; i < deps_length ; i ++ ) {
384
+ const dependency = dependencies [ i ] ;
385
385
if (
386
- ( current_dependencies_set !== null && ! current_dependencies_set . has ( dependency ) ) ||
387
- ! full_dependencies . includes ( dependency )
386
+ ( full_current_dependencies_set !== null &&
387
+ ! full_current_dependencies_set . has ( dependency ) ) ||
388
+ ! full_current_dependencies . includes ( dependency )
388
389
) {
389
- remove_consumer ( signal , dependency , false ) ;
390
+ remove_consumer ( signal , dependency ) ;
390
391
}
391
392
}
392
393
}
@@ -415,7 +416,7 @@ function execute_signal_fn(signal) {
415
416
}
416
417
}
417
418
} else if ( dependencies !== null && current_dependencies_index < dependencies . length ) {
418
- remove_consumers ( signal , current_dependencies_index , false ) ;
419
+ remove_consumers ( signal , current_dependencies_index ) ;
419
420
dependencies . length = current_dependencies_index ;
420
421
}
421
422
return res ;
@@ -435,10 +436,9 @@ function execute_signal_fn(signal) {
435
436
* @template V
436
437
* @param {import('./types.js').ComputationSignal<V> } signal
437
438
* @param {import('./types.js').Signal<V> } dependency
438
- * @param {boolean } remove_unowned
439
439
* @returns {void }
440
440
*/
441
- function remove_consumer ( signal , dependency , remove_unowned ) {
441
+ function remove_consumer ( signal , dependency ) {
442
442
const consumers = dependency . c ;
443
443
let consumers_length = 0 ;
444
444
if ( consumers !== null ) {
@@ -454,25 +454,20 @@ function remove_consumer(signal, dependency, remove_unowned) {
454
454
}
455
455
}
456
456
}
457
- if ( remove_unowned && consumers_length === 0 && ( dependency . f & UNOWNED ) !== 0 ) {
457
+ if ( consumers_length === 0 && ( dependency . f & UNOWNED ) !== 0 ) {
458
458
// If the signal is unowned then we need to make sure to change it to dirty.
459
459
set_signal_status ( dependency , DIRTY ) ;
460
- remove_consumers (
461
- /** @type {import('./types.js').ComputationSignal<V> } **/ ( dependency ) ,
462
- 0 ,
463
- true
464
- ) ;
460
+ remove_consumers ( /** @type {import('./types.js').ComputationSignal<V> } **/ ( dependency ) , 0 ) ;
465
461
}
466
462
}
467
463
468
464
/**
469
465
* @template V
470
466
* @param {import('./types.js').ComputationSignal<V> } signal
471
467
* @param {number } start_index
472
- * @param {boolean } remove_unowned
473
468
* @returns {void }
474
469
*/
475
- function remove_consumers ( signal , start_index , remove_unowned ) {
470
+ function remove_consumers ( signal , start_index ) {
476
471
const dependencies = signal . d ;
477
472
if ( dependencies !== null ) {
478
473
const active_dependencies = start_index === 0 ? null : dependencies . slice ( 0 , start_index ) ;
@@ -481,7 +476,7 @@ function remove_consumers(signal, start_index, remove_unowned) {
481
476
const dependency = dependencies [ i ] ;
482
477
// Avoid removing a consumer if we know that it is active (start_index will not be 0)
483
478
if ( active_dependencies === null || ! active_dependencies . includes ( dependency ) ) {
484
- remove_consumer ( signal , dependency , remove_unowned ) ;
479
+ remove_consumer ( signal , dependency ) ;
485
480
}
486
481
}
487
482
}
@@ -502,7 +497,7 @@ function destroy_references(signal) {
502
497
if ( ( reference . f & IS_EFFECT ) !== 0 ) {
503
498
destroy_signal ( reference ) ;
504
499
} else {
505
- remove_consumers ( reference , 0 , true ) ;
500
+ remove_consumers ( reference , 0 ) ;
506
501
reference . d = null ;
507
502
}
508
503
}
@@ -585,19 +580,26 @@ function flush_queued_effects(effects) {
585
580
const length = effects . length ;
586
581
if ( length > 0 ) {
587
582
infinite_loop_guard ( ) ;
588
- let i ;
589
- for ( i = 0 ; i < length ; i ++ ) {
590
- const signal = effects [ i ] ;
591
- const flags = signal . f ;
592
- if ( ( flags & ( DESTROYED | INERT ) ) === 0 ) {
593
- if ( is_signal_dirty ( signal ) ) {
594
- set_signal_status ( signal , CLEAN ) ;
595
- execute_effect ( signal ) ;
596
- } else if ( ( flags & MAYBE_DIRTY ) !== 0 ) {
597
- set_signal_status ( signal , CLEAN ) ;
583
+ const previously_flushing_effect = is_flushing_effect ;
584
+ is_flushing_effect = true ;
585
+ try {
586
+ let i ;
587
+ for ( i = 0 ; i < length ; i ++ ) {
588
+ const signal = effects [ i ] ;
589
+ const flags = signal . f ;
590
+ if ( ( flags & ( DESTROYED | INERT ) ) === 0 ) {
591
+ if ( is_signal_dirty ( signal ) ) {
592
+ set_signal_status ( signal , CLEAN ) ;
593
+ execute_effect ( signal ) ;
594
+ } else if ( ( flags & MAYBE_DIRTY ) !== 0 ) {
595
+ set_signal_status ( signal , CLEAN ) ;
596
+ }
598
597
}
599
598
}
599
+ } finally {
600
+ is_flushing_effect = previously_flushing_effect ;
600
601
}
602
+
601
603
effects . length = 0 ;
602
604
}
603
605
}
@@ -822,10 +824,7 @@ function update_derived(signal, force_schedule) {
822
824
updating_derived = true ;
823
825
const value = execute_signal_fn ( signal ) ;
824
826
updating_derived = previous_updating_derived ;
825
- const status =
826
- current_skip_consumer || ( current_effect === null && ( signal . f & UNOWNED ) !== 0 )
827
- ? DIRTY
828
- : CLEAN ;
827
+ const status = current_skip_consumer || ( signal . f & UNOWNED ) !== 0 ? DIRTY : CLEAN ;
829
828
set_signal_status ( signal , status ) ;
830
829
const equals = /** @type {import('./types.js').EqualsFunctions } */ ( signal . e ) ;
831
830
if ( ! equals ( value , signal . v ) ) {
@@ -1083,7 +1082,10 @@ function mark_subtree_children_inert(signal, inert, visited_blocks) {
1083
1082
if ( references !== null ) {
1084
1083
let i ;
1085
1084
for ( i = 0 ; i < references . length ; i ++ ) {
1086
- mark_subtree_inert ( references [ i ] , inert , visited_blocks ) ;
1085
+ const reference = references [ i ] ;
1086
+ if ( ( reference . f & IS_EFFECT ) !== 0 ) {
1087
+ mark_subtree_inert ( references [ i ] , inert , visited_blocks ) ;
1088
+ }
1087
1089
}
1088
1090
}
1089
1091
}
@@ -1262,7 +1264,7 @@ export function destroy_signal(signal) {
1262
1264
const destroy = signal . y ;
1263
1265
const flags = signal . f ;
1264
1266
destroy_references ( signal ) ;
1265
- remove_consumers ( signal , 0 , true ) ;
1267
+ remove_consumers ( signal , 0 ) ;
1266
1268
signal . i =
1267
1269
signal . r =
1268
1270
signal . y =
0 commit comments