Skip to content

Commit c6af26f

Browse files
fix: add media listeners immediately when using bind:paused (#13502)
Fix a bug where play/pause events may never be added to the media element. Also simplifies the logic by making it an effect instead of a render effect --------- Co-authored-by: Simon Holthausen <[email protected]>
1 parent 14ecedf commit c6af26f

File tree

2 files changed

+18
-41
lines changed

2 files changed

+18
-41
lines changed

.changeset/fair-items-bathe.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: add media listeners immediately when using `bind:paused`

packages/svelte/src/internal/client/dom/elements/bindings/media.js

Lines changed: 13 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -138,56 +138,28 @@ export function bind_playback_rate(media, get, set = get) {
138138
* @param {(paused: boolean) => void} set
139139
*/
140140
export function bind_paused(media, get, set = get) {
141-
var mounted = hydrating;
142141
var paused = get();
143142

144-
var callback = () => {
143+
var update = () => {
145144
if (paused !== media.paused) {
146-
paused = media.paused;
147145
set((paused = media.paused));
148146
}
149147
};
150148

151-
if (paused == null) {
152-
callback();
153-
}
154-
155-
// Defer listening if not mounted yet so that the first canplay event doesn't cause a potentially wrong update
156-
if (mounted) {
157-
// If someone switches the src while media is playing, the player will pause.
158-
// Listen to the canplay event to get notified of this situation.
159-
listen(media, ['play', 'pause', 'canplay'], callback, false);
160-
}
149+
// If someone switches the src while media is playing, the player will pause.
150+
// Listen to the canplay event to get notified of this situation.
151+
listen(media, ['play', 'pause', 'canplay'], update, paused == null);
161152

162-
render_effect(() => {
163-
paused = !!get();
164-
165-
if (paused !== media.paused) {
166-
var toggle = () => {
167-
mounted = true;
168-
if (paused) {
169-
media.pause();
170-
} else {
171-
media.play().catch(() => {
172-
set((paused = true));
173-
});
174-
}
175-
};
176-
177-
if (mounted) {
178-
toggle();
153+
// Needs to be an effect to ensure media element is mounted: else, if paused is `false` (i.e. should play right away)
154+
// a "The play() request was interrupted by a new load request" error would be thrown because the resource isn't loaded yet.
155+
effect(() => {
156+
if ((paused = !!get()) !== media.paused) {
157+
if (paused) {
158+
media.pause();
179159
} else {
180-
// If this is the first invocation in dom mode, the media element isn't mounted yet,
181-
// and therefore its resource isn't loaded yet. We need to wait for the canplay event
182-
// in this case or else we'll get a "The play() request was interrupted by a new load request" error.
183-
media.addEventListener(
184-
'canplay',
185-
() => {
186-
listen(media, ['play', 'pause', 'canplay'], callback, false);
187-
toggle();
188-
},
189-
{ once: true }
190-
);
160+
media.play().catch(() => {
161+
set((paused = true));
162+
});
191163
}
192164
}
193165
});

0 commit comments

Comments
 (0)