From b815442ba23666682e636bc13a6f84f789abc9d0 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Jan 2024 13:20:07 +0000 Subject: [PATCH 1/4] fix: improve event handling compatibility with delegation --- .changeset/tame-spies-drum.md | 5 ++++ packages/svelte/src/internal/client/render.js | 7 +++++- .../event-attribute-delegation-2/_config.js | 20 +++++++++++++++ .../event-attribute-delegation-2/log.js | 2 ++ .../event-attribute-delegation-2/main.svelte | 13 ++++++++++ .../event-attribute-delegation/_config.js | 25 +++++++++++++++++++ .../samples/event-attribute-delegation/log.js | 2 ++ .../event-attribute-delegation/main.svelte | 13 ++++++++++ 8 files changed, 86 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/_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 000000000000..f22ed7ab622b --- /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 6783603eaecf..09e091e561cb 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -319,7 +319,12 @@ export function event(event_name, dom, handler, capture, passive) { capture, passive }; - const target_handler = handler; + const target_handler = (/** @type {Event} */ event) => { + handle_event_propagation(dom, event); + if (!event.cancelBubble) { + handler(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 000000000000..262240f5f311 --- /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 000000000000..d3df521f4da7 --- /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 000000000000..4cead08260a4 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/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 000000000000..b1f5931a1e13 --- /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 000000000000..d3df521f4da7 --- /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 000000000000..8d3ac9fcc079 --- /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') }}> + +
+
+
From b5788e51edf2f97797be8ddedac74d13cb58e92d Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Jan 2024 13:29:17 +0000 Subject: [PATCH 2/4] fix --- packages/svelte/src/internal/client/render.js | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 09e091e561cb..c609f8edb984 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -319,12 +319,15 @@ export function event(event_name, dom, handler, capture, passive) { capture, passive }; - const target_handler = (/** @type {Event} */ event) => { + /** + * @this {EventTarget} + */ + function target_handler(/** @type {Event} */ event) { handle_event_propagation(dom, event); if (!event.cancelBubble) { - handler(event); + return handler.call(this, event); } - }; + } dom.addEventListener(event_name, target_handler, options); // @ts-ignore if (dom === document.body || dom === window || dom === document) { @@ -878,8 +881,8 @@ export function bind_resize_observer(dom, type, update) { type === 'contentRect' || type === 'contentBoxSize' ? resize_observer_content_box : type === 'borderBoxSize' - ? resize_observer_border_box - : resize_observer_device_pixel_content_box; + ? resize_observer_border_box + : resize_observer_device_pixel_content_box; const unsub = observer.observe(dom, /** @param {any} entry */ (entry) => update(entry[type])); render_effect(() => unsub); } @@ -1603,8 +1606,8 @@ export function element(anchor_node, tag_fn, render_fn, is_svg = false) { ? current_hydration_fragment !== null ? /** @type {HTMLElement | SVGElement} */ (current_hydration_fragment[0]) : is_svg - ? document.createElementNS('http://www.w3.org/2000/svg', tag) - : document.createElement(tag) + ? document.createElementNS('http://www.w3.org/2000/svg', tag) + : document.createElement(tag) : null; const prev_element = element; if (prev_element !== null) { @@ -2866,7 +2869,7 @@ export function mount(component, options) { PassiveDelegatedEvents.includes(event_name) ? { passive: true - } + } : undefined ); // The document listener ensures we catch events that originate from elements that were @@ -2877,7 +2880,7 @@ export function mount(component, options) { PassiveDelegatedEvents.includes(event_name) ? { passive: true - } + } : undefined ); } From 795b4dab52fff6db63ad66d3682dfd1edc21fc74 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Jan 2024 13:33:34 +0000 Subject: [PATCH 3/4] lint --- packages/svelte/src/internal/client/render.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index c609f8edb984..bb1650748e4f 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -881,8 +881,8 @@ export function bind_resize_observer(dom, type, update) { type === 'contentRect' || type === 'contentBoxSize' ? resize_observer_content_box : type === 'borderBoxSize' - ? resize_observer_border_box - : resize_observer_device_pixel_content_box; + ? resize_observer_border_box + : resize_observer_device_pixel_content_box; const unsub = observer.observe(dom, /** @param {any} entry */ (entry) => update(entry[type])); render_effect(() => unsub); } @@ -1606,8 +1606,8 @@ export function element(anchor_node, tag_fn, render_fn, is_svg = false) { ? current_hydration_fragment !== null ? /** @type {HTMLElement | SVGElement} */ (current_hydration_fragment[0]) : is_svg - ? document.createElementNS('http://www.w3.org/2000/svg', tag) - : document.createElement(tag) + ? document.createElementNS('http://www.w3.org/2000/svg', tag) + : document.createElement(tag) : null; const prev_element = element; if (prev_element !== null) { @@ -2869,7 +2869,7 @@ export function mount(component, options) { PassiveDelegatedEvents.includes(event_name) ? { passive: true - } + } : undefined ); // The document listener ensures we catch events that originate from elements that were @@ -2880,7 +2880,7 @@ export function mount(component, options) { PassiveDelegatedEvents.includes(event_name) ? { passive: true - } + } : undefined ); } From e34d2e9bc198501bf8d163450d20bd48ca98e111 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Jan 2024 13:53:22 +0000 Subject: [PATCH 4/4] add test --- .../event-attribute-delegation-2/main.svelte | 13 ++++-------- .../event-attribute-delegation-3/_config.js | 20 +++++++++++++++++++ .../event-attribute-delegation-3/log.js | 2 ++ .../event-attribute-delegation-3/main.svelte | 13 ++++++++++++ 4 files changed, 39 insertions(+), 9 deletions(-) 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 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 index 4cead08260a4..dc5fdd214ecb 100644 --- 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 @@ -1,13 +1,8 @@ -
log.push('clicked container')} onkeydown={() => {}}> -
{ log.push('clicked div 1') }}> -
{ log.push('clicked div 2') }}> - -
-
+
{ 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 000000000000..262240f5f311 --- /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 000000000000..d3df521f4da7 --- /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 000000000000..4cead08260a4 --- /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') }}> + +
+
+