@@ -48,6 +48,7 @@ let current_scheduler_mode = FLUSH_MICROTASK;
4848let is_micro_task_queued = false ;
4949let is_task_queued = false ;
5050let is_raf_queued = false ;
51+ let is_flushing_effect = false ;
5152// Used for $inspect
5253export let is_batching_effect = false ;
5354
@@ -295,7 +296,6 @@ function is_signal_dirty(signal) {
295296 let i ;
296297 for ( i = 0 ; i < length ; i ++ ) {
297298 const dependency = dependencies [ i ] ;
298-
299299 if ( ( dependency . f & MAYBE_DIRTY ) !== 0 && ! is_signal_dirty ( dependency ) ) {
300300 set_signal_status ( dependency , CLEAN ) ;
301301 continue ;
@@ -343,7 +343,7 @@ function execute_signal_fn(signal) {
343343 current_consumer = signal ;
344344 current_block = signal . b ;
345345 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 ;
347347 current_untracking = false ;
348348
349349 // 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) {
366366 res = /** @type {() => V } */ ( init ) ( ) ;
367367 }
368368 let dependencies = /** @type {import('./types.js').Signal<unknown>[] } **/ ( signal . d ) ;
369-
370369 if ( current_dependencies !== null ) {
371370 let i ;
372371 if ( dependencies !== null ) {
372+ const deps_length = dependencies . length ;
373373 // Include any dependencies up until the current_dependencies_index.
374- const full_dependencies =
374+ const full_current_dependencies =
375375 current_dependencies_index === 0
376- ? dependencies
376+ ? current_dependencies
377377 : 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 ;
379379 // If we have more than 16 elements in the array then use a Set for faster performance
380380 // 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 ] ;
385385 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 )
388389 ) {
389- remove_consumer ( signal , dependency , false ) ;
390+ remove_consumer ( signal , dependency ) ;
390391 }
391392 }
392393 }
@@ -415,7 +416,7 @@ function execute_signal_fn(signal) {
415416 }
416417 }
417418 } else if ( dependencies !== null && current_dependencies_index < dependencies . length ) {
418- remove_consumers ( signal , current_dependencies_index , false ) ;
419+ remove_consumers ( signal , current_dependencies_index ) ;
419420 dependencies . length = current_dependencies_index ;
420421 }
421422 return res ;
@@ -435,10 +436,9 @@ function execute_signal_fn(signal) {
435436 * @template V
436437 * @param {import('./types.js').ComputationSignal<V> } signal
437438 * @param {import('./types.js').Signal<V> } dependency
438- * @param {boolean } remove_unowned
439439 * @returns {void }
440440 */
441- function remove_consumer ( signal , dependency , remove_unowned ) {
441+ function remove_consumer ( signal , dependency ) {
442442 const consumers = dependency . c ;
443443 let consumers_length = 0 ;
444444 if ( consumers !== null ) {
@@ -454,25 +454,20 @@ function remove_consumer(signal, dependency, remove_unowned) {
454454 }
455455 }
456456 }
457- if ( remove_unowned && consumers_length === 0 && ( dependency . f & UNOWNED ) !== 0 ) {
457+ if ( consumers_length === 0 && ( dependency . f & UNOWNED ) !== 0 ) {
458458 // If the signal is unowned then we need to make sure to change it to dirty.
459459 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 ) ;
465461 }
466462}
467463
468464/**
469465 * @template V
470466 * @param {import('./types.js').ComputationSignal<V> } signal
471467 * @param {number } start_index
472- * @param {boolean } remove_unowned
473468 * @returns {void }
474469 */
475- function remove_consumers ( signal , start_index , remove_unowned ) {
470+ function remove_consumers ( signal , start_index ) {
476471 const dependencies = signal . d ;
477472 if ( dependencies !== null ) {
478473 const active_dependencies = start_index === 0 ? null : dependencies . slice ( 0 , start_index ) ;
@@ -481,7 +476,7 @@ function remove_consumers(signal, start_index, remove_unowned) {
481476 const dependency = dependencies [ i ] ;
482477 // Avoid removing a consumer if we know that it is active (start_index will not be 0)
483478 if ( active_dependencies === null || ! active_dependencies . includes ( dependency ) ) {
484- remove_consumer ( signal , dependency , remove_unowned ) ;
479+ remove_consumer ( signal , dependency ) ;
485480 }
486481 }
487482 }
@@ -502,7 +497,7 @@ function destroy_references(signal) {
502497 if ( ( reference . f & IS_EFFECT ) !== 0 ) {
503498 destroy_signal ( reference ) ;
504499 } else {
505- remove_consumers ( reference , 0 , true ) ;
500+ remove_consumers ( reference , 0 ) ;
506501 reference . d = null ;
507502 }
508503 }
@@ -585,19 +580,26 @@ function flush_queued_effects(effects) {
585580 const length = effects . length ;
586581 if ( length > 0 ) {
587582 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+ }
598597 }
599598 }
599+ } finally {
600+ is_flushing_effect = previously_flushing_effect ;
600601 }
602+
601603 effects . length = 0 ;
602604 }
603605}
@@ -822,10 +824,7 @@ function update_derived(signal, force_schedule) {
822824 updating_derived = true ;
823825 const value = execute_signal_fn ( signal ) ;
824826 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 ;
829828 set_signal_status ( signal , status ) ;
830829 const equals = /** @type {import('./types.js').EqualsFunctions } */ ( signal . e ) ;
831830 if ( ! equals ( value , signal . v ) ) {
@@ -1083,7 +1082,10 @@ function mark_subtree_children_inert(signal, inert, visited_blocks) {
10831082 if ( references !== null ) {
10841083 let i ;
10851084 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+ }
10871089 }
10881090 }
10891091}
@@ -1262,7 +1264,7 @@ export function destroy_signal(signal) {
12621264 const destroy = signal . y ;
12631265 const flags = signal . f ;
12641266 destroy_references ( signal ) ;
1265- remove_consumers ( signal , 0 , true ) ;
1267+ remove_consumers ( signal , 0 ) ;
12661268 signal . i =
12671269 signal . r =
12681270 signal . y =
0 commit comments