Repository: sveltejs/svelte (JavaScript)

Issue:
Svelte 5: Can't set default snippet props
### Describe the bug

A method that was working previously to ensure a snippet prop function will always be defined was by setting the snippet prop with a default snippet defined inside the current component.

i.e.
```svelte
<script>
	let {children = fallback} = $props();
</script>

{#snippet fallback()}
	Fallback
{/snippet}

<button>
	{@render children()}
</button>
```

This seems to have stopped working though, potentially with the changes in #9759 

Can still conditionally check the children prop is defined as a workaround for setting a fallback, but I do personally prefer being able to default it, given fallback and children should exist in the same scope anyway.

### Reproduction

[REPL](https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE42P3WoCMRBGX2WIggqLud-u0vaiL1F7sWZnMZhNhmRWKCHv3uyPFhHEy28438yZKFptMIjyOwpbdyhK8UEkCsG_NIRwQcOYc3C9V8OkCspr4v3BHlh35DzDZ8_sLLTedbDayilup-rqLYMWwCBDVCdtGo-2AGeV0eqcYAdL8o7CepPBSv4vt9W8Nt5Yuc8inWt0q7ERJfseU3HznvBX1e98skVbG3OsnxvFRbCaKDev9HqThmVfc8yInJE0vnAcncaD8T0fatDD9ejYreSMPH72k_4Al-WUrZ0BAAA=)

### Logs

```shell
Error: `Cannot access 'fallback' before initialization`
```


### System Info

```shell
Svelte REPL
```


### Severity

annoyance


Discussion:
Possible solution: `unshift` the snippet instead of `push`ing it to the init array, that way it comes first
I would personally do:

```html
<script>
	let { children } = $props();
</script>

<button>
	{#if children}
		{@render children()}
	{:else}
		Fallback
	{/if}
</button>
```

Would this not work for you?
> I would personally do:
> 
> ```
> <script>
> 	let { children } = $props();
> </script>
> 
> <button>
> 	{#if children}
> 		{@render children()}
> 	{:else}
> 		Fallback
> 	{/if}
> </button>
> ```
> 
> Would this not work for you?

Works fine, I already mentioned that as an alternative in the description. Just reporting a regression of functionality that worked previously. 



Patch:
diff --git a/.changeset/ten-peaches-sleep.md b/.changeset/ten-peaches-sleep.md
new file mode 100644
index 000000000000..fa130171122e
--- /dev/null
+++ b/.changeset/ten-peaches-sleep.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: better support for top-level snippet declarations
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js
index d62f1fcb490a..7c06cac973fe 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js
@@ -2477,7 +2477,14 @@ export const template_visitors = {
 			body = /** @type {import('estree').BlockStatement} */ (context.visit(node.body));
 		}
 
-		context.state.init.push(b.const(node.expression, b.arrow(args, body)));
+		const path = context.path;
+		// If we're top-level, then we can create a function for the snippet so that it can be referenced
+		// in the props declaration (default value pattern).
+		if (path.length === 1 && path[0].type === 'Fragment') {
+			context.state.init.push(b.function_declaration(node.expression, args, body));
+		} else {
+			context.state.init.push(b.const(node.expression, b.arrow(args, body)));
+		}
 		if (context.state.options.dev) {
 			context.state.init.push(b.stmt(b.call('$.add_snippet_symbol', node.expression)));
 		}


Test patch:
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-top-level/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-top-level/_config.js
new file mode 100644
index 000000000000..129a5734028c
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-top-level/_config.js
@@ -0,0 +1,8 @@
+import { test } from '../../test';
+
+export default test({
+	compileOptions: {
+		dev: true // Render in dev mode to check that the validation error is not thrown
+	},
+	html: `<p>hello world</p>`
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-top-level/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-top-level/main.svelte
new file mode 100644
index 000000000000..b5da34accba2
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-top-level/main.svelte
@@ -0,0 +1,7 @@
+<script>
+	const {children = snippet} = $props();
+</script>
+{@render children()}
+{#snippet snippet()}
+	<p>hello world</p>
+{/snippet}