@@ -27,7 +27,7 @@ import {
2727import { flush_tasks } from './dom/task.js' ;
2828import { add_owner } from './dev/ownership.js' ;
2929import { mutate , set , source } from './reactivity/sources.js' ;
30- import { destroy_derived , update_derived } from './reactivity/deriveds.js' ;
30+ import { destroy_derived , execute_derived , update_derived } from './reactivity/deriveds.js' ;
3131import * as e from './errors.js' ;
3232import { lifecycle_outside_component } from '../shared/errors.js' ;
3333import { FILENAME } from '../../constants.js' ;
@@ -300,40 +300,44 @@ export function update_reaction(reaction) {
300300 var previous_reaction = active_reaction ;
301301 var previous_skip_reaction = skip_reaction ;
302302 var prev_derived_sources = derived_sources ;
303+ var flags = reaction . f ;
303304
304305 new_deps = /** @type {null | Value[] } */ ( null ) ;
305306 skipped_deps = 0 ;
306307 untracked_writes = null ;
307- active_reaction = ( reaction . f & ( BRANCH_EFFECT | ROOT_EFFECT ) ) === 0 ? reaction : null ;
308- skip_reaction = ! is_flushing_effect && ( reaction . f & UNOWNED ) !== 0 ;
308+ active_reaction = ( flags & ( BRANCH_EFFECT | ROOT_EFFECT ) ) === 0 ? reaction : null ;
309+ skip_reaction = ! is_flushing_effect && ( flags & UNOWNED ) !== 0 ;
309310 derived_sources = null ;
310311
311312 try {
312313 var result = /** @type {Function } */ ( 0 , reaction . fn ) ( ) ;
313314 var deps = reaction . deps ;
314315
315- if ( new_deps !== null ) {
316- var i ;
316+ // Avoid doing work on an effect/derived that might have become destroyed
317+ if ( ( flags & DESTROYED ) === 0 ) {
318+ if ( new_deps !== null ) {
319+ var i ;
317320
318- remove_reactions ( reaction , skipped_deps ) ;
321+ remove_reactions ( reaction , skipped_deps ) ;
319322
320- if ( deps !== null && skipped_deps > 0 ) {
321- deps . length = skipped_deps + new_deps . length ;
322- for ( i = 0 ; i < new_deps . length ; i ++ ) {
323- deps [ skipped_deps + i ] = new_deps [ i ] ;
323+ if ( deps !== null && skipped_deps > 0 ) {
324+ deps . length = skipped_deps + new_deps . length ;
325+ for ( i = 0 ; i < new_deps . length ; i ++ ) {
326+ deps [ skipped_deps + i ] = new_deps [ i ] ;
327+ }
328+ } else {
329+ reaction . deps = deps = new_deps ;
324330 }
325- } else {
326- reaction . deps = deps = new_deps ;
327- }
328331
329- if ( ! skip_reaction ) {
330- for ( i = skipped_deps ; i < deps . length ; i ++ ) {
331- ( deps [ i ] . reactions ??= [ ] ) . push ( reaction ) ;
332+ if ( ! skip_reaction ) {
333+ for ( i = skipped_deps ; i < deps . length ; i ++ ) {
334+ ( deps [ i ] . reactions ??= [ ] ) . push ( reaction ) ;
335+ }
332336 }
337+ } else if ( deps !== null && skipped_deps < deps . length ) {
338+ remove_reactions ( reaction , skipped_deps ) ;
339+ deps . length = skipped_deps ;
333340 }
334- } else if ( deps !== null && skipped_deps < deps . length ) {
335- remove_reactions ( reaction , skipped_deps ) ;
336- deps . length = skipped_deps ;
337341 }
338342
339343 return result ;
@@ -739,9 +743,12 @@ export async function tick() {
739743 */
740744export function get ( signal ) {
741745 var flags = signal . f ;
746+ var is_derived = ( flags & DERIVED ) !== 0 ;
742747
743- if ( ( flags & DESTROYED ) !== 0 ) {
744- return signal . v ;
748+ // If the derived is destroyed, just execute it again without retaining
749+ // it's memoisation properties – as the derived is stale
750+ if ( is_derived && ( flags & DESTROYED ) !== 0 ) {
751+ return execute_derived ( /** @type {Derived } */ ( signal ) ) ;
745752 }
746753
747754 if ( is_signals_recorded ) {
@@ -778,7 +785,7 @@ export function get(signal) {
778785 }
779786 }
780787
781- if ( ( flags & DERIVED ) !== 0 ) {
788+ if ( is_derived ) {
782789 var derived = /** @type {Derived } */ ( signal ) ;
783790
784791 if ( check_dirtiness ( derived ) ) {
0 commit comments