Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null inline class JavaScript Event callback properties on destroy #6102

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions api-extractor/report/hls.js.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,16 +443,12 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP
// (undocumented)
protected onMediaDetaching(): void;
// (undocumented)
protected onMediaEnded(): void;
protected onMediaEnded: () => void;
// (undocumented)
protected onMediaSeeking(): void;
protected onMediaSeeking: () => void;
// (undocumented)
protected onTickEnd(): void;
// (undocumented)
protected onvended: EventListener | null;
// (undocumented)
protected onvseeking: EventListener | null;
// (undocumented)
protected playlistType: PlaylistLevelType;
// (undocumented)
protected recoverWorkerError(data: ErrorData): void;
Expand Down
25 changes: 10 additions & 15 deletions src/controller/base-stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ export default class BaseStreamController
protected startFragRequested: boolean = false;
protected decrypter: Decrypter;
protected initPTS: RationalTimestamp[] = [];
protected onvseeking: EventListener | null = null;
protected onvended: EventListener | null = null;

private readonly logPrefix: string = '';
protected log: (msg: any) => void;
Expand Down Expand Up @@ -197,10 +195,8 @@ export default class BaseStreamController
data: MediaAttachedData,
) {
const media = (this.media = this.mediaBuffer = data.media);
this.onvseeking = this.onMediaSeeking.bind(this) as EventListener;
this.onvended = this.onMediaEnded.bind(this) as EventListener;
media.addEventListener('seeking', this.onvseeking);
media.addEventListener('ended', this.onvended);
media.addEventListener('seeking', this.onMediaSeeking);
media.addEventListener('ended', this.onMediaEnded);
const config = this.config;
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
this.startLoad(config.startPosition);
Expand All @@ -215,10 +211,9 @@ export default class BaseStreamController
}

// remove video listeners
if (media && this.onvseeking && this.onvended) {
media.removeEventListener('seeking', this.onvseeking);
media.removeEventListener('ended', this.onvended);
this.onvseeking = this.onvended = null;
if (media) {
media.removeEventListener('seeking', this.onMediaSeeking);
media.removeEventListener('ended', this.onMediaEnded);
}
if (this.keyLoader) {
this.keyLoader.detach();
Expand All @@ -229,7 +224,7 @@ export default class BaseStreamController
this.stopLoad();
}

protected onMediaSeeking() {
protected onMediaSeeking = () => {
const { config, fragCurrent, media, mediaBuffer, state } = this;
const currentTime: number = media ? media.currentTime : 0;
const bufferInfo = BufferHelper.bufferInfo(
Expand Down Expand Up @@ -292,12 +287,12 @@ export default class BaseStreamController

// Async tick to speed up processing
this.tickImmediate();
}
};

protected onMediaEnded() {
protected onMediaEnded = () => {
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
this.startPosition = this.lastCurrentTime = 0;
}
};

protected onManifestLoaded(
event: Events.MANIFEST_LOADED,
Expand All @@ -312,7 +307,7 @@ export default class BaseStreamController
this.stopLoad();
super.onHandlerDestroying();
// @ts-ignore
this.hls = null;
this.hls = this.onMediaSeeking = this.onMediaEnded = null;
}

protected onHandlerDestroyed() {
Expand Down
6 changes: 6 additions & 0 deletions src/controller/buffer-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ export default class BufferController implements ComponentAPI {
this.lastMpegAudioChunk = null;
// @ts-ignore
this.hls = null;
// @ts-ignore
this._onMediaSourceOpen = this._onMediaSourceClose = null;
// @ts-ignore
this._onMediaSourceEnded = null;
// @ts-ignore
this._onStartStreaming = this._onEndStreaming = null;
}

protected registerListeners() {
Expand Down
18 changes: 6 additions & 12 deletions src/controller/eme-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ class EMEController implements ComponentAPI {
private setMediaKeysQueue: Promise<void>[] = EMEController.CDMCleanupPromise
? [EMEController.CDMCleanupPromise]
: [];
private onMediaEncrypted = this._onMediaEncrypted.bind(this);
private onWaitingForKey = this._onWaitingForKey.bind(this);

private debug: (msg: any) => void = logger.debug.bind(logger, LOGGER_PREFIX);
private log: (msg: any) => void = logger.log.bind(logger, LOGGER_PREFIX);
Expand All @@ -113,13 +111,9 @@ class EMEController implements ComponentAPI {
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
config.drmSystems = config.drmSystemOptions = {};
// @ts-ignore
this.hls =
this.onMediaEncrypted =
this.onWaitingForKey =
this.keyIdToKeySessionPromise =
null as any;
this.hls = this.config = this.keyIdToKeySessionPromise = null;
// @ts-ignore
this.config = null;
this.onMediaEncrypted = this.onWaitingForKey = null;
}

private registerListeners() {
Expand Down Expand Up @@ -523,7 +517,7 @@ class EMEController implements ComponentAPI {
return this.attemptKeySystemAccess(keySystemsToAttempt);
}

private _onMediaEncrypted(event: MediaEncryptedEvent) {
private onMediaEncrypted = (event: MediaEncryptedEvent) => {
const { initDataType, initData } = event;
this.debug(`"${event.type}" event: init data type: "${initDataType}"`);

Expand Down Expand Up @@ -639,11 +633,11 @@ class EMEController implements ComponentAPI {
);
}
keySessionContextPromise.catch((error) => this.handleError(error));
}
};

private _onWaitingForKey(event: Event) {
private onWaitingForKey = (event: Event) => {
this.log(`"${event.type}" event`);
}
};

private attemptSetMediaKeys(
keySystem: KeySystems,
Expand Down
15 changes: 7 additions & 8 deletions src/controller/latency-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export default class LatencyController implements ComponentAPI {
private currentTime: number = 0;
private stallCount: number = 0;
private _latency: number | null = null;
private timeupdateHandler = () => this.timeupdate();

constructor(hls: Hls) {
this.hls = hls;
Expand Down Expand Up @@ -126,7 +125,7 @@ export default class LatencyController implements ComponentAPI {
this.onMediaDetaching();
this.levelDetails = null;
// @ts-ignore
this.hls = this.timeupdateHandler = null;
this.hls = this.onTimeupdate = null;
}

private registerListeners() {
Expand All @@ -150,12 +149,12 @@ export default class LatencyController implements ComponentAPI {
data: MediaAttachingData,
) {
this.media = data.media;
this.media.addEventListener('timeupdate', this.timeupdateHandler);
this.media.addEventListener('timeupdate', this.onTimeupdate);
}

private onMediaDetaching() {
if (this.media) {
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
this.media.removeEventListener('timeupdate', this.onTimeupdate);
this.media = null;
}
}
Expand All @@ -172,10 +171,10 @@ export default class LatencyController implements ComponentAPI {
) {
this.levelDetails = details;
if (details.advanced) {
this.timeupdate();
this.onTimeupdate();
}
if (!details.live && this.media) {
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
this.media.removeEventListener('timeupdate', this.onTimeupdate);
}
}

Expand All @@ -191,7 +190,7 @@ export default class LatencyController implements ComponentAPI {
}
}

private timeupdate() {
private onTimeupdate = () => {
const { media, levelDetails } = this;
if (!media || !levelDetails) {
return;
Expand Down Expand Up @@ -242,7 +241,7 @@ export default class LatencyController implements ComponentAPI {
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
media.playbackRate = 1;
}
}
};

private estimateLiveEdge(): number | null {
const { levelDetails } = this;
Expand Down
25 changes: 11 additions & 14 deletions src/controller/stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ export default class StreamController
private altAudio: boolean = false;
private audioOnly: boolean = false;
private fragPlaying: Fragment | null = null;
private onvplaying: EventListener | null = null;
private onvseeked: EventListener | null = null;
private fragLastKbps: number = 0;
private couldBacktrack: boolean = false;
private backtrackFragment: Fragment | null = null;
Expand Down Expand Up @@ -117,6 +115,8 @@ export default class StreamController

protected onHandlerDestroying() {
this._unregisterListeners();
// @ts-ignore
this.onMediaPlaying = this.onMediaSeeked = null;
super.onHandlerDestroying();
}

Expand Down Expand Up @@ -515,10 +515,8 @@ export default class StreamController
) {
super.onMediaAttached(event, data);
const media = data.media;
this.onvplaying = this.onMediaPlaying.bind(this);
this.onvseeked = this.onMediaSeeked.bind(this);
media.addEventListener('playing', this.onvplaying as EventListener);
media.addEventListener('seeked', this.onvseeked as EventListener);
media.addEventListener('playing', this.onMediaPlaying);
media.addEventListener('seeked', this.onMediaSeeked);
this.gapController = new GapController(
this.config,
media,
Expand All @@ -529,10 +527,9 @@ export default class StreamController

protected onMediaDetaching() {
const { media } = this;
if (media && this.onvplaying && this.onvseeked) {
media.removeEventListener('playing', this.onvplaying);
media.removeEventListener('seeked', this.onvseeked);
this.onvplaying = this.onvseeked = null;
if (media) {
media.removeEventListener('playing', this.onMediaPlaying);
media.removeEventListener('seeked', this.onMediaSeeked);
this.videoBuffer = null;
}
this.fragPlaying = null;
Expand All @@ -543,12 +540,12 @@ export default class StreamController
super.onMediaDetaching();
}

private onMediaPlaying() {
private onMediaPlaying = () => {
// tick to speed up FRAG_CHANGED triggering
this.tick();
}
};

private onMediaSeeked() {
private onMediaSeeked = () => {
const media = this.media;
const currentTime = media ? media.currentTime : null;
if (Number.isFinite(currentTime)) {
Expand All @@ -568,7 +565,7 @@ export default class StreamController

// tick to speed up FRAG_CHANGED triggering
this.tick();
}
};

private onManifestLoading() {
// reset buffer on manifest loading
Expand Down
6 changes: 4 additions & 2 deletions src/controller/subtitle-track-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ class SubtitleTrackController extends BasePlaylistController {
private currentTrack: MediaPlaylist | null = null;
private selectDefaultTrack: boolean = true;
private queuedDefaultTrack: number = -1;
private asyncPollTrackChange: () => void = () => this.pollTrackChange(0);
private useTextTrackPolling: boolean = false;
private subtitlePollingInterval: number = -1;
private _subtitleDisplay: boolean = true;

private asyncPollTrackChange = () => this.pollTrackChange(0);

constructor(hls: Hls) {
super(hls, '[subtitle-track-controller]');
this.registerListeners();
Expand All @@ -50,7 +51,8 @@ class SubtitleTrackController extends BasePlaylistController {
this.tracks.length = 0;
this.tracksInGroup.length = 0;
this.currentTrack = null;
this.onTextTracksChanged = this.asyncPollTrackChange = null as any;
// @ts-ignore
this.onTextTracksChanged = this.asyncPollTrackChange = null;
super.destroy();
}

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/controller/latency-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('LatencyController', function () {
currentTimeStub.get(() => currentTime);
currentTimeStub.set((value: number) => {
currentTime = value;
latencyController['timeupdate']();
latencyController['onTimeupdate']();
});
});

Expand Down
Loading