From 87336a9dbb638940dc0fb786b780010bc42ae011 Mon Sep 17 00:00:00 2001 From: Xia Chao <236466140+bun-unsafe@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:33:18 +0800 Subject: [PATCH] fix: avoid duplicate reaction when reconnecting a derived When a derived is disconnected (its last reader is hidden), then its dependency is changed and the reader is shown again, `reconnect` unconditionally pushed the derived into the dependency's `reactions` array. If it was already present, this left a duplicate entry that `remove_reaction` only removes once, leaking the derived (and any component it is owned by) after unmount. Guard the push with a membership check so a derived is only ever registered once per dependency. --- .changeset/lazy-rivers-connect.md | 5 +++++ packages/svelte/src/internal/client/runtime.js | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .changeset/lazy-rivers-connect.md diff --git a/.changeset/lazy-rivers-connect.md b/.changeset/lazy-rivers-connect.md new file mode 100644 index 0000000000..c2486bdac7 --- /dev/null +++ b/.changeset/lazy-rivers-connect.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: avoid duplicate reaction when reconnecting a derived after its reader is hidden diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index d86c349445..6fe6feaae6 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -736,7 +736,10 @@ function reconnect(derived) { if (derived.deps === null) return; for (const dep of derived.deps) { - (dep.reactions ??= []).push(derived); + var reactions = (dep.reactions ??= []); + if (index_of.call(reactions, derived) === -1) { + reactions.push(derived); + } if ((dep.f & DERIVED) !== 0 && (dep.f & CONNECTED) === 0) { unfreeze_derived_effects(/** @type {Derived} */ (dep));