fix: better children snippet / default slot interop (#13734)

- correctly assign children snippet to default slot, fixes #13067
- allow `svelte:fragment` without `let:` directives to be rendered by `@render children()`, fixes #13066
pull/13738/head
Simon H 3 months ago committed by GitHub
parent d0bfd22bef
commit 8251bae8db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: better children snippet / default slot interop

@ -231,7 +231,9 @@ export function build_component(node, component_name, context, anchor = context.
push_prop(b.prop('init', child.expression, child.expression));
// Interop: allows people to pass snippets when component still uses slots
serialized_slots.push(b.init(child.expression.name, b.true));
serialized_slots.push(
b.init(child.expression.name === 'children' ? 'default' : child.expression.name, b.true)
);
continue;
}
@ -273,7 +275,14 @@ export function build_component(node, component_name, context, anchor = context.
);
if (slot_name === 'default' && !has_children_prop) {
if (lets.length === 0 && children.default.every((node) => node.type !== 'SvelteFragment')) {
if (
lets.length === 0 &&
children.default.every(
(node) =>
node.type !== 'SvelteFragment' ||
!node.attributes.some((attr) => attr.type === 'LetDirective')
)
) {
// create `children` prop...
push_prop(
b.init(

@ -120,7 +120,9 @@ export function build_inline_component(node, expression, context) {
push_prop(b.prop('init', child.expression, child.expression));
// Interop: allows people to pass snippets when component still uses slots
serialized_slots.push(b.init(child.expression.name, b.true));
serialized_slots.push(
b.init(child.expression.name === 'children' ? 'default' : child.expression.name, b.true)
);
continue;
}
@ -200,7 +202,11 @@ export function build_inline_component(node, expression, context) {
if (slot_name === 'default' && !has_children_prop) {
if (
lets.default.length === 0 &&
children.default.every((node) => node.type !== 'SvelteFragment')
children.default.every(
(node) =>
node.type !== 'SvelteFragment' ||
!node.attributes.some((attr) => attr.type === 'LetDirective')
)
) {
// create `children` prop...
push_prop(b.prop('init', b.id('children'), slot_fn));

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
html: `<p>bar</p>`
});

@ -0,0 +1,5 @@
<script>
let { children } = $props();
</script>
{@render children()}

@ -0,0 +1,9 @@
<script>
import Child from './child.svelte';
</script>
<Child>
<svelte:fragment>
<p>bar</p>
</svelte:fragment>
</Child>

@ -1,5 +1,5 @@
import { test } from '../../test';
export default test({
html: `<p>Default</p> <p>Named foo</p>`
html: `<p>Default foo</p> <p>Named bar</p>`
});

@ -1,2 +1,2 @@
<p><slot /></p>
<p><slot name="named" foo="foo" /></p>
<p><slot foo="foo" /></p>
<p><slot name="named" bar="bar" /></p>

@ -3,8 +3,10 @@
</script>
<Child>
Default
{#snippet named({ foo })}
Named {foo}
{#snippet children({ foo })}
Default {foo}
{/snippet}
{#snippet named({ bar })}
Named {bar}
{/snippet}
</Child>

Loading…
Cancel
Save