Skip to content

Commit 944ef1d

Browse files
fix: don't spread away $$slots from $props is it's used (#15849)
* fix: don't spread away `$$slots` from `$props` is it's used * beef up test * fix * Update .changeset/ten-plants-carry.md --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>
1 parent 2bc2ae0 commit 944ef1d

File tree

5 files changed

+38
-2
lines changed

5 files changed

+38
-2
lines changed

.changeset/ten-plants-carry.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: don't redeclare `$$slots`

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

+9-2
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,20 +51,26 @@ export function VariableDeclaration(node, context) {
5051
}
5152
}
5253
});
54+
55+
// if `$$slots` is declared separately, deconflict
56+
const slots_name = /** @type {ComponentAnalysis} */ (context.state.analysis).uses_slots
57+
? b.id('$$slots_')
58+
: b.id('$$slots');
59+
5360
if (id.type === 'ObjectPattern' && has_rest) {
5461
// If a rest pattern is used within an object pattern, we need to ensure we don't expose $$slots or $$events
5562
id.properties.splice(
5663
id.properties.length - 1,
5764
0,
5865
// @ts-ignore
59-
b.prop('init', b.id('$$slots'), b.id('$$slots')),
66+
b.prop('init', b.id('$$slots'), slots_name),
6067
b.prop('init', b.id('$$events'), b.id('$$events'))
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
6572
id = b.object_pattern([
66-
b.prop('init', b.id('$$slots'), b.id('$$slots')),
73+
b.prop('init', b.id('$$slots'), slots_name),
6774
b.prop('init', b.id('$$events'), b.id('$$events')),
6875
b.rest(b.id(id.name))
6976
]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script>
2+
const props = $props();
3+
</script>
4+
5+
<p>{Object.keys(props)}</p>
6+
7+
{#if $$slots.foo}
8+
<p>foo exists</p>
9+
{/if}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: `
5+
<p>a</p>
6+
<p>foo exists</p>
7+
`
8+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
import Child from './Child.svelte';
3+
</script>
4+
5+
<Child a="b">
6+
<div slot="foo">foo</div>
7+
</Child>

0 commit comments

Comments
 (0)