fix: correctly cleanup unowned derived dependency memory (#10280)

* fix: correctly cleanup unowned derived dependency memory

* recursive

* recursive
pull/10229/head
Dominic Gannaway 11 months ago committed by GitHub
parent 1538264bd5
commit fb61f4eb70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: correctly cleanup unowned derived dependency memory

@ -498,6 +498,7 @@ function destroy_references(signal) {
if ((reference.f & IS_EFFECT) !== 0) {
destroy_signal(reference);
} else {
destroy_references(reference);
remove_consumers(reference, 0);
reference.d = null;
}
@ -823,6 +824,7 @@ export async function tick() {
function update_derived(signal, force_schedule) {
const previous_updating_derived = updating_derived;
updating_derived = true;
destroy_references(signal);
const value = execute_signal_fn(signal);
updating_derived = previous_updating_derived;
const status = current_skip_consumer || (signal.f & UNOWNED) !== 0 ? DIRTY : CLEAN;
@ -1304,8 +1306,8 @@ export function derived(init) {
signal.i = init;
signal.x = current_component_context;
signal.e = default_equals;
if (!is_unowned) {
push_reference(/** @type {import('./types.js').EffectSignal} */ (current_effect), signal);
if (current_consumer !== null) {
push_reference(current_consumer, signal);
}
return signal;
}

@ -1,5 +1,6 @@
import { describe, assert, it } from 'vitest';
import * as $ from '../../src/internal/client/runtime';
import type { ComputationSignal } from '../../src/internal/client/types';
/**
* @param runes runes mode
@ -199,6 +200,38 @@ describe('signals', () => {
};
});
test('correctly cleanup onowned nested derived values', () => {
return () => {
const nested: ComputationSignal<string>[] = [];
const a = $.source(0);
const b = $.source(0);
const c = $.derived(() => {
const a_2 = $.derived(() => $.get(a) + '!');
const b_2 = $.derived(() => $.get(b) + '?');
nested.push(a_2, b_2);
return { a: $.get(a_2), b: $.get(b_2) };
});
$.get(c);
$.flushSync(() => $.set(a, 1));
$.get(c);
$.flushSync(() => $.set(b, 1));
$.get(c);
// Ensure we're not leaking dependencies
assert.deepEqual(
nested.slice(0, -2).map((s) => s.d),
[null, null, null, null]
);
};
});
// outside of test function so that they are unowned signals
let count = $.source(0);
let calc = $.derived(() => {

Loading…
Cancel
Save