From bb69f9c44cdd065ce69e5da7ab912e6c40fac77c Mon Sep 17 00:00:00 2001 From: wheelman Date: Fri, 22 May 2026 14:40:38 +0530 Subject: [PATCH] fix: declare `let:` directives before `{@const}` on slotted elements (#18271) Fixes #18119 (missed a spot in #16985) --- .changeset/quiet-rivers-melt.md | 5 +++++ .../3-transform/client/visitors/RegularElement.js | 4 ++-- .../Nested.svelte | 7 +++++++ .../_config.js | 15 +++++++++++++++ .../main.svelte | 10 ++++++++++ 5 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 .changeset/quiet-rivers-melt.md create mode 100644 packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/Nested.svelte create mode 100644 packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/_config.js create mode 100644 packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/main.svelte diff --git a/.changeset/quiet-rivers-melt.md b/.changeset/quiet-rivers-melt.md new file mode 100644 index 0000000000..7ce1b9b2d3 --- /dev/null +++ b/.changeset/quiet-rivers-melt.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: declare `let:` directives before `{@const}` declarations on slotted elements diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js index 0579d80b74..1e6230a1f6 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js @@ -201,8 +201,8 @@ export function RegularElement(node, context) { } } - // Let bindings first, they can be used on attributes - context.state.init.push(...lets); + // Let bindings first, they can be used on attributes and `{@const}` declarations + context.state.let_directives.push(...lets); const node_id = context.state.node; diff --git a/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/Nested.svelte b/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/Nested.svelte new file mode 100644 index 0000000000..417e539554 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/Nested.svelte @@ -0,0 +1,7 @@ + + +{#each things as thing} + +{/each} diff --git a/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/_config.js b/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/_config.js new file mode 100644 index 0000000000..bbbcd9ad12 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/_config.js @@ -0,0 +1,15 @@ +import { test } from '../../test'; + +// `let:` directives on a slotted element must be declared before sibling `{@const}` +// declarations that capture them. In dev mode the `{@const}` derived is read eagerly, +// so a wrong declaration order throws "Cannot access '...' before initialization". +export default test({ + compileOptions: { + dev: true + }, + + html: ` +
1
+
2
+ ` +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/main.svelte b/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/main.svelte new file mode 100644 index 0000000000..e2530ef015 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/let-directive-and-const-tag-slotted/main.svelte @@ -0,0 +1,10 @@ + + + +
+ {@const props = { thing }} + {props.thing} +
+