mirror of https://github.com/sveltejs/svelte
fix: guard contents updated before the guard itself (#16930)
Fixes #16850, fixes #16775, fixes #16795, fixes #16982 #16631 introduced a bug that results in the effects within guards being evaluated before the guards themselves. This fix makes sure to iterate the block effects in the correct order (top down) --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>pull/16995/head
parent
7d9ea8ea99
commit
f549478dd0
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: ensure guards (eg. if, each, key) run before their contents
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
import { flushSync } from 'svelte';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['client'],
|
||||||
|
async test({ target, assert, logs }) {
|
||||||
|
const button = target.querySelector('button');
|
||||||
|
|
||||||
|
button?.click();
|
||||||
|
flushSync();
|
||||||
|
button?.click();
|
||||||
|
flushSync();
|
||||||
|
button?.click();
|
||||||
|
flushSync();
|
||||||
|
button?.click();
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
assert.deepEqual(logs, ['two', 'one', 'two', 'one', 'two']);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
let b = $state(false);
|
||||||
|
let v = $state("two");
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
v = b ? "one" : "two";
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => b = !b}>Trigger</button>
|
||||||
|
|
||||||
|
{#if v === "one"}
|
||||||
|
<div>if1 matched! {console.log('one')}</div>
|
||||||
|
{:else if v === "two"}
|
||||||
|
<div>if2 matched! {console.log('two')}</div>
|
||||||
|
{:else}
|
||||||
|
<div>nothing matched {console.log('else')}</div>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
import { flushSync } from 'svelte';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['client'],
|
||||||
|
async test({ target, assert }) {
|
||||||
|
const button = target.querySelector('button');
|
||||||
|
|
||||||
|
flushSync(() => button?.click());
|
||||||
|
|
||||||
|
assert.equal(target.textContent?.trim(), 'Trigger');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<script>
|
||||||
|
let centerRow = $state({ nested: { optional: 2, required: 3 } });
|
||||||
|
|
||||||
|
let someChange = $state(false);
|
||||||
|
$effect(() => {
|
||||||
|
if (someChange) centerRow = undefined;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if centerRow?.nested}
|
||||||
|
{#if centerRow?.nested?.optional != undefined && centerRow.nested.optional > 0}
|
||||||
|
op: {centerRow.nested.optional}<br />
|
||||||
|
{:else}
|
||||||
|
req: {centerRow.nested.required}<br />
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<button onclick={() => (someChange = true)}>Trigger</button>
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<script>
|
||||||
|
let { p } = $props();
|
||||||
|
$effect.pre(() => {
|
||||||
|
console.log('running ' + p)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
mode: ['client'],
|
||||||
|
async test({ assert, target, logs }) {
|
||||||
|
const button = target.querySelector('button');
|
||||||
|
|
||||||
|
button?.click();
|
||||||
|
flushSync();
|
||||||
|
assert.deepEqual(logs, ['pre', 'running b', 'pre', 'pre']);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<script>
|
||||||
|
import Component from './Component.svelte';
|
||||||
|
|
||||||
|
let p = $state('b');
|
||||||
|
|
||||||
|
$effect.pre(() => {
|
||||||
|
console.log('pre')
|
||||||
|
if (p === 'a') p = null;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if p || !p}
|
||||||
|
{#if p}
|
||||||
|
<Component {p} />
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<button onclick={() => p = 'a'}>a</button>
|
||||||
Loading…
Reference in new issue