mirror of https://github.com/sveltejs/svelte
- don't delegate events on custom elements - still invoke listener for cancelled event on the element where it was cancelled: when you do `stopPropagation`, `event.cancelBubble` becomes `true`. We can't use this as an indicator to not invoke a listener directly, because the listner could be on the element where propagation was cancelled, i.e. it should still run for that listener. Instead, adjust the event propagation algorithm to detect when a delegated event listener caused the event to be cancelled fixes #14704event-delegation-fixes
parent
c4e9faad52
commit
c05abb5e54
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: don't delegate events on custom elements
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: still invoke listener for cancelled event on the element where it was cancelled
|
@ -0,0 +1,18 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
async test({ assert, target, logs }) {
|
||||
const [btn1, btn2] = [...target.querySelectorAll('custom-element')].map((c) =>
|
||||
c.shadowRoot?.querySelector('button')
|
||||
);
|
||||
|
||||
btn1?.click();
|
||||
await Promise.resolve();
|
||||
assert.deepEqual(logs, ['reached shadow root1']);
|
||||
|
||||
btn2?.click();
|
||||
await Promise.resolve();
|
||||
assert.deepEqual(logs, ['reached shadow root1', 'reached shadow root2']);
|
||||
}
|
||||
});
|
@ -0,0 +1,19 @@
|
||||
<script>
|
||||
class CustomElement extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.shadowRoot.innerHTML = '<button>click me</button>';
|
||||
// Looks weird, but some custom element implementations actually do this
|
||||
// to prevent unwanted side upwards event propagation
|
||||
this.addEventListener('click', (e) => e.stopPropagation());
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('custom-element', CustomElement);
|
||||
</script>
|
||||
|
||||
<div onclick={() => console.log('bubbled beyond shadow root')}>
|
||||
<custom-element onclick={() => console.log('reached shadow root1')}></custom-element>
|
||||
<custom-element {...{onclick:() => console.log('reached shadow root2')}}></custom-element>
|
||||
</div>
|
Loading…
Reference in new issue