diff --git a/.changeset/thin-dolls-cover.md b/.changeset/thin-dolls-cover.md new file mode 100644 index 0000000000..e9f09342a5 --- /dev/null +++ b/.changeset/thin-dolls-cover.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: cleanup event handlers on media elements diff --git a/packages/svelte/src/internal/client/dom/elements/events.js b/packages/svelte/src/internal/client/dom/elements/events.js index c2b7fc7d83..fa3bf0b021 100644 --- a/packages/svelte/src/internal/client/dom/elements/events.js +++ b/packages/svelte/src/internal/client/dom/elements/events.js @@ -112,8 +112,15 @@ export function event(event_name, dom, handler, capture, passive) { var options = { capture, passive }; var target_handler = create_event(event_name, dom, handler, options); - // @ts-ignore - if (dom === document.body || dom === window || dom === document) { + if ( + dom === document.body || + // @ts-ignore + dom === window || + // @ts-ignore + dom === document || + // Firefox has quirky behavior, it can happen that we still get "canplay" events when the element is already removed + dom instanceof HTMLMediaElement + ) { teardown(() => { dom.removeEventListener(event_name, target_handler, options); }); diff --git a/packages/svelte/tests/runtime-runes/samples/event-media-element-cleanup/_config.js b/packages/svelte/tests/runtime-runes/samples/event-media-element-cleanup/_config.js new file mode 100644 index 0000000000..775afcab89 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-media-element-cleanup/_config.js @@ -0,0 +1,20 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; +import { expect, vi } from 'vitest'; + +const handler = vi.fn(); + +export default test({ + props: { + handler + }, + async test({ target }) { + const button = target.querySelector('button'); + const video = target.querySelector('video'); + + button?.click(); + flushSync(); + video?.dispatchEvent(new Event('someevent')); + expect(handler).not.toHaveBeenCalled(); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-media-element-cleanup/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-media-element-cleanup/main.svelte new file mode 100644 index 0000000000..6a1f9b6b4b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-media-element-cleanup/main.svelte @@ -0,0 +1,9 @@ + + + +{#if show} + +{/if}