fix: improve each block fallback handling (#9914)

pull/9917/head
Dominic Gannaway 10 months ago committed by GitHub
parent 3a4a09102c
commit b1efd8c4cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: improve each block fallback handling

@ -119,6 +119,14 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
current_fallback = fallback;
};
/** @param {import('./types.js').EachBlock} block */
const clear_each = (block) => {
const flags = block.f;
const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;
const anchor_node = block.a;
reconcile_fn(array, block, anchor_node, is_controlled, render_fn, flags, true, keys);
};
const each = render_effect(
() => {
/** @type {V[]} */
@ -137,7 +145,9 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
if (fallback_fn !== null) {
if (length === 0) {
if (block.v.length !== 0 || render === null) {
clear_each(block);
create_fallback_effect();
return;
}
} else if (block.v.length === 0 && current_fallback !== null) {
const fallback = current_fallback;
@ -160,17 +170,7 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
false
);
render = render_effect(
/** @param {import('./types.js').EachBlock} block */
(block) => {
const flags = block.f;
const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;
const anchor_node = block.a;
reconcile_fn(array, block, anchor_node, is_controlled, render_fn, flags, true, keys);
},
block,
true
);
render = render_effect(clear_each, block, true);
push_destroy_fn(each, () => {
const flags = block.f;

@ -0,0 +1,17 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target, component }) {
const [b1] = target.querySelectorAll('button');
assert.htmlEqual(target.innerHTML, '<div>abc</div><button>Toggle</button>');
flushSync(() => {
b1.click();
});
assert.htmlEqual(target.innerHTML, '<div>Fallback</div><button>Toggle</button>');
flushSync(() => {
b1.click();
});
assert.htmlEqual(target.innerHTML, '<div>abc</div><button>Toggle</button>');
}
});

@ -0,0 +1,22 @@
<script>
let data = $state({a:1, b:2, c:3});
let filter = $state(false);
function toggle_filter(){
if(filter) {
filter = false;
data = {a:1, b:2, c:3};
} else {
filter = true;
data = {};
}
}
</script>
<div>
{#each Object.keys(data) as key}
{key}
{:else}
Fallback
{/each}
</div>
<button onclick={toggle_filter}>Toggle</button>
Loading…
Cancel
Save