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 <rich.harris@vercel.com>
Co-authored-by: Dominic Gannaway <dg@domgan.com>
pull/13085/head
Simon H 2 months ago committed by GitHub
parent cf6b64c6c0
commit d776e522d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure reactive graph is fully traversed in the marking phase for non-runes mode

@ -33,7 +33,8 @@ import {
UNOWNED, UNOWNED,
CLEAN, CLEAN,
INSPECT_EFFECT, INSPECT_EFFECT,
HEAD_EFFECT HEAD_EFFECT,
MAYBE_DIRTY
} from '../constants.js'; } from '../constants.js';
import { set } from './sources.js'; import { set } from './sources.js';
import * as e from '../errors.js'; import * as e from '../errors.js';
@ -281,6 +282,12 @@ export function legacy_pre_effect_reset() {
for (var token of context.l.r1) { for (var token of context.l.r1) {
var effect = token.effect; var effect = token.effect;
// If the effect is CLEAN, then make it MAYBE_DIRTY. This ensures we traverse through
// the effects dependencies and correctly ensure each dependency is up-to-date.
if ((effect.f & CLEAN) !== 0) {
set_signal_status(effect, MAYBE_DIRTY);
}
if (check_dirtiness(effect)) { if (check_dirtiness(effect)) {
update_effect(effect); update_effect(effect);
} }

@ -0,0 +1,15 @@
<script>
import { writable } from 'svelte/store';
import { store } from './state.js';
export let value;
const copy = writable(value);
$: {
copy.set(value);
store.set({ value });
}
</script>
<p>{$copy}</p>

@ -0,0 +1,18 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
import { store } from './state.js';
export default test({
html: '<p>0</p><button>1</button>',
before_test() {
store.set({ value: 0 });
},
async test({ assert, target }) {
const button = target.querySelector('button');
flushSync(() => button?.click());
assert.htmlEqual(target.innerHTML, '<p>1</p><button>1</button>');
}
});

@ -0,0 +1,8 @@
<script>
import { store } from './state.js';
import Child from './Child.svelte';
</script>
<Child value={$store.value} />
<button on:click={() => store.set({ value: 1 })}>1</button>

@ -0,0 +1,3 @@
import { writable } from 'svelte/store';
export const store = writable({ value: 0 });
Loading…
Cancel
Save