fix(web): critical runtime fixes

Fix BigInt(NaN), player.src(undefined), codeMap fallback, videoWidth,
quality guard, listener leaks, vid.style, window.videojs, MediaSession SSR.
This commit is contained in:
Kamil Moskała
2026-03-25 00:08:10 +01:00
parent 580acb7225
commit 3e839810f6
4 changed files with 25 additions and 16 deletions
@@ -74,9 +74,6 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
nativeTextTracks: true,
},
});
// @ts-ignore used for debugging or extending purposes
window.videojs = videojs;
super(new WebEventEmitter(player));
this.video = video;
@@ -110,7 +107,7 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
width: this.player.videoWidth(),
height: this.player.videoHeight(),
duration: this.duration,
fileSize: BigInt(NaN),
fileSize: -1n,
isHDR: false,
isLive: false,
orientation: "landscape",
@@ -80,7 +80,7 @@ const VideoView = forwardRef<VideoViewRef, VideoViewProps>(
const vid = player.__getNativeRef();
const objectFit: CSSProperties["objectFit"] =
resizeMode === "stretch" ? "fill" : resizeMode;
vid.style = `position: absolute; inset: 0; width: 100%; height: 100%; object-fit: ${objectFit}`;
vid.style.cssText = `position: absolute; inset: 0; width: 100%; height: 100%; object-fit: ${objectFit}`;
}, [player, resizeMode]);
return (
@@ -3,7 +3,10 @@ import type { CustomVideoMetadata } from "../types/VideoConfig";
type VideoJsPlayer = ReturnType<typeof videojs>;
const mediaSession = window.navigator.mediaSession;
function getMediaSession(): MediaSession | undefined {
if (typeof window === "undefined") return undefined;
return window.navigator?.mediaSession;
}
export class MediaSessionHandler {
enabled: boolean = false;
@@ -11,6 +14,9 @@ export class MediaSessionHandler {
constructor(private player: VideoJsPlayer) {}
enable() {
const mediaSession = getMediaSession();
if (!mediaSession) return;
this.enabled = true;
const defaultSkipTime = 15;
@@ -133,6 +139,9 @@ export class MediaSessionHandler {
disable() {}
updateMediaSession(metadata: CustomVideoMetadata | undefined) {
const mediaSession = getMediaSession();
if (!mediaSession) return;
if (!metadata) {
mediaSession.metadata = null;
return;
@@ -106,6 +106,8 @@ export class WebEventEmitter implements VideoPlayerEventEmitterBase {
this.player.off("durationchange", this._onDurationChange);
this.player.off("loadstart", this._onLoadStart);
this.player.off("play", this._onPlay);
this.player.off("pause", this._onPause);
@@ -127,7 +129,6 @@ export class WebEventEmitter implements VideoPlayerEventEmitterBase {
this.player.videoTracks().off("change", this._onVideoTrackChange);
this._onQualityChange = this._onQualityChange.bind(this);
// @ts-expect-error this isn't typed
this.player.qualityLevels().off("change", this._onQualityChange);
}
@@ -309,8 +310,8 @@ export class WebEventEmitter implements VideoPlayerEventEmitterBase {
this._emit("onLoad", {
currentTime: this.player.currentTime() ?? 0,
duration: this.player.duration() ?? NaN,
width: this.player.width() ?? NaN,
height: this.player.height() ?? NaN,
width: this.player.videoWidth() ?? NaN,
height: this.player.videoHeight() ?? NaN,
orientation: "unknown",
});
}
@@ -324,19 +325,19 @@ export class WebEventEmitter implements VideoPlayerEventEmitterBase {
this._emit("onLoadStart", {
sourceType: "network",
source: {
uri: this.player.src(undefined)!,
uri: this.player.currentSrc(),
config: {
uri: this.player.src(undefined)!,
uri: this.player.currentSrc(),
externalSubtitles: [],
},
getAssetInformationAsync: async () => {
return {
duration: this.player.duration() ?? NaN,
height: this.player.height() ?? NaN,
width: this.player.width() ?? NaN,
height: this.player.videoHeight() ?? NaN,
width: this.player.videoWidth() ?? NaN,
orientation: "unknown",
bitrate: NaN,
fileSize: BigInt(NaN),
fileSize: -1n,
isHDR: false,
isLive: false,
};
@@ -399,7 +400,7 @@ export class WebEventEmitter implements VideoPlayerEventEmitterBase {
number,
LibraryError | PlayerError | SourceError | UnknownError
>;
this._emit("onError", new VideoError(codeMap[err.code]!, err.message));
this._emit("onError", new VideoError(codeMap[err.code] ?? "unknown/unknown", err.message));
}
_onTextTrackChange() {
@@ -450,7 +451,9 @@ export class WebEventEmitter implements VideoPlayerEventEmitterBase {
_onQualityChange() {
// @ts-expect-error this isn't typed
const levels: VideoJsQualityArray = this.player.qualityLevels();
const quality = levels[levels.selectedIndex]!;
if (levels.selectedIndex < 0) return;
const quality = levels[levels.selectedIndex];
if (!quality) return;
this._emit("onQualityChange", {
id: quality.id,