Skip to content

Commit 8b5446f

Browse files
committed
fix: ensure implicit children snippet renders correctly
place anchors around render tags, not snippet tags fixes #9678
1 parent 3e3ae92 commit 8b5446f

File tree

5 files changed

+53
-13
lines changed

5 files changed

+53
-13
lines changed

.changeset/famous-knives-sneeze.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: ensure implicit children snippet renders correctly

packages/svelte/src/compiler/phases/3-transform/server/transform-server.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,11 +1113,17 @@ const template_visitors = {
11131113
);
11141114
},
11151115
RenderTag(node, context) {
1116-
const snippet_function = context.state.options.dev
1116+
const state = context.state;
1117+
const [anchor, anchor_id] = serialize_anchor(state);
1118+
1119+
state.init.push(anchor);
1120+
state.template.push(t_expression(anchor_id));
1121+
1122+
const snippet_function = state.options.dev
11171123
? b.call('$.validate_snippet', node.expression)
11181124
: node.expression;
11191125
if (node.argument) {
1120-
context.state.template.push(
1126+
state.template.push(
11211127
t_statement(
11221128
b.stmt(
11231129
b.call(
@@ -1129,8 +1135,10 @@ const template_visitors = {
11291135
)
11301136
);
11311137
} else {
1132-
context.state.template.push(t_statement(b.stmt(b.call(snippet_function, b.id('$$payload')))));
1138+
state.template.push(t_statement(b.stmt(b.call(snippet_function, b.id('$$payload')))));
11331139
}
1140+
1141+
state.template.push(t_expression(anchor_id));
11341142
},
11351143
ClassDirective(node) {
11361144
error(node, 'INTERNAL', 'Node should have been handled elsewhere');
@@ -1423,27 +1431,18 @@ const template_visitors = {
14231431
state.template.push(t_expression(id));
14241432
},
14251433
SnippetBlock(node, context) {
1426-
const [dec, id] = serialize_anchor(context.state);
1427-
14281434
// TODO hoist where possible
14291435
/** @type {import('estree').Pattern[]} */
14301436
const args = [b.id('$$payload')];
14311437
if (node.context) {
14321438
args.push(node.context);
14331439
}
14341440

1435-
const out = b.member_id('$$payload.out');
1436-
14371441
context.state.init.push(
14381442
b.function_declaration(
14391443
node.expression,
14401444
args,
1441-
b.block([
1442-
dec,
1443-
b.stmt(b.assignment('+=', out, id)),
1444-
.../** @type {import('estree').BlockStatement} */ (context.visit(node.body)).body,
1445-
b.stmt(b.assignment('+=', out, id))
1446-
])
1445+
b.block(/** @type {import('estree').BlockStatement} */ (context.visit(node.body)).body)
14471446
)
14481447
);
14491448
if (context.state.options.dev) {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
const { children, change } = $props();
3+
</script>
4+
5+
<button onclick={change}>
6+
{@render children()}
7+
</button>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
html: `<button><span>hidden</span></button>`,
6+
7+
async test({ assert, target }) {
8+
const [b1] = target.querySelectorAll('button');
9+
10+
flushSync(() => {
11+
b1?.click();
12+
});
13+
14+
assert.htmlEqual(target.innerHTML, `<button><span>showing</span></button>`);
15+
}
16+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import Button from "./Button.svelte";
3+
4+
let show = $state(false);
5+
</script>
6+
7+
<Button change={() => show = true}>
8+
{#if show}
9+
<span>showing</span>
10+
{:else}
11+
<span>hidden</span>
12+
{/if}
13+
</Button>

0 commit comments

Comments
 (0)