diff --git a/.changeset/fast-parrots-draw.md b/.changeset/fast-parrots-draw.md
new file mode 100644
index 0000000000..e56a35ff9b
--- /dev/null
+++ b/.changeset/fast-parrots-draw.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: delegate functions with shadowed variables if declared locally
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js
index 773aa59744..b13f3f89b6 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js
@@ -192,8 +192,13 @@ function get_delegated_event(event_name, handler, context) {
return unhoisted;
}
- // If we are referencing a binding that is shadowed in another scope then bail out.
- if (local_binding !== null && binding !== null && local_binding.node !== binding.node) {
+ // If we are referencing a binding that is shadowed in another scope then bail out (unless it's declared within the function).
+ if (
+ local_binding !== null &&
+ binding !== null &&
+ local_binding.node !== binding.node &&
+ scope.declarations.get(reference) !== binding
+ ) {
return unhoisted;
}
diff --git a/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/_expected/client/index.svelte.js
new file mode 100644
index 0000000000..0d95d8d335
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/_expected/client/index.svelte.js
@@ -0,0 +1,28 @@
+import 'svelte/internal/disclose-version';
+import 'svelte/internal/flags/legacy';
+import * as $ from 'svelte/internal/client';
+
+var on_click = (e) => {
+ const index = Number(e.currentTarget.dataset.index);
+
+ console.log(index);
+};
+
+var root_1 = $.from_html(``);
+
+export default function Delegated_locally_declared_shadowed($$anchor) {
+ var fragment = $.comment();
+ var node = $.first_child(fragment);
+
+ $.each(node, 0, () => ({ length: 1 }), $.index, ($$anchor, $$item, index) => {
+ var button = root_1();
+
+ $.set_attribute(button, 'data-index', index);
+ button.__click = [on_click];
+ $.append($$anchor, button);
+ });
+
+ $.append($$anchor, fragment);
+}
+
+$.delegate(['click']);
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/_expected/server/index.svelte.js
new file mode 100644
index 0000000000..e465af6f8b
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/_expected/server/index.svelte.js
@@ -0,0 +1,13 @@
+import * as $ from 'svelte/internal/server';
+
+export default function Delegated_locally_declared_shadowed($$payload) {
+ const each_array = $.ensure_array_like({ length: 1 });
+
+ $$payload.out += ``;
+
+ for (let index = 0, $$length = each_array.length; index < $$length; index++) {
+ $$payload.out += ``;
+ }
+
+ $$payload.out += ``;
+}
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/index.svelte b/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/index.svelte
new file mode 100644
index 0000000000..d870a6b270
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/delegated-locally-declared-shadowed/index.svelte
@@ -0,0 +1,12 @@
+
+
+{#each { length: 1 }, index}
+
+{/each}