Name call serializers differently

This commit is contained in:
Vanilagy
2025-12-30 11:44:27 +01:00
parent aafb928460
commit 8467a9d672
5 changed files with 36 additions and 27 deletions
+2 -2
View File
@@ -14,7 +14,7 @@ import {
assert,
AsyncMutex,
AsyncMutexLock,
CallSerializer2,
ForgivingCallSerializer,
defer,
isFirefox,
last,
@@ -255,7 +255,7 @@ export class PacketCursor<T extends InputTrack = InputTrack> {
private _reader: PacketReader<T>;
private _options: PacketRetrievalOptions;
private _nextIsFirst = true;
private _callSerializer = new CallSerializer2();
private _callSerializer = new ForgivingCallSerializer();
constructor(track: T, options: PacketRetrievalOptions = {}) {
if (!(track instanceof InputTrack)) {
+3 -3
View File
@@ -20,7 +20,7 @@ import {
} from './codec-data';
import { CustomAudioDecoder, customAudioDecoders, CustomVideoDecoder, customVideoDecoders } from './custom-coder';
import {
CallSerializer,
NaiveCallSerializer,
Rotation,
isChromium,
toUint8Array,
@@ -57,7 +57,7 @@ export class VideoDecoderWrapper extends DecoderWrapper<VideoSample> {
decoder: VideoDecoder | null = null;
customDecoder: CustomVideoDecoder | null = null;
customDecoderCallSerializer = new CallSerializer();
customDecoderCallSerializer = new NaiveCallSerializer();
customDecoderQueueSize = 0;
customDecoderClosed = false;
@@ -645,7 +645,7 @@ export class AudioDecoderWrapper extends DecoderWrapper<AudioSample> {
decoder: AudioDecoder | null = null;
customDecoder: CustomAudioDecoder | null = null;
customDecoderCallSerializer = new CallSerializer();
customDecoderCallSerializer = new NaiveCallSerializer();
customDecoderQueueSize = 0;
customDecoderClosed = false;
+3 -3
View File
@@ -23,7 +23,7 @@ import { OutputAudioTrack, OutputSubtitleTrack, OutputTrack, OutputVideoTrack }
import {
assert,
assertNever,
CallSerializer,
NaiveCallSerializer,
clamp,
isFirefox,
last,
@@ -214,7 +214,7 @@ class VideoEncoderWrapper {
private resizeCanvas: HTMLCanvasElement | OffscreenCanvas | null = null;
private customEncoder: CustomVideoEncoder | null = null;
private customEncoderCallSerializer = new CallSerializer();
private customEncoderCallSerializer = new NaiveCallSerializer();
private customEncoderQueueSize = 0;
// Alpha stuff
@@ -1342,7 +1342,7 @@ class AudioEncoderWrapper {
private writeOutputValue: ((view: DataView, byteOffset: number, value: number) => void) | null = null;
private customEncoder: CustomAudioEncoder | null = null;
private customEncoderCallSerializer = new CallSerializer();
private customEncoderCallSerializer = new NaiveCallSerializer();
private customEncoderQueueSize = 0;
private lastEndSampleIndex: number | null = null;
+24 -15
View File
@@ -675,20 +675,6 @@ export const computeRationalApproximation = (x: number, maxDenominator: number)
};
};
export class CallSerializer {
currentPromise = Promise.resolve();
errored = false;
call(fn: () => Promise<void> | void) {
return this.currentPromise = this.currentPromise
.then(fn)
.catch((error) => {
this.errored = true;
throw error;
});
}
}
let isWebKitCache: boolean | null = null;
export const isWebKit = () => {
if (isWebKitCache !== null) {
@@ -938,7 +924,30 @@ export class AsyncMutexLock implements Disposable {
}
}
export class CallSerializer2 {
/**
* A simple call serializer that works by chaining promises. When one callback throws, the serializer becomes bricked,
* meaning all future calls will also throw.
*/
export class NaiveCallSerializer {
currentPromise = Promise.resolve();
errored = false;
call(fn: () => Promise<void> | void) {
return this.currentPromise = this.currentPromise
.then(fn)
.catch((error) => {
this.errored = true;
throw error;
});
}
}
/**
* A more complex call serializer implementation that works with optionally asynchronous functions. It is forgiving
* in the sense that when a call throws, the error is surfaced but subsequent calls will go through again. So, it
* recovers.
*/
export class ForgivingCallSerializer {
private currentPromise: Promise<unknown> | null = null;
private queuedCalls = 0;
@@ -1,5 +1,5 @@
import { expect, test } from 'vitest';
import { CallSerializer2 } from '../../src/misc.js';
import { ForgivingCallSerializer } from '../../src/misc.js';
const executeDelayed = async <T>(fn: () => T) => {
await new Promise(resolve => setTimeout(resolve, 10));
@@ -8,7 +8,7 @@ const executeDelayed = async <T>(fn: () => T) => {
test('Call serialization and return values', async () => {
const numbers: number[] = [];
const serializer = new CallSerializer2();
const serializer = new ForgivingCallSerializer();
const first = serializer.call(() => numbers.push(1));
const second = serializer.call(() => executeDelayed(() => numbers.push(2)));
@@ -25,7 +25,7 @@ test('Call serialization and return values', async () => {
});
test('Synchronous return value', async () => {
const serializer = new CallSerializer2();
const serializer = new ForgivingCallSerializer();
const first = serializer.call(() => {});
expect(first).not.toBeInstanceOf(Promise);
@@ -42,7 +42,7 @@ test('Synchronous return value', async () => {
});
test('Error handling', async () => {
const serializer = new CallSerializer2();
const serializer = new ForgivingCallSerializer();
expect(() => serializer.call(() => {
throw new Error('yo');