From 38b475f851c7da28cd823913bb3f7b728c958703 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 21 Mar 2025 13:45:15 +0000 Subject: [PATCH 1/2] fix: ensure toStore root effect is connected to correct parent effect --- .changeset/twelve-bananas-destroy.md | 5 +++ packages/svelte/src/store/index-client.js | 35 +++++++++++++++---- .../samples/toStore-subscribe2/_config.js | 13 +++++++ .../samples/toStore-subscribe2/main.svelte | 11 ++++++ 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 .changeset/twelve-bananas-destroy.md create mode 100644 packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/main.svelte diff --git a/.changeset/twelve-bananas-destroy.md b/.changeset/twelve-bananas-destroy.md new file mode 100644 index 000000000000..873ee21877b7 --- /dev/null +++ b/.changeset/twelve-bananas-destroy.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure toStore root effect is connected to correct parent effect diff --git a/packages/svelte/src/store/index-client.js b/packages/svelte/src/store/index-client.js index ae6806ec763f..2f0a1a831a0c 100644 --- a/packages/svelte/src/store/index-client.js +++ b/packages/svelte/src/store/index-client.js @@ -6,6 +6,12 @@ import { } from '../internal/client/reactivity/effects.js'; import { get, writable } from './shared/index.js'; import { createSubscriber } from '../reactivity/create-subscriber.js'; +import { + active_effect, + active_reaction, + set_active_effect, + set_active_reaction +} from '../internal/client/runtime.js'; export { derived, get, readable, readonly, writable } from './shared/index.js'; @@ -39,19 +45,34 @@ export { derived, get, readable, readonly, writable } from './shared/index.js'; * @returns {Writable | Readable} */ export function toStore(get, set) { - let init_value = get(); + var effect = active_effect; + var reaction = active_reaction; + var init_value = get(); + const store = writable(init_value, (set) => { // If the value has changed before we call subscribe, then // we need to treat the value as already having run - let ran = init_value !== get(); + var ran = init_value !== get(); // TODO do we need a different implementation on the server? - const teardown = effect_root(() => { - render_effect(() => { - const value = get(); - if (ran) set(value); + var teardown; + // Apply the reaction and effect at the time of toStore being called + var previous_reaction = active_reaction; + var previous_effect = active_effect; + set_active_reaction(reaction); + set_active_effect(effect); + + try { + teardown = effect_root(() => { + render_effect(() => { + const value = get(); + if (ran) set(value); + }); }); - }); + } finally { + set_active_reaction(previous_reaction); + set_active_effect(previous_effect); + } ran = true; diff --git a/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js b/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js new file mode 100644 index 000000000000..11ab9f0b572d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js @@ -0,0 +1,13 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + let btn = target.querySelector('button'); + + btn?.click(); + flushSync(); + + assert.htmlEqual(target.innerHTML, `
Count 1!
Count from store 1!
`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/main.svelte b/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/main.svelte new file mode 100644 index 000000000000..82d20105b8eb --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/main.svelte @@ -0,0 +1,11 @@ + + +
Count {counter}!
+
Count from store {$count}!
+ + From 44065dabe1b638537211550bf8ec660e43dd0fac Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 21 Mar 2025 10:20:33 -0400 Subject: [PATCH 2/2] prettier --- .../runtime-runes/samples/toStore-subscribe2/_config.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js b/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js index 11ab9f0b572d..bc1793e7a461 100644 --- a/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/toStore-subscribe2/_config.js @@ -8,6 +8,9 @@ export default test({ btn?.click(); flushSync(); - assert.htmlEqual(target.innerHTML, `
Count 1!
Count from store 1!
`); + assert.htmlEqual( + target.innerHTML, + `
Count 1!
Count from store 1!
` + ); } });