fix(viewer): destroy only the current hls/flv instance on player teardown (#3139)

switchUrl() re-invokes the customType handler, which registered one
'destroy' listener per created player. On teardown every stale closure
fired — mpegts null-derefs on an already-destroyed instance, crashing
the page after FLV URL refreshes. Register a single hook per media
type (WeakMap-guarded) that destroys the currently assigned player
inside try/catch.
pull/3582/head
Tomas Dvorak 2 weeks ago
parent d260c3f92d
commit f8a58109b4

@ -82,7 +82,7 @@ const playM3u8 =
hls.loadSource(url); hls.loadSource(url);
hls.attachMedia(video); hls.attachMedia(video);
art.hls = hls; art.hls = hls;
art.on("destroy", () => hls.destroy()); hookMediaDestroy(art, "hls");
} else if (video.canPlayType("application/vnd.apple.mpegurl")) { } else if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = url; video.src = url;
} else { } else {
@ -106,12 +106,35 @@ const playFlv = (video: HTMLVideoElement, url: string, art: Artplayer) => {
flv.attachMediaElement(video); flv.attachMediaElement(video);
flv.load(); flv.load();
art.flv = flv; art.flv = flv;
art.on("destroy", () => flv.destroy()); hookMediaDestroy(art, "flv");
} else { } else {
art.notice.show = "Unsupported playback format: flv"; art.notice.show = "Unsupported playback format: flv";
} }
}; };
// Registers a single destroy hook per media type. switchUrl() re-invokes the
// customType handler and would otherwise stack one handler per player —
// destroying a stale, already-destroyed instance (mpegts null-derefs, #3139).
const hookedPlayers = new WeakMap<Artplayer, Set<string>>();
const hookMediaDestroy = (art: Artplayer, key: "hls" | "flv") => {
let flags = hookedPlayers.get(art);
if (!flags) {
flags = new Set();
hookedPlayers.set(art, flags);
}
if (flags.has(key)) {
return;
}
flags.add(key);
art.on("destroy", () => {
try {
art[key]?.destroy();
} catch (e) {
console.warn(`Failed to destroy ${key} player:`, e);
}
});
};
export default function Player({ export default function Player({
option, option,
chapters, chapters,

Loading…
Cancel
Save