From d14620fb8a895b5b9f1cb036778539986de860c5 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 4 Oct 2024 12:33:35 -0400 Subject: [PATCH 1/2] fix: add media listeners immediately when using `bind:paused` --- .changeset/fair-items-bathe.md | 5 ++ .../client/dom/elements/bindings/media.js | 50 ++++--------------- 2 files changed, 15 insertions(+), 40 deletions(-) create mode 100644 .changeset/fair-items-bathe.md diff --git a/.changeset/fair-items-bathe.md b/.changeset/fair-items-bathe.md new file mode 100644 index 000000000000..3abaf8e7bdbf --- /dev/null +++ b/.changeset/fair-items-bathe.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: add media listeners immediately when using `bind:paused` diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/media.js b/packages/svelte/src/internal/client/dom/elements/bindings/media.js index ad955c89dccd..d1ddf677ee4e 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/media.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/media.js @@ -138,56 +138,26 @@ export function bind_playback_rate(media, get, set = get) { * @param {(paused: boolean) => void} set */ export function bind_paused(media, get, set = get) { - var mounted = hydrating; var paused = get(); - var callback = () => { + var update = () => { if (paused !== media.paused) { - paused = media.paused; set((paused = media.paused)); } }; - if (paused == null) { - callback(); - } - - // Defer listening if not mounted yet so that the first canplay event doesn't cause a potentially wrong update - if (mounted) { - // If someone switches the src while media is playing, the player will pause. - // Listen to the canplay event to get notified of this situation. - listen(media, ['play', 'pause', 'canplay'], callback, false); - } + // If someone switches the src while media is playing, the player will pause. + // Listen to the canplay event to get notified of this situation. + listen(media, ['play', 'pause', 'canplay'], update, paused == null); render_effect(() => { - paused = !!get(); - - if (paused !== media.paused) { - var toggle = () => { - mounted = true; - if (paused) { - media.pause(); - } else { - media.play().catch(() => { - set((paused = true)); - }); - } - }; - - if (mounted) { - toggle(); + if ((paused = !!get()) !== media.paused) { + if (paused) { + media.pause(); } else { - // If this is the first invocation in dom mode, the media element isn't mounted yet, - // and therefore its resource isn't loaded yet. We need to wait for the canplay event - // in this case or else we'll get a "The play() request was interrupted by a new load request" error. - media.addEventListener( - 'canplay', - () => { - listen(media, ['play', 'pause', 'canplay'], callback, false); - toggle(); - }, - { once: true } - ); + media.play().catch(() => { + set((paused = true)); + }); } } }); From a0623d4db1ebfd7e0156f54bbf3a9f4cf40442f4 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 7 Oct 2024 14:39:59 +0200 Subject: [PATCH 2/2] make it a render effect --- .../svelte/src/internal/client/dom/elements/bindings/media.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/media.js b/packages/svelte/src/internal/client/dom/elements/bindings/media.js index d1ddf677ee4e..444a1b34390f 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/media.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/media.js @@ -150,7 +150,9 @@ export function bind_paused(media, get, set = get) { // Listen to the canplay event to get notified of this situation. listen(media, ['play', 'pause', 'canplay'], update, paused == null); - render_effect(() => { + // Needs to be an effect to ensure media element is mounted: else, if paused is `false` (i.e. should play right away) + // a "The play() request was interrupted by a new load request" error would be thrown because the resource isn't loaded yet. + effect(() => { if ((paused = !!get()) !== media.paused) { if (paused) { media.pause();