From 0eca0ace9457d226409e582f9e275cb8a4ddb0a1 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Jan 2024 13:59:55 +0000 Subject: [PATCH] fix: improve event handling compatibility with delegation (#10168) * fix: improve event handling compatibility with delegation * fix * lint * add test --- .changeset/tame-spies-drum.md | 5 ++++ packages/svelte/src/internal/client/render.js | 10 +++++++- .../event-attribute-delegation-2/_config.js | 20 +++++++++++++++ .../event-attribute-delegation-2/log.js | 2 ++ .../event-attribute-delegation-2/main.svelte | 8 ++++++ .../event-attribute-delegation-3/_config.js | 20 +++++++++++++++ .../event-attribute-delegation-3/log.js | 2 ++ .../event-attribute-delegation-3/main.svelte | 13 ++++++++++ .../event-attribute-delegation/_config.js | 25 +++++++++++++++++++ .../samples/event-attribute-delegation/log.js | 2 ++ .../event-attribute-delegation/main.svelte | 13 ++++++++++ 11 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 .changeset/tame-spies-drum.md create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte diff --git a/.changeset/tame-spies-drum.md b/.changeset/tame-spies-drum.md new file mode 100644 index 0000000000..f22ed7ab62 --- /dev/null +++ b/.changeset/tame-spies-drum.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve event handling compatibility with delegation diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 6783603eae..bb1650748e 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -319,7 +319,15 @@ export function event(event_name, dom, handler, capture, passive) { capture, passive }; - const target_handler = handler; + /** + * @this {EventTarget} + */ + function target_handler(/** @type {Event} */ event) { + handle_event_propagation(dom, event); + if (!event.cancelBubble) { + return handler.call(this, event); + } + } dom.addEventListener(event_name, target_handler, options); // @ts-ignore if (dom === document.body || dom === window || dom === document) { diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js new file mode 100644 index 0000000000..262240f5f3 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js @@ -0,0 +1,20 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; +import { log } from './log.js'; + +export default test({ + before_test() { + log.length = 0; + }, + + async test({ assert, target }) { + const [b1] = target.querySelectorAll('button'); + + flushSync(() => { + b1?.click(); + }); + + await Promise.resolve(); + assert.deepEqual(log, ['clicked button']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js new file mode 100644 index 0000000000..d3df521f4d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js @@ -0,0 +1,2 @@ +/** @type {any[]} */ +export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte new file mode 100644 index 0000000000..dc5fdd214e --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte @@ -0,0 +1,8 @@ + +
{ log.push('clicked div') }}> + +
diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js new file mode 100644 index 0000000000..262240f5f3 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js @@ -0,0 +1,20 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; +import { log } from './log.js'; + +export default test({ + before_test() { + log.length = 0; + }, + + async test({ assert, target }) { + const [b1] = target.querySelectorAll('button'); + + flushSync(() => { + b1?.click(); + }); + + await Promise.resolve(); + assert.deepEqual(log, ['clicked button']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js new file mode 100644 index 0000000000..d3df521f4d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js @@ -0,0 +1,2 @@ +/** @type {any[]} */ +export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte new file mode 100644 index 0000000000..4cead08260 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte @@ -0,0 +1,13 @@ + +
log.push('clicked container')} onkeydown={() => {}}> +
{ log.push('clicked div 1') }}> +
{ log.push('clicked div 2') }}> + +
+
+
diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js new file mode 100644 index 0000000000..b1f5931a1e --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js @@ -0,0 +1,25 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; +import { log } from './log.js'; + +export default test({ + before_test() { + log.length = 0; + }, + + async test({ assert, target }) { + const [b1] = target.querySelectorAll('button'); + + flushSync(() => { + b1?.click(); + }); + + await Promise.resolve(); + assert.deepEqual(log, [ + 'clicked button', + 'clicked div 2', + 'clicked div 1', + 'clicked container' + ]); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js new file mode 100644 index 0000000000..d3df521f4d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js @@ -0,0 +1,2 @@ +/** @type {any[]} */ +export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte new file mode 100644 index 0000000000..8d3ac9fcc0 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte @@ -0,0 +1,13 @@ + +
log.push('clicked container')} onkeydown={() => {}}> +
{ log.push('clicked div 1') }}> +
{ log.push('clicked div 2') }}> + +
+
+