diff --git a/.changeset/famous-knives-sneeze.md b/.changeset/famous-knives-sneeze.md new file mode 100644 index 0000000000..9c7dcb42d3 --- /dev/null +++ b/.changeset/famous-knives-sneeze.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure implicit children snippet renders correctly diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index 4f8e510709..37f4cc757f 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -1125,11 +1125,17 @@ const template_visitors = { ); }, RenderTag(node, context) { - const snippet_function = context.state.options.dev + const state = context.state; + const [anchor, anchor_id] = serialize_anchor(state); + + state.init.push(anchor); + state.template.push(t_expression(anchor_id)); + + const snippet_function = state.options.dev ? b.call('$.validate_snippet', node.expression) : node.expression; if (node.argument) { - context.state.template.push( + state.template.push( t_statement( b.stmt( b.call( @@ -1141,8 +1147,10 @@ const template_visitors = { ) ); } else { - context.state.template.push(t_statement(b.stmt(b.call(snippet_function, b.id('$$payload'))))); + state.template.push(t_statement(b.stmt(b.call(snippet_function, b.id('$$payload'))))); } + + state.template.push(t_expression(anchor_id)); }, ClassDirective(node) { error(node, 'INTERNAL', 'Node should have been handled elsewhere'); @@ -1435,8 +1443,6 @@ const template_visitors = { state.template.push(t_expression(id)); }, SnippetBlock(node, context) { - const [dec, id] = serialize_anchor(context.state); - // TODO hoist where possible /** @type {import('estree').Pattern[]} */ const args = [b.id('$$payload')]; @@ -1444,18 +1450,11 @@ const template_visitors = { args.push(node.context); } - const out = b.member_id('$$payload.out'); - context.state.init.push( b.function_declaration( node.expression, args, - b.block([ - dec, - b.stmt(b.assignment('+=', out, id)), - .../** @type {import('estree').BlockStatement} */ (context.visit(node.body)).body, - b.stmt(b.assignment('+=', out, id)) - ]) + /** @type {import('estree').BlockStatement} */ (context.visit(node.body)) ) ); if (context.state.options.dev) { diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/Button.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/Button.svelte new file mode 100644 index 0000000000..bf8ea31e99 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/Button.svelte @@ -0,0 +1,7 @@ + + + diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/_config.js new file mode 100644 index 0000000000..cd15ff7212 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/_config.js @@ -0,0 +1,16 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: ``, + + async test({ assert, target }) { + const [b1] = target.querySelectorAll('button'); + + flushSync(() => { + b1?.click(); + }); + + assert.htmlEqual(target.innerHTML, ``); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/main.svelte new file mode 100644 index 0000000000..55a095bf3c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-dynamic-children/main.svelte @@ -0,0 +1,13 @@ + + +