diff --git a/.changeset/great-ghosts-unite.md b/.changeset/great-ghosts-unite.md new file mode 100644 index 000000000000..2973737cfd11 --- /dev/null +++ b/.changeset/great-ghosts-unite.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: link offscreen items and last effect in each block correctly diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index 320c0346902c..77e669aa22c1 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -637,6 +637,10 @@ function link(state, prev, next) { state.first = next; state.effect.first = next && next.e; } else { + if (prev.e === state.effect.last && next !== null) { + state.effect.last = next.e; + } + if (prev.e.next) { prev.e.next.prev = null; } @@ -648,6 +652,10 @@ function link(state, prev, next) { if (next === null) { state.effect.last = prev && prev.e; } else { + if (next.e === state.effect.last && prev === null) { + state.effect.last = next.e.prev; + } + if (next.e.prev) { next.e.prev.next = null; } diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-10/_config.js b/packages/svelte/tests/runtime-runes/samples/each-updates-10/_config.js new file mode 100644 index 000000000000..d5c9e36f1db6 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-10/_config.js @@ -0,0 +1,51 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + const [add, adjust] = target.querySelectorAll('button'); + + add.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + ` +

Keyed

+
Item: 1. Index: 0
+
Item: 0. Index: 1
+

Unkeyed

+
Item: 1. Index: 0
+
Item: 0. Index: 1
` + ); + + add.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + ` +

Keyed

+
Item: 2. Index: 0
+
Item: 1. Index: 1
+
Item: 0. Index: 2
+

Unkeyed

+
Item: 2. Index: 0
+
Item: 1. Index: 1
+
Item: 0. Index: 2
` + ); + + adjust.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + ` +

Keyed

+
Item: 2. Index: 0
+
Item: 1. Index: 1
+
Item: 10. Index: 2
+

Unkeyed

+
Item: 2. Index: 0
+
Item: 1. Index: 1
+
Item: 10. Index: 2
` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-10/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-updates-10/main.svelte new file mode 100644 index 000000000000..20ce8279de36 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-10/main.svelte @@ -0,0 +1,16 @@ + + + + + +

Keyed

+{#each items as item, index (item)} +
Item: {item.t}. Index: {index}
+{/each} + +

Unkeyed

+{#each items as item, index} +
Item: {item.t}. Index: {index}
+{/each}