fix: events don't go through propagation

pull/18058/head
paoloricciuti 5 months ago
parent 700454d77c
commit a0650d0611

@ -63,10 +63,21 @@ export function replay_events(dom) {
* @param {AddEventListenerOptions} [options] * @param {AddEventListenerOptions} [options]
*/ */
export function create_event(event_name, dom, handler, options = {}) { export function create_event(event_name, dom, handler, options = {}) {
// Capture whether a custom renderer is active at creation time (during mount),
// since `renderer` will be null when the event actually fires
var is_custom_renderer = renderer != null;
/** /**
* @this {EventTarget} * @this {EventTarget}
*/ */
function target_handler(/** @type {Event} */ event) { function target_handler(/** @type {Event} */ event) {
if (is_custom_renderer) {
// Custom renderers don't use DOM event propagation/delegation,
// so just call the handler directly
return without_reactive_context(() => {
return handler?.call(this, event);
});
}
if (!options.capture) { if (!options.capture) {
// Only call in the bubble phase, else delegated events would be called before the capturing events // Only call in the bubble phase, else delegated events would be called before the capturing events
handle_event_propagation.call(dom, event); handle_event_propagation.call(dom, event);

@ -0,0 +1,24 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
test({ assert, target, serialize, logs }) {
const button = target.children.find(
(/** @type {any} */ n) => n.type === 'element' && n.name === 'button'
);
assert.ok(button);
const listeners = button.listeners?.click;
assert.ok(listeners, 'button should have click listeners');
// Call the handler with a plain object that is NOT a DOM Event.
// If handle_event_propagation is called, it will fail because
// it tries to access DOM-specific properties like composedPath, ownerDocument, etc.
for (const { handler } of listeners) {
handler.call(button, { type: 'click' });
}
flushSync();
assert.deepEqual(logs, [{ type: 'click' }]);
}
});

@ -0,0 +1,7 @@
<script>
function increment(e) {
console.log(e);
}
</script>
<button onclick={increment}>log</button>
Loading…
Cancel
Save