Skip to content

Commit 0134777

Browse files
committed
fix: don't spread away $$slots from $props is it's used
1 parent 1c2fc21 commit 0134777

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

.changeset/ten-plants-carry.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: don't spread away `$$slots` from `$props` is it's used

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/** @import { VariableDeclaration, VariableDeclarator, Expression, CallExpression, Pattern, Identifier } from 'estree' */
22
/** @import { Binding } from '#compiler' */
33
/** @import { Context } from '../types.js' */
4+
/** @import { ComponentAnalysis } from '../../../types.js' */
45
/** @import { Scope } from '../../../scope.js' */
56
import { build_fallback, extract_paths } from '../../../../utils/ast.js';
67
import * as b from '#compiler/builders';
@@ -50,23 +51,25 @@ export function VariableDeclaration(node, context) {
5051
}
5152
}
5253
});
54+
const to_remove = [b.prop('init', b.id('$$events'), b.id('$$events'))];
55+
// we don't want to spread away `$$slots` if `$$slots` is used in the component
56+
// otherwise there will be a reference to `$$slots` in the component already
57+
// the typecast is fine since `$props` can only be used in a component
58+
if (!(/** @type {ComponentAnalysis} */ (context.state.analysis).uses_slots)) {
59+
to_remove.unshift(b.prop('init', b.id('$$slots'), b.id('$$slots')));
60+
}
5361
if (id.type === 'ObjectPattern' && has_rest) {
5462
// If a rest pattern is used within an object pattern, we need to ensure we don't expose $$slots or $$events
5563
id.properties.splice(
5664
id.properties.length - 1,
5765
0,
5866
// @ts-ignore
59-
b.prop('init', b.id('$$slots'), b.id('$$slots')),
60-
b.prop('init', b.id('$$events'), b.id('$$events'))
67+
...to_remove
6168
);
6269
} else if (id.type === 'Identifier') {
6370
// If $props is referenced as an identifier, we need to ensure we don't expose $$slots or $$events as properties
6471
// on the identifier reference
65-
id = b.object_pattern([
66-
b.prop('init', b.id('$$slots'), b.id('$$slots')),
67-
b.prop('init', b.id('$$events'), b.id('$$events')),
68-
b.rest(b.id(id.name))
69-
]);
72+
id = b.object_pattern([...to_remove, b.rest(b.id(id.name))]);
7073
}
7174
declarations.push(
7275
b.declarator(/** @type {Pattern} */ (context.visit(id)), b.id('$$props'))

packages/svelte/tests/server-side-rendering/samples/props-id-and-$$slots/_expected.html

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
const props = $props();
3+
</script>
4+
5+
{#if $$slots.foo}{/if}

0 commit comments

Comments
 (0)