Skip to content

Commit 52051b4

Browse files
committed
fix: better children snippet / default slot interop
- correctly assign children snippet to default slot, fixes #13067 - allow `svelte:fragment` without `let:` directives to be rendered by `@render children()`, fixes #13066
1 parent 41b5cd6 commit 52051b4

File tree

9 files changed

+51
-10
lines changed

9 files changed

+51
-10
lines changed

.changeset/tidy-spies-beg.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: better children snippet / default slot interop

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ export function build_component(node, component_name, context, anchor = context.
231231
push_prop(b.prop('init', child.expression, child.expression));
232232

233233
// Interop: allows people to pass snippets when component still uses slots
234-
serialized_slots.push(b.init(child.expression.name, b.true));
234+
serialized_slots.push(
235+
b.init(child.expression.name === 'children' ? 'default' : child.expression.name, b.true)
236+
);
235237

236238
continue;
237239
}
@@ -273,7 +275,14 @@ export function build_component(node, component_name, context, anchor = context.
273275
);
274276

275277
if (slot_name === 'default' && !has_children_prop) {
276-
if (lets.length === 0 && children.default.every((node) => node.type !== 'SvelteFragment')) {
278+
if (
279+
lets.length === 0 &&
280+
children.default.every(
281+
(node) =>
282+
node.type !== 'SvelteFragment' ||
283+
!node.attributes.some((attr) => attr.type === 'LetDirective')
284+
)
285+
) {
277286
// create `children` prop...
278287
push_prop(
279288
b.init(

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ export function build_inline_component(node, expression, context) {
120120
push_prop(b.prop('init', child.expression, child.expression));
121121

122122
// Interop: allows people to pass snippets when component still uses slots
123-
serialized_slots.push(b.init(child.expression.name, b.true));
123+
serialized_slots.push(
124+
b.init(child.expression.name === 'children' ? 'default' : child.expression.name, b.true)
125+
);
124126

125127
continue;
126128
}
@@ -200,7 +202,11 @@ export function build_inline_component(node, expression, context) {
200202
if (slot_name === 'default' && !has_children_prop) {
201203
if (
202204
lets.default.length === 0 &&
203-
children.default.every((node) => node.type !== 'SvelteFragment')
205+
children.default.every(
206+
(node) =>
207+
node.type !== 'SvelteFragment' ||
208+
!node.attributes.some((attr) => attr.type === 'LetDirective')
209+
)
204210
) {
205211
// create `children` prop...
206212
push_prop(b.prop('init', b.id('children'), slot_fn));
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: `<p>bar</p>`
5+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let { children } = $props();
3+
</script>
4+
5+
{@render children()}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script>
2+
import Child from './child.svelte';
3+
</script>
4+
5+
<Child>
6+
<svelte:fragment>
7+
<p>bar</p>
8+
</svelte:fragment>
9+
</Child>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { test } from '../../test';
22

33
export default test({
4-
html: `<p>Default</p> <p>Named foo</p>`
4+
html: `<p>Default foo</p> <p>Named bar</p>`
55
});
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
<p><slot /></p>
2-
<p><slot name="named" foo="foo" /></p>
1+
<p><slot foo="foo" /></p>
2+
<p><slot name="named" bar="bar" /></p>

packages/svelte/tests/runtime-runes/samples/snippets-as-slots/main.svelte

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
</script>
44

55
<Child>
6-
Default
7-
{#snippet named({ foo })}
8-
Named {foo}
6+
{#snippet children({ foo })}
7+
Default {foo}
8+
{/snippet}
9+
{#snippet named({ bar })}
10+
Named {bar}
911
{/snippet}
1012
</Child>

0 commit comments

Comments
 (0)