Skip to content

Commit d776e52

Browse files
dummdidummRich-Harristrueadm
authored
fix: ensure reactive graph is fully traversed in the marking phase for non-runes mode (#13059)
* fix: ensure signal status is set in legacy mode fixes #13051 * add (failing) test * alternative fix * add changeset * alternative fix * add comment --------- Co-authored-by: Rich Harris <[email protected]> Co-authored-by: Dominic Gannaway <[email protected]>
1 parent cf6b64c commit d776e52

File tree

6 files changed

+57
-1
lines changed

6 files changed

+57
-1
lines changed

.changeset/angry-weeks-design.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 reactive graph is fully traversed in the marking phase for non-runes mode

packages/svelte/src/internal/client/reactivity/effects.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import {
3333
UNOWNED,
3434
CLEAN,
3535
INSPECT_EFFECT,
36-
HEAD_EFFECT
36+
HEAD_EFFECT,
37+
MAYBE_DIRTY
3738
} from '../constants.js';
3839
import { set } from './sources.js';
3940
import * as e from '../errors.js';
@@ -281,6 +282,12 @@ export function legacy_pre_effect_reset() {
281282
for (var token of context.l.r1) {
282283
var effect = token.effect;
283284

285+
// If the effect is CLEAN, then make it MAYBE_DIRTY. This ensures we traverse through
286+
// the effects dependencies and correctly ensure each dependency is up-to-date.
287+
if ((effect.f & CLEAN) !== 0) {
288+
set_signal_status(effect, MAYBE_DIRTY);
289+
}
290+
284291
if (check_dirtiness(effect)) {
285292
update_effect(effect);
286293
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script>
2+
import { writable } from 'svelte/store';
3+
import { store } from './state.js';
4+
5+
export let value;
6+
7+
const copy = writable(value);
8+
9+
$: {
10+
copy.set(value);
11+
store.set({ value });
12+
}
13+
</script>
14+
15+
<p>{$copy}</p>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
import { store } from './state.js';
4+
5+
export default test({
6+
html: '<p>0</p><button>1</button>',
7+
8+
before_test() {
9+
store.set({ value: 0 });
10+
},
11+
12+
async test({ assert, target }) {
13+
const button = target.querySelector('button');
14+
flushSync(() => button?.click());
15+
16+
assert.htmlEqual(target.innerHTML, '<p>1</p><button>1</button>');
17+
}
18+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
import { store } from './state.js';
3+
import Child from './Child.svelte';
4+
</script>
5+
6+
<Child value={$store.value} />
7+
8+
<button on:click={() => store.set({ value: 1 })}>1</button>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { writable } from 'svelte/store';
2+
3+
export const store = writable({ value: 0 });

0 commit comments

Comments
 (0)