diff --git a/.changeset/brown-moons-sleep.md b/.changeset/brown-moons-sleep.md new file mode 100644 index 000000000000..3074d919a021 --- /dev/null +++ b/.changeset/brown-moons-sleep.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: dynamic event delegation for stateful call expressions 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 645895144f38..9c366c74cf2e 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 @@ -1143,8 +1143,19 @@ function serialize_event_handler(node, { state, visit }) { ]) ); - if (handler.type === 'Identifier' || handler.type === 'MemberExpression') { - const id = object(handler); + if ( + handler.type === 'Identifier' || + handler.type === 'MemberExpression' || + (handler.type === 'CallExpression' && + (handler.callee.type === 'Identifier' || handler.callee.type === 'MemberExpression')) + ) { + const id = object( + handler.type === 'CallExpression' + ? /** @type {import("estree").Identifier | import("estree").MemberExpression} */ ( + handler.callee + ) + : handler + ); const binding = id === null ? null : state.scope.get(id.name); if ( binding !== null && diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-hof-delegated-event/_config.js b/packages/svelte/tests/runtime-runes/samples/dynamic-hof-delegated-event/_config.js new file mode 100644 index 000000000000..cb37111379a9 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-hof-delegated-event/_config.js @@ -0,0 +1,24 @@ +import { flushSync } from 'svelte'; +import { test, ok } from '../../test'; + +export default test({ + mode: ['client'], + async test({ assert, target, logs }) { + const [btn1, btn2, btn3] = target.querySelectorAll('button'); + + flushSync(() => { + btn1.click(); + btn2.click(); + }); + + assert.deepEqual(logs, ['AA', 'AB']); + + flushSync(() => { + btn3.click(); + btn1.click(); + btn2.click(); + }); + + assert.deepEqual(logs, ['AA', 'AB', 'BA', 'BB']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-hof-delegated-event/main.svelte b/packages/svelte/tests/runtime-runes/samples/dynamic-hof-delegated-event/main.svelte new file mode 100644 index 000000000000..bff372d3b1b3 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-hof-delegated-event/main.svelte @@ -0,0 +1,17 @@ + + + + + +
+