From b49cd79bc4c5064a0ddd34832670029ceebb6997 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 23 Jul 2024 13:08:57 +0100 Subject: [PATCH] fix: ensure dynamic event handlers are wrapped in a derived --- .changeset/bright-colts-play.md | 5 +++++ .../3-transform/client/visitors/template.js | 13 ++++++++++--- .../dynamic-element-event-handler3/_config.js | 15 +++++++++++++++ .../dynamic-element-event-handler3/main.svelte | 9 +++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 .changeset/bright-colts-play.md create mode 100644 packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/_config.js create mode 100644 packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/main.svelte diff --git a/.changeset/bright-colts-play.md b/.changeset/bright-colts-play.md new file mode 100644 index 0000000000..758264da10 --- /dev/null +++ b/.changeset/bright-colts-play.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure dynamic event handlers are wrapped in a derived 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 af10f0a4cd..9099ad2aed 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 @@ -1132,20 +1132,27 @@ function serialize_event_handler(node, { state, visit }) { handler = node.expression; // Event handlers can be dynamic (source/store/prop/conditional etc) - const dynamic_handler = () => - b.function( + const dynamic_handler = () => { + const id = b.id(state.scope.generate('event_handler')); + + state.init.push( + b.var(id, b.call('$.derived', b.thunk(/** @type {Expression} */ (visit(handler))))) + ); + + return b.function( null, [b.rest(b.id('$$args'))], b.block([ b.return( b.call( - b.member(/** @type {Expression} */ (visit(handler)), b.id('apply'), false, true), + b.member(b.call('$.get', id), b.id('apply'), false, true), b.this, b.id('$$args') ) ) ]) ); + }; if (handler.type === 'Identifier' || handler.type === 'MemberExpression') { const id = object(handler); diff --git a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/_config.js b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/_config.js new file mode 100644 index 0000000000..01c02087f7 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/_config.js @@ -0,0 +1,15 @@ +import { test } from '../../test'; + +export default test({ + html: '', + + test({ assert, logs, target }) { + const button = target.querySelector('button'); + + button?.click(); + button?.click(); + button?.click(); + + assert.deepEqual(logs, ['create', 'trigger', 'trigger', 'trigger']); + } +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/main.svelte b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/main.svelte new file mode 100644 index 0000000000..38d0885039 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-event-handler3/main.svelte @@ -0,0 +1,9 @@ + + +