From 2aae8c4b83e64a84088672a02dfa6becf41d5b9d Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 27 Jun 2024 09:59:05 +0100 Subject: [PATCH] fix: ensure correct each block anchoring is applied to new entries --- .changeset/kind-donuts-enjoy.md | 5 +++ .../src/internal/client/dom/blocks/each.js | 5 ++- .../samples/each-updates-8/_config.js | 33 +++++++++++++++++++ .../samples/each-updates-8/main.svelte | 23 +++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 .changeset/kind-donuts-enjoy.md create mode 100644 packages/svelte/tests/runtime-runes/samples/each-updates-8/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/each-updates-8/main.svelte diff --git a/.changeset/kind-donuts-enjoy.md b/.changeset/kind-donuts-enjoy.md new file mode 100644 index 0000000000..03aa97610d --- /dev/null +++ b/.changeset/kind-donuts-enjoy.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure correct each block anchoring is applied to new entries diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index e20d4ec41f..90b4febbd6 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -291,7 +291,10 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) { item = items.get(key); if (item === undefined) { - var child_anchor = current ? get_first_node(current.e) : anchor; + var effect_dom = current?.e.dom; + var child_anchor = /** @type {Node} */ ( + effect_dom ? (is_array(effect_dom) ? effect_dom[0] : effect_dom) : anchor + ); prev = create_item(child_anchor, prev, prev.next, value, key, i, render_fn, flags); diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-8/_config.js b/packages/svelte/tests/runtime-runes/samples/each-updates-8/_config.js new file mode 100644 index 0000000000..e01fcf6f97 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-8/_config.js @@ -0,0 +1,33 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `

first

message 1

`, + + async test({ assert, target }) { + /** + * @type {{ click: () => void; }} + */ + let btn1; + + [btn1] = target.querySelectorAll('button'); + + flushSync(() => { + btn1.click(); + }); + + assert.htmlEqual(target.innerHTML, `

first

message 1

message 2

`); + + await Promise.resolve(); + + assert.htmlEqual(target.innerHTML, `

first

message 1

message 2

`); + + flushSync(() => { + btn1.click(); + }); + + await Promise.resolve(); + + assert.htmlEqual(target.innerHTML, `

first

message 1

message 2

message 3

`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-8/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-updates-8/main.svelte new file mode 100644 index 0000000000..869ccdc8dd --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-8/main.svelte @@ -0,0 +1,23 @@ + + + + +{#each messages as msg, i (`${msg.id}_${msg.tmpId ?? ""}`)} + {#if i === 0} +

first

+ {/if} +

{msg.content}

+{/each}