Skip to content

Commit 1f37c02

Browse files
trueadmRich-Harris
andauthored
fix: ensure toStore root effect is connected to correct parent effect (#15574)
* fix: ensure toStore root effect is connected to correct parent effect * prettier --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>
1 parent ade66c6 commit 1f37c02

File tree

4 files changed

+60
-7
lines changed

4 files changed

+60
-7
lines changed

.changeset/twelve-bananas-destroy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: ensure toStore root effect is connected to correct parent effect

packages/svelte/src/store/index-client.js

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import {
66
} from '../internal/client/reactivity/effects.js';
77
import { get, writable } from './shared/index.js';
88
import { createSubscriber } from '../reactivity/create-subscriber.js';
9+
import {
10+
active_effect,
11+
active_reaction,
12+
set_active_effect,
13+
set_active_reaction
14+
} from '../internal/client/runtime.js';
915

1016
export { derived, get, readable, readonly, writable } from './shared/index.js';
1117

@@ -39,19 +45,34 @@ export { derived, get, readable, readonly, writable } from './shared/index.js';
3945
* @returns {Writable<V> | Readable<V>}
4046
*/
4147
export function toStore(get, set) {
42-
let init_value = get();
48+
var effect = active_effect;
49+
var reaction = active_reaction;
50+
var init_value = get();
51+
4352
const store = writable(init_value, (set) => {
4453
// If the value has changed before we call subscribe, then
4554
// we need to treat the value as already having run
46-
let ran = init_value !== get();
55+
var ran = init_value !== get();
4756

4857
// TODO do we need a different implementation on the server?
49-
const teardown = effect_root(() => {
50-
render_effect(() => {
51-
const value = get();
52-
if (ran) set(value);
58+
var teardown;
59+
// Apply the reaction and effect at the time of toStore being called
60+
var previous_reaction = active_reaction;
61+
var previous_effect = active_effect;
62+
set_active_reaction(reaction);
63+
set_active_effect(effect);
64+
65+
try {
66+
teardown = effect_root(() => {
67+
render_effect(() => {
68+
const value = get();
69+
if (ran) set(value);
70+
});
5371
});
54-
});
72+
} finally {
73+
set_active_reaction(previous_reaction);
74+
set_active_effect(previous_effect);
75+
}
5576

5677
ran = true;
5778

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target }) {
6+
let btn = target.querySelector('button');
7+
8+
btn?.click();
9+
flushSync();
10+
11+
assert.htmlEqual(
12+
target.innerHTML,
13+
`<div>Count 1!</div><div>Count from store 1!</div><button>Add 1</button>`
14+
);
15+
}
16+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
import { toStore } from "svelte/store";
3+
4+
let counter = $state(0);
5+
const count = toStore(() => counter, value => counter = value);
6+
</script>
7+
8+
<div>Count {counter}!</div>
9+
<div>Count from store {$count}!</div>
10+
11+
<button onclick={() => counter+=1}>Add 1</button>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy