make linter happy

This commit is contained in:
Jörg Breitbart
2026-08-28 17:32:53 +02:00
parent f1ae0ab30b
commit 651a3537dd
2 changed files with 29 additions and 31 deletions
+29 -27
View File
@@ -42,7 +42,7 @@ interface IAnimation {
/** ImageDecoder instance */
decoder: ImageDecoder | undefined;
decoderPromise: Promise<ImageDecoder> | undefined;
cache: BitmapBuffer,
cache: BitmapBuffer;
/** start timestamp */
startTime: number | undefined;
/** whether a decode task ist scheduled */
@@ -64,7 +64,7 @@ interface IAnimation {
}
interface ImageDraw {
interface IImageDraw {
imageId: number;
imgSpec: IImageSpec;
tileId: number;
@@ -143,7 +143,7 @@ class BitmapBuffer implements IDisposable {
}
// eslint-disable-next-line
declare const InstallTrigger: any;
@@ -165,8 +165,8 @@ async function BlobDecoder(blob: Blob, type: string): Promise<ImageDecoder> {
*
* But this straightforward handling with blob.stream() uncovers several bugs:
* 1. Chromium: Fails to stream chunked blobs reliably.
* 2. Firefox: Native lifecycle race condition. Closing an old decoder breaks the
* shared underlying native stream of the same blob for new decoders, throwing
* 2. Firefox: Native lifecycle race condition. Closing an old decoder breaks the
* shared underlying native stream of the same blob for new decoders, throwing
* an uncatchable "Closed decoder" DOMException during `tracks.ready`.
*
* So we use a safer approach by pulling full raw bytes over first and transferring ownership.
@@ -207,17 +207,21 @@ async function BlobDecoder(blob: Blob, type: string): Promise<ImageDecoder> {
*/
export class AnimationManager implements IDisposable, IResetHandler {
private _animations = new Map<number, IAnimation>();
private _raf: number | null = null;
private _draws: ImageDraw[] = [];
private _animationFrame: number | undefined = undefined;
private _draws: IImageDraw[] = [];
constructor(
private _storage: ImageStorage,
private _renderer: ImageRenderer,
private _terminal: ITerminalExt)
{}
private _terminal: ITerminalExt
) {}
private _raf(callback: FrameRequestCallback): number {
return this._terminal._core._coreBrowserService!.window.requestAnimationFrame(callback);
}
public dispose(): void {
this.reset();
this._storage = undefined!;
@@ -238,8 +242,8 @@ export class AnimationManager implements IDisposable, IResetHandler {
}
this._animations.clear();
this._draws = [];
if (this._raf) cancelAnimationFrame(this._raf);
this._raf = null;
if (this._animationFrame) this._terminal._core._coreBrowserService?.window.cancelAnimationFrame(this._animationFrame);
this._animationFrame = undefined;
}
@@ -271,7 +275,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
const result = await decoder.decode({ frameIndex: i });
const frame = result.image;
const width = frame.displayWidth;
const height = frame.displayHeight
const height = frame.displayHeight;
const duration = (frame.duration ?? 0) / 1000;
frame.close();
// skip wrong dimensions and zero duration
@@ -287,7 +291,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
timestamps.push(elapsed);
durations.push(duration);
elapsed += duration;
} catch (e) {
} catch {
break;
}
}
@@ -334,8 +338,8 @@ export class AnimationManager implements IDisposable, IResetHandler {
this.viewportUpdated();
// early schedule to give decoder time to fill the cache before RAF
this._schedule(anim);
if (this._raf === null) {
this._raf = requestAnimationFrame(this._loop);
if (this._animationFrame === undefined) {
this._animationFrame = this._raf?.(ts => this._loop(ts));
}
}
@@ -363,7 +367,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
const rows = this._terminal.rows;
const cols = this._terminal.cols;
const buffer = this._terminal._core.buffer;
const actives: Set<number> = new Set;
const actives: Set<number> = new Set();
this._draws = [];
for (let row = 0; row < rows; ++row) {
const line = buffer.lines.get(row + buffer.ydisp) as IBufferLineExt;
@@ -457,8 +461,8 @@ export class AnimationManager implements IDisposable, IResetHandler {
this._closeDecoder(anim);
}
}
if (visibles.size && this._raf === null) {
this._raf = requestAnimationFrame(this._loop);
if (visibles.size && this._animationFrame === undefined) {
this._animationFrame = this._raf?.(ts => this._loop(ts));
}
}
@@ -468,7 +472,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
*/
private _loop = (ts: number): void => {
if (!this._animations.size) {
this._raf = null;
this._animationFrame = undefined;
return;
}
@@ -484,9 +488,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
continue;
}
anyVisible = true;
if (anim.startTime === undefined) anim.startTime = ts;
anim.startTime ??= ts;
const frameIdx = this._timedFrameIdx(anim, ts - anim.startTime);
anim.frameIdx = frameIdx;
const current = anim.frames[frameIdx];
@@ -497,7 +499,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
if (bm) {
// FIXME: setting spec.actual delegates draws from onRender back to ImageStorage
// --> should be avoided to prevent double draws within same rAF
// we took ownership of spec.actual, thus have to close it here
// but only if we have more than 4 frames (ringbuffer size is 4)
if (anim.numFrames > 4) spec.actual?.close();
@@ -518,7 +520,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
this._renderer.draw(d.imgSpec, d.tileId, d.col, d.row, d.count);
}
}
this._raf = anyVisible ? requestAnimationFrame(this._loop) : null;
this._animationFrame = anyVisible ? this._raf?.(ts => this._loop(ts)) : undefined;
};
@@ -579,11 +581,11 @@ export class AnimationManager implements IDisposable, IResetHandler {
let res: ImageDecodeResult;
try {
res = await a.decoder.decode({ frameIndex: n });
} catch (e) { continue; }
} catch { continue; }
let bm: ImageBitmap;
try {
bm = await createImageBitmap(res.image, { resizeWidth: a.w, resizeHeight: a.h });
} catch (e) { continue; } finally { res?.image?.close(); }
} catch { continue; } finally { res?.image?.close(); }
if (!a.inViewport) {
bm.close();
break;
@@ -601,7 +603,7 @@ export class AnimationManager implements IDisposable, IResetHandler {
private _closeDecoder(a: IAnimation): void {
const decoder = a.decoder;
a.decoder = undefined;
try { decoder?.close(); } catch (e) {}
try { decoder?.close(); } catch {}
const decP = a.decoderPromise;
a.decoderPromise = undefined;
decP?.then(dec => dec && dec !== decoder ? dec.close() : null).catch(() => {});
-4
View File
@@ -199,10 +199,6 @@ export class IIPHandler implements IOscHandler, IResetHandler {
} else {
blob = new Blob([this._dec.data8], { type: metrics.mime });
}
//let imgBytes: Uint8Array;
//if (this._aniManager && metrics.animated) {
// imgBytes = new Uint8Array(this._dec.data8);
//}
this._dec.release();
return createImageBitmap(blob, { resizeWidth: w, resizeHeight: h })
.then(bm => {