Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/twelve-bananas-destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: ensure toStore root effect is connected to correct parent effect
35 changes: 28 additions & 7 deletions packages/svelte/src/store/index-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -39,19 +45,34 @@ export { derived, get, readable, readonly, writable } from './shared/index.js';
* @returns {Writable<V> | Readable<V>}
*/
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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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, `<div>Count 1!</div><div>Count from store 1!</div><button>Add 1</button>`);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script>
import { toStore } from "svelte/store";

let counter = $state(0);
const count = toStore(() => counter, value => counter = value);
</script>

<div>Count {counter}!</div>
<div>Count from store {$count}!</div>

<button onclick={() => counter+=1}>Add 1</button>
Loading