Skip to content

Commit 3494f4c

Browse files
committed
allow passing snippets rendered as slots
1 parent 1bdf919 commit 3494f4c

File tree

9 files changed

+68
-33
lines changed

9 files changed

+68
-33
lines changed

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,8 @@ function serialize_inline_component(node, component_name, context) {
789789

790790
/** @type {import('estree').Statement[]} */
791791
const snippet_declarations = [];
792+
/** @type {import('estree').Property[]} */
793+
const serialized_slots = [];
792794

793795
// Group children by slot
794796
for (const child of node.fragment.nodes) {
@@ -802,6 +804,8 @@ function serialize_inline_component(node, component_name, context) {
802804
});
803805

804806
push_prop(b.prop('init', child.expression, child.expression));
807+
// Back/forward compatibility: allows people to pass snippets when component still uses slots
808+
serialized_slots.push(b.init(child.expression.name, b.true));
805809

806810
continue;
807811
}
@@ -825,8 +829,6 @@ function serialize_inline_component(node, component_name, context) {
825829
}
826830

827831
// Serialize each slot
828-
/** @type {import('estree').Property[]} */
829-
const serialized_slots = [];
830832
for (const slot_name of Object.keys(children)) {
831833
const body = create_block(node, `${node.name}_${slot_name}`, children[slot_name], context);
832834
if (body.length === 0) continue;
@@ -3070,11 +3072,14 @@ export const template_visitors = {
30703072
b.block(create_block(node, 'fallback', node.fragment.nodes, context))
30713073
);
30723074

3073-
const expression = is_default
3074-
? b.call('$.default_slot', b.id('$$props'))
3075-
: b.member(b.member(b.id('$$props'), b.id('$$slots')), name, true, true);
3076-
3077-
const slot = b.call('$.slot', context.state.node, expression, props_expression, fallback);
3075+
const slot = b.call(
3076+
'$.slot',
3077+
context.state.node,
3078+
b.id('$$props'),
3079+
name,
3080+
props_expression,
3081+
fallback
3082+
);
30783083
context.state.init.push(b.stmt(slot));
30793084
},
30803085
SvelteHead(node, context) {

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,8 @@ function serialize_inline_component(node, component_name, context) {
10371037

10381038
/** @type {import('estree').Statement[]} */
10391039
const snippet_declarations = [];
1040+
/** @type {import('estree').Property[]} */
1041+
const serialized_slots = [];
10401042

10411043
// Group children by slot
10421044
for (const child of node.fragment.nodes) {
@@ -1050,6 +1052,8 @@ function serialize_inline_component(node, component_name, context) {
10501052
});
10511053

10521054
push_prop(b.prop('init', child.expression, child.expression));
1055+
// Back/forward compatibility: allows people to pass snippets when component still uses slots
1056+
serialized_slots.push(b.init(child.expression.name, b.true));
10531057

10541058
continue;
10551059
}
@@ -1071,9 +1075,6 @@ function serialize_inline_component(node, component_name, context) {
10711075
}
10721076

10731077
// Serialize each slot
1074-
/** @type {import('estree').Property[]} */
1075-
const serialized_slots = [];
1076-
10771078
for (const slot_name of Object.keys(children)) {
10781079
const body = create_block(node, children[slot_name], context);
10791080
if (body.length === 0) continue;
@@ -1750,15 +1751,15 @@ const template_visitors = {
17501751
const lets = [];
17511752

17521753
/** @type {import('estree').Expression} */
1753-
let expression = b.call('$.default_slot', b.id('$$props'));
1754+
let slot_name = b.literal('default');
17541755

17551756
for (const attribute of node.attributes) {
17561757
if (attribute.type === 'SpreadAttribute') {
17571758
spreads.push(/** @type {import('estree').Expression} */ (context.visit(attribute)));
17581759
} else if (attribute.type === 'Attribute') {
17591760
const value = serialize_attribute_value(attribute.value, context, false, true);
17601761
if (attribute.name === 'name') {
1761-
expression = b.member(b.member_id('$$props.$$slots'), value, true, true);
1762+
slot_name = value;
17621763
} else if (attribute.name !== 'slot') {
17631764
if (attribute.metadata.dynamic) {
17641765
props.push(b.get(attribute.name, [b.return(value)]));
@@ -1782,7 +1783,14 @@ const template_visitors = {
17821783
node.fragment.nodes.length === 0
17831784
? b.literal(null)
17841785
: b.thunk(b.block(create_block(node, node.fragment.nodes, context)));
1785-
const slot = b.call('$.slot', b.id('$$payload'), expression, props_expression, fallback);
1786+
const slot = b.call(
1787+
'$.slot',
1788+
b.id('$$payload'),
1789+
b.id('$$props'),
1790+
slot_name,
1791+
props_expression,
1792+
fallback
1793+
);
17861794

17871795
state.template.push(t_statement(b.stmt(slot)));
17881796
state.template.push(block_close);

packages/svelte/src/internal/client/dom/legacy/misc.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,3 @@ export function update_legacy_props($$new_props) {
6666
}
6767
}
6868
}
69-
70-
/**
71-
* @param {Record<string, any>} $$props
72-
*/
73-
export function default_slot($$props) {
74-
var children = $$props.$$slots?.default;
75-
if (children === true) {
76-
return $$props.children;
77-
} else {
78-
return children;
79-
}
80-
}

packages/svelte/src/internal/client/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ export {
7272
add_legacy_event_listener,
7373
bubble_event,
7474
reactive_import,
75-
update_legacy_props,
76-
default_slot
75+
update_legacy_props
7776
} from './dom/legacy/misc.js';
7877
export {
7978
append,

packages/svelte/src/internal/client/render.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,21 @@ export function set_text(dom, value) {
6363

6464
/**
6565
* @param {Comment} anchor
66-
* @param {void | ((anchor: Comment, slot_props: Record<string, unknown>) => void)} slot_fn
66+
* @param {Record<string, any>} $$props
67+
* @param {string} slot_name
6768
* @param {Record<string, unknown>} slot_props
6869
* @param {null | ((anchor: Comment) => void)} fallback_fn
6970
*/
70-
export function slot(anchor, slot_fn, slot_props, fallback_fn) {
71+
export function slot(anchor, $$props, slot_name, slot_props, fallback_fn) {
72+
var slot_fn = $$props.$$slots?.[slot_name];
73+
if (slot_fn === true) {
74+
if (slot_name === 'default') {
75+
slot_fn = $$props.children;
76+
} else {
77+
slot_fn = $$props[slot_name];
78+
}
79+
}
80+
7181
if (slot_fn === undefined) {
7282
if (fallback_fn !== null) {
7383
fallback_fn(anchor);

packages/svelte/src/internal/server/index.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -499,12 +499,22 @@ export async function value_or_fallback_async(value, fallback) {
499499

500500
/**
501501
* @param {Payload} payload
502-
* @param {void | ((payload: Payload, props: Record<string, unknown>) => void)} slot_fn
502+
* @param {Record<string, any>} $$props
503+
* @param {string} slot_name
503504
* @param {Record<string, unknown>} slot_props
504505
* @param {null | (() => void)} fallback_fn
505506
* @returns {void}
506507
*/
507-
export function slot(payload, slot_fn, slot_props, fallback_fn) {
508+
export function slot(payload, $$props, slot_name, slot_props, fallback_fn) {
509+
var slot_fn = $$props.$$slots?.[slot_name];
510+
if (slot_fn === true) {
511+
if (slot_name === 'default') {
512+
slot_fn = $$props.children;
513+
} else {
514+
slot_fn = $$props[slot_name];
515+
}
516+
}
517+
508518
if (slot_fn === undefined) {
509519
if (fallback_fn !== null) {
510520
fallback_fn();
@@ -631,5 +641,3 @@ export {
631641
} from '../shared/validate.js';
632642

633643
export { escape_html as escape };
634-
635-
export { default_slot } from '../client/dom/legacy/misc.js';
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<p><slot /></p>
2+
<p><slot name="named" /></p>
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>Default</p> <p>Named</p>`
5+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
import Child from './Child.svelte';
3+
</script>
4+
5+
<Child>
6+
Default
7+
{#snippet named()}
8+
Named
9+
{/snippet}
10+
</Child>

0 commit comments

Comments
 (0)