From 64e9f0e5f6f19ef59609dcbb67dbc372031fd154 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 23 Jul 2024 23:36:26 +0100 Subject: [PATCH] fix: improve dynamic event handling (#12570) --- .../3-transform/client/visitors/template.js | 38 +++++++++---------- .../dynamic-element-event-handler/_config.js | 26 +++++++++++++ .../dynamic-element-event-handler/main.svelte | 19 ++++++++++ 3 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/main.svelte 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 a1f231398b..030996bc32 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 @@ -1148,25 +1148,7 @@ function serialize_event_handler(node, metadata, { state, visit }) { ]) ); - if (handler.type === 'Identifier' || handler.type === 'MemberExpression') { - const id = object(handler); - const binding = id === null ? null : state.scope.get(id.name); - if ( - binding !== null && - (binding.kind === 'state' || - binding.kind === 'frozen_state' || - binding.declaration_kind === 'import' || - binding.kind === 'legacy_reactive' || - binding.kind === 'derived' || - binding.kind === 'prop' || - binding.kind === 'bindable_prop' || - binding.kind === 'store_sub') - ) { - handler = dynamic_handler(); - } else { - handler = /** @type {Expression} */ (visit(handler)); - } - } else if ( + if ( metadata?.contains_call_expression && !( (handler.type === 'ArrowFunctionExpression' || handler.type === 'FunctionExpression') && @@ -1193,6 +1175,24 @@ function serialize_event_handler(node, metadata, { state, visit }) { ) ]) ); + } else if (handler.type === 'Identifier' || handler.type === 'MemberExpression') { + const id = object(handler); + const binding = id === null ? null : state.scope.get(id.name); + if ( + binding !== null && + (binding.kind === 'state' || + binding.kind === 'frozen_state' || + binding.declaration_kind === 'import' || + binding.kind === 'legacy_reactive' || + binding.kind === 'derived' || + binding.kind === 'prop' || + binding.kind === 'bindable_prop' || + binding.kind === 'store_sub') + ) { + handler = dynamic_handler(); + } else { + handler = /** @type {Expression} */ (visit(handler)); + } } else if (handler.type === 'ConditionalExpression' || handler.type === 'LogicalExpression') { handler = dynamic_handler(); } else { diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/_config.js b/packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/_config.js new file mode 100644 index 0000000000..e3cc5ecde3 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/_config.js @@ -0,0 +1,26 @@ +import { test } from '../../test'; + +export default test({ + html: '
', + + test({ assert, logs, target }) { + const [b1, b2, b3] = target.querySelectorAll('button'); + + b1?.click(); + b2?.click(); + b3?.click(); + b1?.click(); + b2?.click(); + + assert.deepEqual(logs, [ + 'creating "Hello" handler for Tama', + 'Hello Tama', + 'creating "Hello" handler for Pochi', + 'Hello Pochi', + 'creating "Bye" handler for Tama', + 'Bye Tama', + 'creating "Bye" handler for Pochi', + 'Bye Pochi' + ]); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/main.svelte b/packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/main.svelte new file mode 100644 index 0000000000..430be19126 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-element-event-handler/main.svelte @@ -0,0 +1,19 @@ + + + + + +
+