diff --git a/.changeset/chilly-bats-build.md b/.changeset/chilly-bats-build.md new file mode 100644 index 0000000000..872e4c79c4 --- /dev/null +++ b/.changeset/chilly-bats-build.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: hydrate each blocks inside element correctly diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js index 62d07014ee..3588f2843a 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js @@ -99,7 +99,14 @@ export function process_children(nodes, initial, is_element, context) { if (is_static_element(node, context.state)) { skipped += 1; - } else if (node.type === 'EachBlock' && nodes.length === 1 && is_element) { + } else if ( + node.type === 'EachBlock' && + nodes.length === 1 && + is_element && + // In case it's wrapped in async the async logic will want to skip sibling nodes up until the end, hence we cannot make this controlled + // TODO switch this around and instead optimize for elements with a single block child and not require extra comments (neither for async nor normally) + !(node.body.metadata.has_await || node.metadata.expression.has_await) + ) { node.metadata.is_controlled = true; } else { const id = flush_node(false, node.type === 'RegularElement' ? node.name : 'node'); diff --git a/packages/svelte/tests/runtime-runes/samples/async-each-sibling/_config.js b/packages/svelte/tests/runtime-runes/samples/async-each-sibling/_config.js new file mode 100644 index 0000000000..ff10a48f11 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-each-sibling/_config.js @@ -0,0 +1,16 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + mode: ['async-server', 'hydrate', 'client'], + ssrHtml: ` `, + + async test({ assert, target }) { + await tick(); + const [add] = target.querySelectorAll('button'); + + add.click(); + await tick(); + assert.htmlEqual(target.innerHTML, ` `); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-each-sibling/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-each-sibling/main.svelte new file mode 100644 index 0000000000..2c35440511 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-each-sibling/main.svelte @@ -0,0 +1,11 @@ + + + + +