File tree Expand file tree Collapse file tree 3 files changed +42
-2
lines changed Expand file tree Collapse file tree 3 files changed +42
-2
lines changed Original file line number Diff line number Diff line change
1
+ ---
2
+ " svelte " : patch
3
+ ---
4
+
5
+ fix: correctly cleanup unowned derived dependency memory
Original file line number Diff line number Diff line change @@ -498,6 +498,7 @@ function destroy_references(signal) {
498
498
if ( ( reference . f & IS_EFFECT ) !== 0 ) {
499
499
destroy_signal ( reference ) ;
500
500
} else {
501
+ destroy_references ( reference ) ;
501
502
remove_consumers ( reference , 0 ) ;
502
503
reference . d = null ;
503
504
}
@@ -823,6 +824,7 @@ export async function tick() {
823
824
function update_derived ( signal , force_schedule ) {
824
825
const previous_updating_derived = updating_derived ;
825
826
updating_derived = true ;
827
+ destroy_references ( signal ) ;
826
828
const value = execute_signal_fn ( signal ) ;
827
829
updating_derived = previous_updating_derived ;
828
830
const status = current_skip_consumer || ( signal . f & UNOWNED ) !== 0 ? DIRTY : CLEAN ;
@@ -1304,8 +1306,8 @@ export function derived(init) {
1304
1306
signal . i = init ;
1305
1307
signal . x = current_component_context ;
1306
1308
signal . e = default_equals ;
1307
- if ( ! is_unowned ) {
1308
- push_reference ( /** @type { import('./types.js').EffectSignal } */ ( current_effect ) , signal ) ;
1309
+ if ( current_consumer !== null ) {
1310
+ push_reference ( current_consumer , signal ) ;
1309
1311
}
1310
1312
return signal ;
1311
1313
}
Original file line number Diff line number Diff line change 1
1
import { describe , assert , it } from 'vitest' ;
2
2
import * as $ from '../../src/internal/client/runtime' ;
3
+ import type { ComputationSignal } from '../../src/internal/client/types' ;
3
4
4
5
/**
5
6
* @param runes runes mode
@@ -199,6 +200,38 @@ describe('signals', () => {
199
200
} ;
200
201
} ) ;
201
202
203
+ test ( 'correctly cleanup onowned nested derived values' , ( ) => {
204
+ return ( ) => {
205
+ const nested : ComputationSignal < string > [ ] = [ ] ;
206
+
207
+ const a = $ . source ( 0 ) ;
208
+ const b = $ . source ( 0 ) ;
209
+ const c = $ . derived ( ( ) => {
210
+ const a_2 = $ . derived ( ( ) => $ . get ( a ) + '!' ) ;
211
+ const b_2 = $ . derived ( ( ) => $ . get ( b ) + '?' ) ;
212
+ nested . push ( a_2 , b_2 ) ;
213
+
214
+ return { a : $ . get ( a_2 ) , b : $ . get ( b_2 ) } ;
215
+ } ) ;
216
+
217
+ $ . get ( c ) ;
218
+
219
+ $ . flushSync ( ( ) => $ . set ( a , 1 ) ) ;
220
+
221
+ $ . get ( c ) ;
222
+
223
+ $ . flushSync ( ( ) => $ . set ( b , 1 ) ) ;
224
+
225
+ $ . get ( c ) ;
226
+
227
+ // Ensure we're not leaking dependencies
228
+ assert . deepEqual (
229
+ nested . slice ( 0 , - 2 ) . map ( ( s ) => s . d ) ,
230
+ [ null , null , null , null ]
231
+ ) ;
232
+ } ;
233
+ } ) ;
234
+
202
235
// outside of test function so that they are unowned signals
203
236
let count = $ . source ( 0 ) ;
204
237
let calc = $ . derived ( ( ) => {
You can’t perform that action at this time.
0 commit comments