Skip to content

Commit 0ac341d

Browse files
authored
expose which slots are present in $$slots (#4602)
1 parent dccdb9f commit 0ac341d

File tree

22 files changed

+123
-34
lines changed

22 files changed

+123
-34
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
* Expose object of which slots have received content in `$$slots` ([#2106](https://github.com/sveltejs/svelte/issues/2106))
56
* Add types to `createEventDispatcher` ([#5211](https://github.com/sveltejs/svelte/issues/5211))
67
* In SSR mode, do not automatically declare variables for reactive assignments to member expressions ([#5247](https://github.com/sveltejs/svelte/issues/5247))
78
* Include selector in message of `unused-css-selector` warning ([#5252](https://github.com/sveltejs/svelte/issues/5252))

src/compiler/compile/render_dom/Renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export default class Renderer {
6060

6161
if (component.slots.size > 0) {
6262
this.add_to_context('$$scope');
63-
this.add_to_context('$$slots');
63+
this.add_to_context('#slots');
6464
}
6565

6666
if (this.binding_groups.size > 0) {

src/compiler/compile/render_dom/index.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ export default function dom(
7070
);
7171
}
7272

73+
const uses_slots = component.var_lookup.has('$$slots');
74+
let compute_slots;
75+
if (uses_slots) {
76+
compute_slots = b`
77+
const $$slots = @compute_slots(#slots);
78+
`;
79+
}
80+
81+
7382
const uses_props = component.var_lookup.has('$$props');
7483
const uses_rest = component.var_lookup.has('$$restProps');
7584
const $$props = uses_props || uses_rest ? `$$new_props` : `$$props`;
@@ -409,13 +418,14 @@ export default function dom(
409418
410419
${resubscribable_reactive_store_unsubscribers}
411420
421+
${component.slots.size || component.compile_options.dev || uses_slots ? b`let { $$slots: #slots = {}, $$scope } = $$props;` : null}
422+
${component.compile_options.dev && b`@validate_slots('${component.tag}', #slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
423+
${compute_slots}
424+
412425
${instance_javascript}
413426
414427
${unknown_props_check}
415428
416-
${component.slots.size || component.compile_options.dev ? b`let { $$slots = {}, $$scope } = $$props;` : null}
417-
${component.compile_options.dev && b`@validate_slots('${component.tag}', $$slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`}
418-
419429
${renderer.binding_groups.size > 0 && b`const $$binding_groups = [${[...renderer.binding_groups.keys()].map(_ => x`[]`)}];`}
420430
421431
${component.partly_hoisted}

src/compiler/compile/render_dom/wrappers/Slot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export default class SlotWrapper extends Wrapper {
125125
const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
126126

127127
block.chunks.init.push(b`
128-
const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name};
128+
const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name};
129129
const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
130130
${has_fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
131131
`);

src/compiler/compile/render_ssr/handlers/Slot.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ export default function(node: Slot, renderer: Renderer, options: RenderOptions)
1111
const result = renderer.pop();
1212

1313
renderer.add_expression(x`
14-
$$slots.${node.slot_name}
15-
? $$slots.${node.slot_name}(${slot_data})
14+
#slots.${node.slot_name}
15+
? #slots.${node.slot_name}(${slot_data})
1616
: ${result}
1717
`);
1818
}

src/compiler/compile/render_ssr/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export default function ssr(
3434
const props = component.vars.filter(variable => !variable.module && variable.export_name);
3535
const rest = uses_rest ? b`let $$restProps = @compute_rest_props($$props, [${props.map(prop => `"${prop.export_name}"`).join(',')}]);` : null;
3636

37+
const uses_slots = component.var_lookup.has('$$slots');
38+
const slots = uses_slots ? b`let $$slots = @compute_slots(#slots);` : null;
39+
3740
const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$');
3841
const reactive_store_values = reactive_stores
3942
.map(({ name }) => {
@@ -118,6 +121,7 @@ export default function ssr(
118121

119122
const blocks = [
120123
rest,
124+
slots,
121125
...reactive_stores.map(({ name }) => {
122126
const store_name = name.slice(1);
123127
const store = component.var_lookup.get(store_name);
@@ -144,7 +148,7 @@ export default function ssr(
144148
145149
${component.fully_hoisted}
146150
147-
const ${name} = @create_ssr_component(($$result, $$props, $$bindings, $$slots) => {
151+
const ${name} = @create_ssr_component(($$result, $$props, $$bindings, #slots) => {
148152
${blocks}
149153
});
150154
`;

src/compiler/compile/utils/reserved_keywords.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const reserved_keywords = new Set(["$$props", "$$restProps"]);
1+
export const reserved_keywords = new Set(["$$props", "$$restProps", "$$slots"]);
22

33
export function is_reserved_keyword(name) {
44
return reserved_keywords.has(name);

src/runtime/internal/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ export function compute_rest_props(props, keys) {
128128
return rest;
129129
}
130130

131+
export function compute_slots(slots) {
132+
const result = {};
133+
for (const key in slots) {
134+
result[key] = true;
135+
}
136+
return result;
137+
}
138+
131139
export function once(fn) {
132140
let ran = false;
133141
return function(this: any, ...args) {

test/js/samples/capture-inject-state/expected.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ function instance($$self, $$props, $$invalidate) {
103103
$$subscribe_prop = () => ($$unsubscribe_prop(), $$unsubscribe_prop = subscribe(prop, $$value => $$invalidate(2, $prop = $$value)), prop);
104104

105105
$$self.$$.on_destroy.push(() => $$unsubscribe_prop());
106+
let { $$slots: slots = {}, $$scope } = $$props;
107+
validate_slots("Component", slots, []);
106108
let { prop } = $$props;
107109
validate_store(prop, "prop");
108110
$$subscribe_prop();
@@ -115,9 +117,6 @@ function instance($$self, $$props, $$invalidate) {
115117
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
116118
});
117119

118-
let { $$slots = {}, $$scope } = $$props;
119-
validate_slots("Component", $$slots, []);
120-
121120
$$self.$$set = $$props => {
122121
if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop));
123122
if ("alias" in $$props) $$invalidate(1, realName = $$props.alias);

test/js/samples/debug-empty/expected.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,15 @@ function create_fragment(ctx) {
6969
}
7070

7171
function instance($$self, $$props, $$invalidate) {
72+
let { $$slots: slots = {}, $$scope } = $$props;
73+
validate_slots("Component", slots, []);
7274
let { name } = $$props;
7375
const writable_props = ["name"];
7476

7577
Object.keys($$props).forEach(key => {
7678
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`);
7779
});
7880

79-
let { $$slots = {}, $$scope } = $$props;
80-
validate_slots("Component", $$slots, []);
81-
8281
$$self.$$set = $$props => {
8382
if ("name" in $$props) $$invalidate(0, name = $$props.name);
8483
};

0 commit comments

Comments
 (0)