Skip to content

Commit 0eca0ac

Browse files
authored
fix: improve event handling compatibility with delegation (#10168)
* fix: improve event handling compatibility with delegation * fix * lint * add test
1 parent a26012f commit 0eca0ac

File tree

11 files changed

+119
-1
lines changed

11 files changed

+119
-1
lines changed

.changeset/tame-spies-drum.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: improve event handling compatibility with delegation

packages/svelte/src/internal/client/render.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,15 @@ export function event(event_name, dom, handler, capture, passive) {
319319
capture,
320320
passive
321321
};
322-
const target_handler = handler;
322+
/**
323+
* @this {EventTarget}
324+
*/
325+
function target_handler(/** @type {Event} */ event) {
326+
handle_event_propagation(dom, event);
327+
if (!event.cancelBubble) {
328+
return handler.call(this, event);
329+
}
330+
}
323331
dom.addEventListener(event_name, target_handler, options);
324332
// @ts-ignore
325333
if (dom === document.body || dom === window || dom === document) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
import { log } from './log.js';
4+
5+
export default test({
6+
before_test() {
7+
log.length = 0;
8+
},
9+
10+
async test({ assert, target }) {
11+
const [b1] = target.querySelectorAll('button');
12+
13+
flushSync(() => {
14+
b1?.click();
15+
});
16+
17+
await Promise.resolve();
18+
assert.deepEqual(log, ['clicked button']);
19+
}
20+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/** @type {any[]} */
2+
export const log = [];
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
import { log } from './log.js';
3+
</script>
4+
<div on:click={(e) => { log.push('clicked div') }}>
5+
<button onclick={(e) => { log.push('clicked button'); e.stopPropagation() }}>
6+
Button
7+
</button>
8+
</div>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
import { log } from './log.js';
4+
5+
export default test({
6+
before_test() {
7+
log.length = 0;
8+
},
9+
10+
async test({ assert, target }) {
11+
const [b1] = target.querySelectorAll('button');
12+
13+
flushSync(() => {
14+
b1?.click();
15+
});
16+
17+
await Promise.resolve();
18+
assert.deepEqual(log, ['clicked button']);
19+
}
20+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/** @type {any[]} */
2+
export const log = [];
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import { log } from './log.js';
3+
const action = () => {}
4+
</script>
5+
<div use:action onclick={() => log.push('clicked container')} onkeydown={() => {}}>
6+
<div use:action onclick={(e) => { log.push('clicked div 1') }}>
7+
<div onclick={(e) => { log.push('clicked div 2') }}>
8+
<button onclick={(e) => { log.push('clicked button'); e.stopPropagation() }}>
9+
Button
10+
</button>
11+
</div>
12+
</div>
13+
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
import { log } from './log.js';
4+
5+
export default test({
6+
before_test() {
7+
log.length = 0;
8+
},
9+
10+
async test({ assert, target }) {
11+
const [b1] = target.querySelectorAll('button');
12+
13+
flushSync(() => {
14+
b1?.click();
15+
});
16+
17+
await Promise.resolve();
18+
assert.deepEqual(log, [
19+
'clicked button',
20+
'clicked div 2',
21+
'clicked div 1',
22+
'clicked container'
23+
]);
24+
}
25+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/** @type {any[]} */
2+
export const log = [];
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import { log } from './log.js';
3+
const action = () => {}
4+
</script>
5+
<div use:action onclick={() => log.push('clicked container')} onkeydown={() => {}}>
6+
<div use:action onclick={(e) => { log.push('clicked div 1') }}>
7+
<div onclick={(e) => { log.push('clicked div 2') }}>
8+
<button onclick={(e) => { log.push('clicked button') }}>
9+
Button
10+
</button>
11+
</div>
12+
</div>
13+
</div>

0 commit comments

Comments
 (0)