fix: strip internal properties from rest props during SSR (#13492)

* fix: strip internal properties from rest props during SSR

* address feedback

* update snapshots

* lint
pull/13486/head
Dominic Gannaway 11 months ago committed by GitHub
parent e8508526e7
commit 3ce0384e9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: strip internal properties from rest props during SSR

@ -25,8 +25,14 @@ export function VariableDeclaration(node, context) {
}
if (rune === '$props') {
let has_rest = false;
// remove $bindable() from props declaration
const id = walk(declarator.id, null, {
let id = walk(declarator.id, null, {
RestElement(node, context) {
if (context.path.at(-1) === declarator.id) {
has_rest = true;
}
},
AssignmentPattern(node) {
if (
node.right.type === 'CallExpression' &&
@ -39,6 +45,24 @@ export function VariableDeclaration(node, context) {
}
}
});
if (id.type === 'ObjectPattern' && has_rest) {
// If a rest pattern is used within an object pattern, we need to ensure we don't expose $$slots or $$events
id.properties.splice(
id.properties.length - 1,
0,
// @ts-ignore
b.prop('init', b.id('$$slots'), b.id('$$slots')),
b.prop('init', b.id('$$events'), b.id('$$events'))
);
} else if (id.type === 'Identifier') {
// If $props is referenced as an identifier, we need to ensure we don't expose $$slots or $$events as properties
// on the identifier reference
id = b.object_pattern([
b.prop('init', b.id('$$slots'), b.id('$$slots')),
b.prop('init', b.id('$$events'), b.id('$$events')),
b.rest(b.id(id.name))
]);
}
declarations.push(
b.declarator(/** @type {Pattern} */ (context.visit(id)), b.id('$$props'))
);

@ -0,0 +1,8 @@
<script>
let rest = $props();
</script>
<ul>
{#each Object.getOwnPropertyNames(rest) as n}
<li>{n}</li>
{/each}
</ul>

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
html: '<ul><li>name</li><li>title</li><li>children</li></ul>'
});

@ -0,0 +1,5 @@
<script>
import Component from "./Component.svelte";
</script>
<Component name="n" title="t">Foo</Component>

@ -0,0 +1,12 @@
<script>
let {
children,
...rest
} = $props();
</script>
{@render children?.()}
<ul>
{#each Object.getOwnPropertyNames(rest) as n}
<li>{n}</li>
{/each}
</ul>

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
html: 'Foo\n<ul><li>name</li><li>title</li></ul>'
});

@ -0,0 +1,5 @@
<script>
import Component from "./Component.svelte";
</script>
<Component name="n" title="t">Foo</Component>

@ -3,7 +3,7 @@ import * as $ from "svelte/internal/server";
export default function Props_identifier($$payload, $$props) {
$.push();
let props = $$props;
let { $$slots, $$events, ...props } = $$props;
props.a;
props[a];

Loading…
Cancel
Save