Repository: sveltejs/svelte
File: packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js (JavaScript)

Code before:
/**
 * @param {VariableDeclaration} node
 * @param {Context} context
 */
export function VariableDeclaration(node, context) {
	/** @type {VariableDeclarator[]} */
	const declarations = [];

	if (context.state.analysis.runes) {
		for (const declarator of node.declarations) {
			const init = declarator.init;
			const rune = get_rune(init, context.state.scope);
			if (!rune || rune === '$effect.tracking' || rune === '$inspect' || rune === '$effect.root') {
				declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator)));
				continue;
			}

			if (rune === '$props') {
				let has_rest = false;
				// remove $bindable() from props declaration
				const 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' &&
							get_rune(node.right, context.state.scope) === '$bindable'
						) {
							const right = node.right.arguments.length
								? /** @type {Expression} */ (context.visit(node.right.arguments[0]))
								: b.id('undefined');
							return b.assignment_pattern(node.left, right);
						}
					}
				});
				// If a rest pattern is used, we need to ensure we don't expose $$slots or $$events
				if (id.type === 'ObjectPattern' && has_rest) {
					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'))
					);
				}
				declarations.push(
					b.declarator(/** @type {Pattern} */ (context.visit(id)), b.id('$$props'))
				);

Review comment (bug):
We should also cover this case
```svelte
<script>
	let rest = $props();
</script>
{@render rest.children?.()}
<ul>
	{#each Object.getOwnPropertyNames(rest) as n}
			<li>{n}</li>
	{/each}
</ul>
```
that is still [broken in this PR](https://svelte-5-preview-5j4omcg69-svelte.vercel.app/#H4sIAAAAAAAAEz2MwarCMBBFfyXMc9FCafc19ukPqHvroi8dNZJOw2SqSMi_SxQed3Uv554IF-swQHuKQMOE0MLOe6hAXj6X8EAnCBWEeWGTFx0MWy9dT704FMUYRG3UyvPsQ1Gue9LNPxK3jDQif6ja3KwbGem3LsrUk17cxxJ_cDA3dfi7o5H6inJ40pFnjyyv_TBhKPK7VENQlPIhRzvbRUq6cfYrabIkW5vFdVDBNI_2YnGEVnjBdE5v2YEb2OsAAAA=)

Code after:
/**
 * @param {VariableDeclaration} node
 * @param {Context} context
 */
export function VariableDeclaration(node, context) {
	/** @type {VariableDeclarator[]} */
	const declarations = [];

	if (context.state.analysis.runes) {
		for (const declarator of node.declarations) {
			const init = declarator.init;
			const rune = get_rune(init, context.state.scope);
			if (!rune || rune === '$effect.tracking' || rune === '$inspect' || rune === '$effect.root') {
				declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator)));
				continue;
			}

			if (rune === '$props') {
				let has_rest = false;
				// remove $bindable() from props declaration
				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' &&
							get_rune(node.right, context.state.scope) === '$bindable'
						) {
							const right = node.right.arguments.length
								? /** @type {Expression} */ (context.visit(node.right.arguments[0]))
								: b.id('undefined');
							return b.assignment_pattern(node.left, right);
						}
					}
				});
				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([