diff --git a/.changeset/ten-eels-move.md b/.changeset/ten-eels-move.md new file mode 100644 index 0000000000..dfada3b8b2 --- /dev/null +++ b/.changeset/ten-eels-move.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: ensure capture events don't call delegated events diff --git a/packages/svelte/src/internal/client/dom/elements/events.js b/packages/svelte/src/internal/client/dom/elements/events.js index bd5a77dffb..330bcc2661 100644 --- a/packages/svelte/src/internal/client/dom/elements/events.js +++ b/packages/svelte/src/internal/client/dom/elements/events.js @@ -17,7 +17,10 @@ export function event(event_name, dom, handler, capture, passive) { * @this {EventTarget} */ function target_handler(/** @type {Event} */ event) { - handle_event_propagation(dom, event); + if (!capture) { + // Only call in the bubble phase, else delegated events would be called before the capturing events + handle_event_propagation(dom, event); + } if (!event.cancelBubble) { return handler.call(this, event); } diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/_config.js new file mode 100644 index 0000000000..69f1788171 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/_config.js @@ -0,0 +1,16 @@ +import { test } from '../../test'; +import { log } from './log.js'; + +export default test({ + before_test() { + log.length = 0; + }, + + async test({ assert, target }) { + const btn = target.querySelector('button'); + + btn?.click(); + await Promise.resolve(); + assert.deepEqual(log, ['div onclickcapture', 'button onclick']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/log.js new file mode 100644 index 0000000000..d3df521f4d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/log.js @@ -0,0 +1,2 @@ +/** @type {any[]} */ +export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/main.svelte new file mode 100644 index 0000000000..b79cc9008f --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/main.svelte @@ -0,0 +1,7 @@ + + +
log.push('div onclickcapture')}> + +