From 794b8f3dfd14fad5d2d67dea7607bae8185cf800 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Tue, 2 Dec 2025 23:27:04 +0100 Subject: [PATCH 1/2] fix: keep reactions up to date even when read outside of effect (#17295) In #17105 one line in `update_reaction` was changed that can cause reactivity loss. It checks if the reaction is updated inside of an effect and only then will push to the reactions. The prior version had an additional check to still add to the reactions if there is already at least one reaction on the derived, indicating it is connected. Removing this check fixes #17263 while keeping correctness: a connected derived by definition at least has one reaction and therefore can properly cleanup. --- .changeset/small-llamas-drum.md | 5 ++++ .../svelte/src/internal/client/runtime.js | 2 +- packages/svelte/tests/signals/test.ts | 25 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 .changeset/small-llamas-drum.md diff --git a/.changeset/small-llamas-drum.md b/.changeset/small-llamas-drum.md new file mode 100644 index 0000000000..3848f83920 --- /dev/null +++ b/.changeset/small-llamas-drum.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: keep reactions up to date even when read outside of effect diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 100804a974..64c8409b8f 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -278,7 +278,7 @@ export function update_reaction(reaction) { reaction.deps = deps = new_deps; } - if (is_updating_effect && effect_tracking() && (reaction.f & CONNECTED) !== 0) { + if (effect_tracking() && (reaction.f & CONNECTED) !== 0) { for (i = skipped_deps; i < deps.length; i++) { (deps[i].reactions ??= []).push(reaction); } diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 13430609a8..23c4bb42f9 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -1418,6 +1418,31 @@ describe('signals', () => { }; }); + test('derived when connected should add new dependency to its reaction even when read outside effect', () => { + let count_a = state(0); + let count_b = state(0); + let which = state(true); + let double = derived(() => ($.get(which) ? $.get(count_a) * 2 : $.get(count_b) * 2)); + + render_effect(() => { + $.get(double); + }); + + return () => { + flushSync(); + assert.equal($.get(double!), 0); + + set(which, false); + $.get(double); // read before render effect has a chance to rerun + flushSync(); + assert.equal($.get(double!), 0); + + set(count_b, 1); + flushSync(); + assert.equal($.get(double!), 2); + }; + }); + test('$effect.root inside deriveds stay alive independently', () => { const log: any[] = []; const c = state(0); From f091b11eab0b0f274b6332ae2aa081679f74064b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:49:10 -0500 Subject: [PATCH 2/2] Version Packages (#17286) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/petite-mammals-talk.md | 5 ----- .changeset/sad-paths-build.md | 5 ----- .changeset/small-llamas-drum.md | 5 ----- packages/svelte/CHANGELOG.md | 10 ++++++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 6 files changed, 12 insertions(+), 17 deletions(-) delete mode 100644 .changeset/petite-mammals-talk.md delete mode 100644 .changeset/sad-paths-build.md delete mode 100644 .changeset/small-llamas-drum.md diff --git a/.changeset/petite-mammals-talk.md b/.changeset/petite-mammals-talk.md deleted file mode 100644 index 97edc1953a..0000000000 --- a/.changeset/petite-mammals-talk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -chore: move DOM-related effect properties to `effect.nodes` diff --git a/.changeset/sad-paths-build.md b/.changeset/sad-paths-build.md deleted file mode 100644 index f64d6f766c..0000000000 --- a/.changeset/sad-paths-build.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: allow `$props.id()` to occur after an `await` diff --git a/.changeset/small-llamas-drum.md b/.changeset/small-llamas-drum.md deleted file mode 100644 index 3848f83920..0000000000 --- a/.changeset/small-llamas-drum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: keep reactions up to date even when read outside of effect diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 2e8b9e814f..dc3b63ffd6 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,15 @@ # svelte +## 5.45.4 + +### Patch Changes + +- chore: move DOM-related effect properties to `effect.nodes` ([#17293](https://github.com/sveltejs/svelte/pull/17293)) + +- fix: allow `$props.id()` to occur after an `await` ([#17285](https://github.com/sveltejs/svelte/pull/17285)) + +- fix: keep reactions up to date even when read outside of effect ([#17295](https://github.com/sveltejs/svelte/pull/17295)) + ## 5.45.3 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index b3af271800..2bfc07031d 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.45.3", + "version": "5.45.4", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 69f6907a49..abfc05b688 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.45.3'; +export const VERSION = '5.45.4'; export const PUBLIC_VERSION = '5';