Repository: sveltejs/svelte
File: packages/svelte/src/internal/client/dom/elements/bindings/media.js (JavaScript)

Code before:

	// Start listening to ratechange events after the element is inserted into the dom,
	// else playback will be set to 1 by the browser
	effect(() => {
		listen(media, ['ratechange'], () => {
			set(media.playbackRate);
		});
	});
}

/**
 * @param {HTMLVideoElement | HTMLAudioElement} media
 * @param {() => boolean | undefined} get
 * @param {(paused: boolean) => void} set
 */
export function bind_paused(media, get, set = get) {
	var mounted = hydrating;
	var paused = get();

	var callback = () => {
		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);
	}

	render_effect(() => {
		paused = !!get();

		if (paused !== media.paused) {
			var toggle = () => {
				mounted = true;
				if (paused) {
					media.pause();
				} else {
					media.play().catch(() => {
						set((paused = true));
					});
				}
			};

Review comment (suggestion):
Should this be the expected behavior? This can be really annoying to deal with.
For context, that is the situation: https://svelte-5-preview.vercel.app/#H4sIAAAAAAAACqVSwW7bMAz9FUKXJoARNzns4MUBti_oYbd5KByZtoXKpCFSHQrD_z4oStd1wbBDT4QeH98jHrWY3nkUU31fDLUTmsp8mWdTGH2Z00Oe0SuawgjHYBNyFBvcrKeGGvWooG5CqOH-8ysgwUINFL3_Dc1tFOyghr71ggmmRi2TKMy-fYEaNiTBbqE-wZJ6jb6TbfQqKsFegVtJXf_WbWPneJ_U_1ROnc3dqDpLVZatVccku4F58LizPJXCkTopn_dl69swSS6P1rN92vEw3G3_7Xb4uNs5Dh4fNRK-MzuWb8HT8WIGZ0ddZWMISPrNTVgvKbY14zmhesl1hUWCXU_H8jKaVc5RlQmYrHf2qV7eQlsv931Ix8lW-7RB5v9n9nAze7iZDaeGLgQdEXoXRDO1gJY6OGPPAcEpIHVS5D-SmKwjBmBC2MjMzmOoEuun8x6I8xm2r_pfWcfrAmMr8AkELVMnDZnCTNy53mFnKg0R1x_rL2WeCyQJAwAA

Code after:

	// Start listening to ratechange events after the element is inserted into the dom,
	// else playback will be set to 1 by the browser
	effect(() => {
		listen(media, ['ratechange'], () => {
			set(media.playbackRate);
		});
	});
}

/**
 * @param {HTMLVideoElement | HTMLAudioElement} media
 * @param {() => boolean | undefined} get
 * @param {(paused: boolean) => void} set
 */
export function bind_paused(media, get, set = get) {
	var paused = get();

	var update = () => {
		if (paused !== media.paused) {
			set((paused = media.paused));
		}
	};

	// 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);

	// 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();
			} else {
				media.play().catch(() => {
					set((paused = true));
				});
			}
		}
	});
}

/**
 * @param {HTMLVideoElement | HTMLAudioElement} media
 * @param {() => number | undefined} get
 * @param {(volume: number) => void} set
 */
export function bind_volume(media, get, set = get) {
	var callback = () => {
		set(media.volume);