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