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}