Add ducktyped Promise checks (fixes #472)

This commit is contained in:
Vanilagy
2026-08-26 11:24:24 +02:00
parent 0f9dc1f91b
commit 14fb7d0119
19 changed files with 162 additions and 128 deletions
+6 -5
View File
@@ -23,6 +23,7 @@ import {
AsyncMutex,
binarySearchExact,
binarySearchLessOrEqual,
isThenable,
UNDETERMINED_LANGUAGE,
} from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
@@ -84,7 +85,7 @@ export class AdtsDemuxer extends Demuxer {
// Skip all ID3v2 tags at the start of the file
while (true) {
let slice = this.reader.requestSlice(this.lastLoadedPos, ID3_V2_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
this.lastSampleLoaded = true;
@@ -105,7 +106,7 @@ export class AdtsDemuxer extends Demuxer {
MIN_ADTS_FRAME_HEADER_SIZE,
MAX_ADTS_FRAME_HEADER_SIZE,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
this.lastSampleLoaded = true;
return;
@@ -167,7 +168,7 @@ export class AdtsDemuxer extends Demuxer {
while (true) {
let headerSlice = this.reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
if (!headerSlice) break;
const id3V2Header = readId3V2Header(headerSlice);
@@ -176,7 +177,7 @@ export class AdtsDemuxer extends Demuxer {
}
let contentSlice = this.reader.requestSlice(headerSlice.filePos, id3V2Header.size);
if (contentSlice instanceof Promise) contentSlice = await contentSlice;
if (isThenable(contentSlice)) contentSlice = await contentSlice;
if (!contentSlice) break;
parseId3V2Tag(contentSlice, id3V2Header, this.metadataTags);
@@ -306,7 +307,7 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
data = PLACEHOLDER_DATA;
} else {
let slice = this.demuxer.reader.requestSlice(rawSample.dataStart, rawSample.dataSize);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null; // Data didn't fit into the rest of the file
+2 -2
View File
@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { assert, MaybePromise } from './misc';
import { assert, isThenable, MaybePromise } from './misc';
import { readBytes, Reader } from './reader';
// Inspired in part by https://github.com/halloweeks/AES-128-CBC/blob/main/AES_128_CBC.h
@@ -258,7 +258,7 @@ export const createAes128CbcDecryptStream = (
const requestedLength = CHUNK_SIZE + BLOCK_SIZE;
let nextSlice = reader.requestSliceRange(pos, 0, requestedLength);
if (nextSlice instanceof Promise) nextSlice = await nextSlice;
if (isThenable(nextSlice)) nextSlice = await nextSlice;
if (!nextSlice || nextSlice.length === 0) {
// Due to padding, this should never happen
throw new Error('Invalid ciphertext.');
+8 -7
View File
@@ -15,6 +15,7 @@ import {
assert,
AsyncMutex,
binarySearchLessOrEqual,
isThenable,
textDecoder,
UNDETERMINED_LANGUAGE,
} from '../misc';
@@ -108,7 +109,7 @@ export class FlacDemuxer extends Demuxer {
let currentPos = 0;
while (true) {
let headerSlice = this.reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
if (!headerSlice) {
this.lastSampleLoaded = true;
@@ -121,7 +122,7 @@ export class FlacDemuxer extends Demuxer {
}
let contentSlice = this.reader.requestSlice(headerSlice.filePos, id3V2Header.size);
if (contentSlice instanceof Promise) contentSlice = await contentSlice;
if (isThenable(contentSlice)) contentSlice = await contentSlice;
assert(contentSlice);
parseId3V2Tag(contentSlice, id3V2Header, this.metadataTags);
@@ -136,7 +137,7 @@ export class FlacDemuxer extends Demuxer {
|| currentPos < this.reader.fileSize
) {
let sizeSlice = this.reader.requestSlice(currentPos, 4);
if (sizeSlice instanceof Promise) sizeSlice = await sizeSlice;
if (isThenable(sizeSlice)) sizeSlice = await sizeSlice;
currentPos += 4;
if (sizeSlice === null) {
@@ -160,7 +161,7 @@ export class FlacDemuxer extends Demuxer {
currentPos,
size,
);
if (streamInfoBlock instanceof Promise) streamInfoBlock = await streamInfoBlock;
if (isThenable(streamInfoBlock)) streamInfoBlock = await streamInfoBlock;
assert(streamInfoBlock);
if (streamInfoBlock === null) {
@@ -219,7 +220,7 @@ export class FlacDemuxer extends Demuxer {
currentPos,
size,
);
if (vorbisCommentBlock instanceof Promise) vorbisCommentBlock = await vorbisCommentBlock;
if (isThenable(vorbisCommentBlock)) vorbisCommentBlock = await vorbisCommentBlock;
assert(vorbisCommentBlock);
@@ -237,7 +238,7 @@ export class FlacDemuxer extends Demuxer {
currentPos,
size,
);
if (pictureBlock instanceof Promise) pictureBlock = await pictureBlock;
if (isThenable(pictureBlock)) pictureBlock = await pictureBlock;
assert(pictureBlock);
const pictureType = readU32Be(pictureBlock);
@@ -775,7 +776,7 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
rawSample.byteOffset,
rawSample.byteSize,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null; // Data didn't fit into the rest of the file
+16 -16
View File
@@ -36,7 +36,7 @@ import { TS_PACKET_SIZE } from './mpeg-ts/mpeg-ts-misc';
import { HlsDemuxer } from './hls/hls-demuxer';
import { HLS_MIME_TYPE } from './hls/hls-misc';
import { PathedSource } from './source';
import { MaybePromise } from './misc';
import { isThenable, MaybePromise } from './misc';
/**
* Base class representing an input media file format.
@@ -75,7 +75,7 @@ export abstract class IsobmffInputFormat extends InputFormat {
/** @internal */
protected async _getMajorBrand(input: Input) {
let slice = input._reader.requestSlice(0, 12);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return null;
slice.skip(4);
@@ -117,7 +117,7 @@ export class Mp4InputFormat extends IsobmffInputFormat {
}
let slice = input._reader.requestSlice(4, 4);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
const fourCc = readAscii(slice, 4);
@@ -169,7 +169,7 @@ export class MatroskaInputFormat extends InputFormat {
/** @internal */
protected async isSupportedEBMLOfDocType(input: Input, desiredDocType: string) {
let headerSlice = input._reader.requestSlice(0, MAX_HEADER_SIZE);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
if (!headerSlice) return false;
const varIntSize = readVarIntSize(headerSlice);
@@ -192,7 +192,7 @@ export class MatroskaInputFormat extends InputFormat {
}
let dataSlice = input._reader.requestSlice(headerSlice.filePos, dataSize);
if (dataSlice instanceof Promise) dataSlice = await dataSlice;
if (isThenable(dataSlice)) dataSlice = await dataSlice;
if (!dataSlice) return false;
const startPos = headerSlice.filePos;
@@ -295,7 +295,7 @@ export class Mp3InputFormat extends InputFormat {
while (true) {
let slice = input._reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const id3V2Header = readId3V2Header(slice);
@@ -315,7 +315,7 @@ export class Mp3InputFormat extends InputFormat {
const xingOffset = getXingOffset(firstHeader.mpegVersionId, firstHeader.channel);
let slice = input._reader.requestSlice(firstResult.startPos + xingOffset, 4);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
const word = readU32Be(slice);
@@ -376,7 +376,7 @@ export class WaveInputFormat extends InputFormat {
/** @internal */
async _canReadInput(input: Input) {
let slice = input._reader.requestSlice(0, 12);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
const riffType = readAscii(slice, 4);
@@ -416,7 +416,7 @@ export class OggInputFormat extends InputFormat {
/** @internal */
async _canReadInput(input: Input) {
let slice = input._reader.requestSlice(0, 4);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
return readAscii(slice, 4) === 'OggS';
@@ -451,7 +451,7 @@ export class FlacInputFormat extends InputFormat {
// There might be ID3v2 headers at the start, skip 'em
while (true) {
let slice = input._reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const id3V2Header = readId3V2Header(slice);
@@ -463,7 +463,7 @@ export class FlacInputFormat extends InputFormat {
}
let slice = input._reader.requestSlice(currentPos, 4);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
return readAscii(slice, 4) === 'fLaC';
@@ -498,7 +498,7 @@ export class AdtsInputFormat extends InputFormat {
while (true) {
let slice = input._reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const id3V2Header = readId3V2Header(slice);
@@ -514,7 +514,7 @@ export class AdtsInputFormat extends InputFormat {
MIN_ADTS_FRAME_HEADER_SIZE,
MAX_ADTS_FRAME_HEADER_SIZE,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
const firstHeader = readAdtsFrameHeader(slice);
@@ -529,7 +529,7 @@ export class AdtsInputFormat extends InputFormat {
MIN_ADTS_FRAME_HEADER_SIZE,
MAX_ADTS_FRAME_HEADER_SIZE,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
const secondHeader = readAdtsFrameHeader(slice);
@@ -573,7 +573,7 @@ export class MpegTsInputFormat extends InputFormat {
async _canReadInput(input: Input) {
const lengthToCheck = TS_PACKET_SIZE + 16 + 1;
let slice = input._reader.requestSlice(0, lengthToCheck);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
const bytes = readBytes(slice, lengthToCheck);
@@ -618,7 +618,7 @@ export class HlsInputFormat extends InputFormat {
/** @internal */
async _canReadInput(input: Input) {
let slice = input._reader.requestSlice(0, 7);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return false;
const isM3u8 = readAscii(slice, 7) === '#EXTM3U';
+9 -9
View File
@@ -12,7 +12,7 @@ import { customAudioDecoders, customVideoDecoders } from './custom-coder';
import { Input } from './input';
import { Logging } from './logging';
import { EncodedPacketSink, PacketRetrievalOptions } from './media-sink';
import { assert, MaybePromise, Rational, Rotation, roundToDivisor, simplifyRational } from './misc';
import { assert, isThenable, MaybePromise, Rational, Rotation, roundToDivisor, simplifyRational } from './misc';
import { TrackType } from './output';
import { EncodedPacket, PacketType } from './packet';
import { TrackDisposition } from './metadata';
@@ -528,7 +528,7 @@ export abstract class InputTrack {
}
const requireSync = <T>(value: MaybePromise<T>, getterName: string, asyncName: string): T => {
if (value instanceof Promise) {
if (isThenable(value)) {
throw new Error(
`'${getterName}' is deprecated and not available synchronously for this track. Use the preferred`
+ ` '${asyncName}()' instead.`,
@@ -554,7 +554,7 @@ const toValidatedPredicate = <T extends InputTrack>(
};
const result = predicate(track);
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then(handle);
}
return handle(result);
@@ -1225,7 +1225,7 @@ export const toValidatedInputTrackQuery = <T extends InputTrack>(
};
const result = query.filter!(track);
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then(handle);
} else {
return handle(result);
@@ -1248,7 +1248,7 @@ export const toValidatedInputTrackQuery = <T extends InputTrack>(
};
const result = query.sortBy!(track);
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then(handle);
} else {
return handle(result);
@@ -1274,7 +1274,7 @@ export const mergeInputTrackQueries = <T extends InputTrack>(
return queryB?.filter?.(track) ?? true;
};
if (resultA instanceof Promise) {
if (isThenable(resultA)) {
return resultA.then(handleResultA);
} else {
return handleResultA(resultA);
@@ -1294,7 +1294,7 @@ export const mergeInputTrackQueries = <T extends InputTrack>(
];
};
if (resultA instanceof Promise || resultB instanceof Promise) {
if (isThenable(resultA) || isThenable(resultB)) {
return Promise.all([resultA, resultB]).then(([resultA, resultB]) => {
return join(resultA, resultB);
});
@@ -1313,7 +1313,7 @@ export const queryInputTracks = async <T extends InputTrack>(
let matched = tracks;
if (query?.filter) {
const filterMatches = tracks.map(t => query.filter!(t));
const hasAsyncFilter = filterMatches.some(x => x instanceof Promise);
const hasAsyncFilter = filterMatches.some(x => isThenable(x));
if (hasAsyncFilter) {
// eslint-disable-next-line @typescript-eslint/await-thenable
const resolvedFilterMatches = await Promise.all(filterMatches);
@@ -1328,7 +1328,7 @@ export const queryInputTracks = async <T extends InputTrack>(
}
const sortValues = matched.map(t => query.sortBy!(t));
const hasAsyncSort = sortValues.some(x => x instanceof Promise);
const hasAsyncSort = sortValues.some(x => isThenable(x));
const resolvedSortValues = hasAsyncSort
// eslint-disable-next-line @typescript-eslint/await-thenable
? await Promise.all(sortValues)
+12 -11
View File
@@ -58,6 +58,7 @@ import {
COLOR_PRIMARIES_MAP_INVERSE,
findLastIndex,
isIso639Dash2LanguageCode,
isThenable,
last,
MATRIX_COEFFICIENTS_MAP_INVERSE,
normalizeRotation,
@@ -364,7 +365,7 @@ export class IsobmffDemuxer extends Demuxer {
while (true) {
let slice = this.reader.requestSliceRange(currentPos, MIN_BOX_HEADER_SIZE, MAX_BOX_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const startPos = currentPos;
@@ -380,7 +381,7 @@ export class IsobmffDemuxer extends Demuxer {
// Found moov, load it
let moovSlice = this.reader.requestSlice(slice.filePos, boxInfo.contentSize);
if (moovSlice instanceof Promise) moovSlice = await moovSlice;
if (isThenable(moovSlice)) moovSlice = await moovSlice;
if (!moovSlice) break;
this.moovSlice = moovSlice;
@@ -431,7 +432,7 @@ export class IsobmffDemuxer extends Demuxer {
// The last 4 bytes may contain the size of the mfra box at the end of the file
let lastWordSlice = this.reader.requestSlice(this.reader.fileSize - 4, 4);
if (lastWordSlice instanceof Promise) lastWordSlice = await lastWordSlice;
if (isThenable(lastWordSlice)) lastWordSlice = await lastWordSlice;
assert(lastWordSlice);
const lastWord = readU32Be(lastWordSlice);
@@ -443,7 +444,7 @@ export class IsobmffDemuxer extends Demuxer {
MIN_BOX_HEADER_SIZE,
MAX_BOX_HEADER_SIZE,
);
if (mfraHeaderSlice instanceof Promise) mfraHeaderSlice = await mfraHeaderSlice;
if (isThenable(mfraHeaderSlice)) mfraHeaderSlice = await mfraHeaderSlice;
if (mfraHeaderSlice) {
const boxInfo = readBoxHeader(mfraHeaderSlice);
@@ -451,7 +452,7 @@ export class IsobmffDemuxer extends Demuxer {
if (boxInfo && boxInfo.name === 'mfra') {
// We found the mfra box, allowing for much better random access. Let's parse it.
let mfraSlice = this.reader.requestSlice(mfraHeaderSlice.filePos, boxInfo.contentSize);
if (mfraSlice instanceof Promise) mfraSlice = await mfraSlice;
if (isThenable(mfraSlice)) mfraSlice = await mfraSlice;
if (mfraSlice) {
this.readContiguousBoxes(mfraSlice);
@@ -678,14 +679,14 @@ export class IsobmffDemuxer extends Demuxer {
}
let headerSlice = this.reader.requestSliceRange(startPos, MIN_BOX_HEADER_SIZE, MAX_BOX_HEADER_SIZE);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
assert(headerSlice);
const moofBoxInfo = readBoxHeader(headerSlice);
assert(moofBoxInfo?.name === 'moof');
let entireSlice = this.reader.requestSlice(startPos, moofBoxInfo.totalSize);
if (entireSlice instanceof Promise) entireSlice = await entireSlice;
if (isThenable(entireSlice)) entireSlice = await entireSlice;
assert(entireSlice);
this.traverseBox(entireSlice);
@@ -3144,7 +3145,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
sampleInfo.sampleOffset,
sampleInfo.sampleSize,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null; // Data is outside
}
@@ -3207,7 +3208,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
fragmentSample.byteOffset,
fragmentSample.byteSize,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null; // Data is outside
}
@@ -3321,7 +3322,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
// Load the header
let slice = demuxer.reader.requestSliceRange(currentPos, MIN_BOX_HEADER_SIZE, MAX_BOX_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const boxStartPos = currentPos;
@@ -3748,7 +3749,7 @@ const resolveEncryptionAuxInfo = async (
}
let slice = reader.requestSlice(aux.offset, totalSize);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
throw new Error('Failed to read auxiliary encryption info.');
}
+3 -3
View File
@@ -7,7 +7,7 @@
*/
import { MediaCodec } from '../codec';
import { assert, assertNever, textDecoder, textEncoder } from '../misc';
import { assert, assertNever, isThenable, textDecoder, textEncoder } from '../misc';
import { FileSlice, readBytes, Reader, readF32Be, readF64Be, readU8 } from '../reader';
import { Writer } from '../writer';
@@ -688,7 +688,7 @@ export const searchForNextElementId = async (
while (until === null || currentPos < until) {
let slice = reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const elementHeader = readElementHeader(slice);
@@ -716,7 +716,7 @@ export const resync = async (reader: Reader, startPos: number, ids: EBMLId[], un
while (currentPos < until) {
let slice = reader.requestSliceRange(currentPos, 0, Math.min(CHUNK_SIZE, until - currentPos));
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
if (slice.length < MAX_VAR_INT_SIZE) break;
+14 -13
View File
@@ -42,6 +42,7 @@ import {
COLOR_PRIMARIES_MAP_INVERSE,
findLastIndex,
isIso639Dash2LanguageCode,
isThenable,
last,
MATRIX_COEFFICIENTS_MAP_INVERSE,
normalizeRotation,
@@ -334,7 +335,7 @@ export class MatroskaDemuxer extends Demuxer {
// Loop over all top-level elements in the file
while (true) {
let slice = this.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const header = readElementHeader(slice);
@@ -350,7 +351,7 @@ export class MatroskaDemuxer extends Demuxer {
assertDefinedSize(size);
let slice = this.reader.requestSlice(dataStartPos, size);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
this.readContiguousElements(slice);
@@ -433,7 +434,7 @@ export class MatroskaDemuxer extends Demuxer {
while (this.currentSegment.elementEndPos === null || currentPos < this.currentSegment.elementEndPos) {
let slice = this.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const elementStartPos = currentPos;
@@ -468,7 +469,7 @@ export class MatroskaDemuxer extends Demuxer {
assertDefinedSize(size);
let slice = this.reader.requestSlice(dataStartPos, size);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (slice) {
this.readContiguousElements(slice);
@@ -484,7 +485,7 @@ export class MatroskaDemuxer extends Demuxer {
assertDefinedSize(size);
let slice = this.reader.requestSlice(dataStartPos, size);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (slice) {
this.readContiguousElements(slice);
@@ -519,7 +520,7 @@ export class MatroskaDemuxer extends Demuxer {
MIN_HEADER_SIZE,
MAX_HEADER_SIZE,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) continue;
const header = readElementHeader(slice);
@@ -533,7 +534,7 @@ export class MatroskaDemuxer extends Demuxer {
this.currentSegment[target.flag] = true;
let dataSlice = this.reader.requestSlice(slice.filePos, size);
if (dataSlice instanceof Promise) dataSlice = await dataSlice;
if (isThenable(dataSlice)) dataSlice = await dataSlice;
if (!dataSlice) continue;
this.readContiguousElements(dataSlice);
@@ -608,7 +609,7 @@ export class MatroskaDemuxer extends Demuxer {
}
let headerSlice = this.reader.requestSliceRange(startPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
assert(headerSlice);
const elementStartPos = startPos;
@@ -637,7 +638,7 @@ export class MatroskaDemuxer extends Demuxer {
// Load the entire cluster
let dataSlice = this.reader.requestSlice(dataStartPos, size);
if (dataSlice instanceof Promise) dataSlice = await dataSlice;
if (isThenable(dataSlice)) dataSlice = await dataSlice;
const cluster: Cluster = {
segment,
@@ -894,7 +895,7 @@ export class MatroskaDemuxer extends Demuxer {
MIN_HEADER_SIZE,
MAX_HEADER_SIZE,
);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) continue;
const header = readElementHeader(slice);
@@ -907,7 +908,7 @@ export class MatroskaDemuxer extends Demuxer {
this.currentSegment = segment;
let dataSlice = this.reader.requestSlice(slice.filePos, size);
if (dataSlice instanceof Promise) dataSlice = await dataSlice;
if (isThenable(dataSlice)) dataSlice = await dataSlice;
if (dataSlice) {
this.readContiguousElements(dataSlice);
}
@@ -2347,7 +2348,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
// Load the header
let slice = demuxer.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const elementStartPos = currentPos;
@@ -2418,7 +2419,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
// the first segment.
let slice = demuxer.reader.requestSliceRange(endPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const elementId = readElementId(slice);
+3 -2
View File
@@ -28,6 +28,7 @@ import {
clamp,
clearIntervalUnthrottled,
floorToDivisor,
isThenable,
last,
missingWebCodecsClassMessage,
promiseWithResolvers,
@@ -426,7 +427,7 @@ class VideoEncoderWrapper {
// Apply the user-defined process function, if any
if (config.transform?.process) {
let processed = config.transform.process(videoSample);
if (processed instanceof Promise) {
if (isThenable(processed)) {
processed = await processed;
}
@@ -1937,7 +1938,7 @@ class AudioEncoderWrapper {
if (config.transform?.process) {
try {
let processed = config.transform.process(audioSample);
if (processed instanceof Promise) {
if (isThenable(processed)) {
processed = await processed;
}
+14
View File
@@ -738,6 +738,20 @@ export const missingWebCodecsClassMessage = (className: string) => {
*/
export type MaybePromise<T> = T | Promise<T>;
const NativePromiseConstructor = /* #__PURE__ */ (async () => {})().constructor as PromiseConstructor;
/**
* Needed to properly deal with custom Promise implementations and because this is closer to how the JS spec does it.
*/
export const isThenable = <T>(value: MaybePromise<T>): value is Promise<T> => {
if (value instanceof NativePromiseConstructor || value instanceof Promise) {
return true;
}
// Fall back to a crude duck typing check
return typeof (value as PromiseLike<T> | null | undefined)?.then === 'function';
};
/** Acts like `??` except the condition is -1 and not null/undefined. */
export const coalesceIndex = (a: number, b: number) => {
return a !== -1 ? a : b;
+8 -7
View File
@@ -17,6 +17,7 @@ import {
AsyncMutex,
binarySearchExact,
binarySearchLessOrEqual,
isThenable,
toDataView,
UNDETERMINED_LANGUAGE,
} from '../misc';
@@ -102,7 +103,7 @@ export class Mp3Demuxer extends Demuxer {
// Let's skip all ID3v2 tags at the start of the file
while (true) {
let slice = this.reader.requestSlice(this.lastLoadedPos, ID3_V2_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
this.lastSampleLoaded = true;
@@ -136,7 +137,7 @@ export class Mp3Demuxer extends Demuxer {
const xingOffset = getXingOffset(header.mpegVersionId, header.channel);
let slice = this.reader.requestSlice(result.startPos + xingOffset, 4);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (slice) {
const word = readU32Be(slice);
const isXing = word === XING || word === INFO;
@@ -151,7 +152,7 @@ export class Mp3Demuxer extends Demuxer {
if (!this.xingData) {
let xingDataSlice = this.reader.requestSlice(result.startPos + xingOffset + 4, 12);
if (xingDataSlice instanceof Promise) xingDataSlice = await xingDataSlice;
if (isThenable(xingDataSlice)) xingDataSlice = await xingDataSlice;
if (xingDataSlice) {
const xingData = readBytes(xingDataSlice, 12);
const view = toDataView(xingData);
@@ -216,7 +217,7 @@ export class Mp3Demuxer extends Demuxer {
while (true) {
let headerSlice = this.reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
if (!headerSlice) break;
const id3V2Header = readId3V2Header(headerSlice);
@@ -227,7 +228,7 @@ export class Mp3Demuxer extends Demuxer {
id3V2HeaderFound = true;
let contentSlice = this.reader.requestSlice(headerSlice.filePos, id3V2Header.size);
if (contentSlice instanceof Promise) contentSlice = await contentSlice;
if (isThenable(contentSlice)) contentSlice = await contentSlice;
if (!contentSlice) break;
parseId3V2Tag(contentSlice, id3V2Header, this.metadataTags);
@@ -238,7 +239,7 @@ export class Mp3Demuxer extends Demuxer {
if (!id3V2HeaderFound && this.reader.fileSize !== null && this.reader.fileSize >= ID3_V1_TAG_SIZE) {
// Try reading an ID3v1 tag at the end of the file
let slice = this.reader.requestSlice(this.reader.fileSize - ID3_V1_TAG_SIZE, ID3_V1_TAG_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
assert(slice);
const tag = readAscii(slice, 3);
@@ -388,7 +389,7 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
data = PLACEHOLDER_DATA;
} else {
let slice = this.demuxer.reader.requestSlice(rawSample.dataStart, rawSample.dataSize);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null; // Data didn't fit into the rest of the file
+2 -1
View File
@@ -7,6 +7,7 @@
*/
import { MP3_FRAME_HEADER_SIZE, getMp3ChannelCount, Mp3FrameHeader, readMp3FrameHeader } from '../../shared/mp3-misc';
import { isThenable } from '../misc';
import { Reader, readU32Be } from '../reader';
export const readNextMp3FrameHeader = async (
@@ -27,7 +28,7 @@ export const readNextMp3FrameHeader = async (
: CHUNK_SIZE;
let slice = reader.requestSliceRange(currentPos, MP3_FRAME_HEADER_SIZE, maxLength);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice || slice.length < MP3_FRAME_HEADER_SIZE) break;
while (slice.remainingLength >= MP3_FRAME_HEADER_SIZE) {
+18 -17
View File
@@ -63,6 +63,7 @@ import {
COLOR_PRIMARIES_MAP_INVERSE,
findLastIndex,
floorToMultiple,
isThenable,
last,
MATRIX_COEFFICIENTS_MAP_INVERSE,
readExpGolomb,
@@ -190,7 +191,7 @@ export class MpegTsDemuxer extends Demuxer {
return this.metadataPromise ??= (async () => {
const lengthToCheck = TS_PACKET_SIZE + 16 + 1;
let startingSlice = this.reader.requestSlice(0, lengthToCheck);
if (startingSlice instanceof Promise) startingSlice = await startingSlice;
if (isThenable(startingSlice)) startingSlice = await startingSlice;
assert(startingSlice);
const startingBytes = readBytes(startingSlice, lengthToCheck);
@@ -951,7 +952,7 @@ export class MpegTsDemuxer extends Demuxer {
async readPacketHeader(pos: number): Promise<TsPacketHeader | null> {
let slice = this.reader.requestSlice(pos, 4);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null;
@@ -987,7 +988,7 @@ export class MpegTsDemuxer extends Demuxer {
async readPacket(pos: number): Promise<TsPacket | null> {
// Code in here is duplicated from readPacketHeader for performance reasons
let slice = this.reader.requestSlice(pos, TS_PACKET_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null;
@@ -2099,7 +2100,7 @@ class PacketReadingContext {
while (true) {
let remaining = this.ensureBuffered(CHUNK_SIZE);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
if (remaining === 0) {
break;
@@ -2253,7 +2254,7 @@ class PacketReadingContext {
while (true) {
let remaining = this.ensureBuffered(CHUNK_SIZE);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
const startPos = this.currentPos;
@@ -2269,7 +2270,7 @@ class PacketReadingContext {
const possibleHeaderStartPos = this.currentPos;
let remaining = this.ensureBuffered(MAX_ADTS_FRAME_HEADER_SIZE);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
if (remaining < MAX_ADTS_FRAME_HEADER_SIZE) {
return;
@@ -2282,7 +2283,7 @@ class PacketReadingContext {
this.seekTo(possibleHeaderStartPos);
let remaining = this.ensureBuffered(header.frameLength);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
return this.supplyPacket(
remaining,
@@ -2300,7 +2301,7 @@ class PacketReadingContext {
const possibleHeaderStartPos = this.currentPos;
let remaining = this.ensureBuffered(MP3_FRAME_HEADER_SIZE);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
if (remaining < MP3_FRAME_HEADER_SIZE) {
return;
@@ -2314,7 +2315,7 @@ class PacketReadingContext {
this.seekTo(possibleHeaderStartPos);
let remaining = this.ensureBuffered(result.header.totalSize);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
const duration = result.header.audioSamplesInFrame * TIMESCALE
/ elementaryStream.info.sampleRate;
@@ -2332,7 +2333,7 @@ class PacketReadingContext {
// Need at least 5 bytes for sync word + CRC + fscod/frmsizecod
let remaining = this.ensureBuffered(5);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
if (remaining < 5) {
return;
@@ -2361,7 +2362,7 @@ class PacketReadingContext {
this.seekTo(possibleSyncPos);
remaining = this.ensureBuffered(frameSize);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
const duration = Math.round(
AC3_SAMPLES_PER_FRAME * TIMESCALE / elementaryStream.info.sampleRate,
@@ -2377,7 +2378,7 @@ class PacketReadingContext {
// Need at least 5 bytes for E-AC-3 header parsing (sync word + frmsiz + fscod/numblkscod)
let remaining = this.ensureBuffered(5);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
if (remaining < 5) {
return;
@@ -2399,7 +2400,7 @@ class PacketReadingContext {
this.seekTo(possibleSyncPos);
remaining = this.ensureBuffered(frameSize);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
// Duration = numblks * 256 samples per block
const samplesPerFrame = numblks * 256;
@@ -2416,7 +2417,7 @@ class PacketReadingContext {
const possibleSyncPos = this.currentPos;
let remaining = this.ensureBuffered(DTS_CORE_FRAME_HEADER_SIZE);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
if (remaining < DTS_CORE_FRAME_HEADER_SIZE) {
return;
@@ -2438,7 +2439,7 @@ class PacketReadingContext {
const headerBound = Math.min(leadingExss.frameSize, DTS_EXSS_MAX_HEADER_SIZE);
let remaining = this.ensureBuffered(headerBound);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
leadingExss = parseDtsExssHeader(this.readBytes(remaining)) ?? leadingExss;
}
@@ -2456,7 +2457,7 @@ class PacketReadingContext {
const neededBytes = nextSubstreamPos + DTS_EXSS_HEADER_PREFIX_SIZE;
let remaining = this.ensureBuffered(neededBytes);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
if (remaining < neededBytes) {
break;
@@ -2484,7 +2485,7 @@ class PacketReadingContext {
this.seekTo(possibleSyncPos);
remaining = this.ensureBuffered(frameSize);
if (remaining instanceof Promise) remaining = await remaining;
if (isThenable(remaining)) remaining = await remaining;
const duration = Math.round(
sampleCount * TIMESCALE / elementaryStream.info.sampleRate,
+9 -8
View File
@@ -18,6 +18,7 @@ import {
AsyncMutex,
binarySearchLessOrEqual,
findLast,
isThenable,
last,
roundIfAlmostInteger,
toDataView,
@@ -72,7 +73,7 @@ export class OggDemuxer extends Demuxer {
while (true) {
let slice = this.reader.requestSliceRange(currentPos, MIN_PAGE_HEADER_SIZE, MAX_PAGE_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const page = readPageHeader(slice);
@@ -274,7 +275,7 @@ export class OggDemuxer extends Demuxer {
while (true) {
// Load the entire page data
let pageSlice = this.reader.requestSlice(currentPage.dataStartPos, currentPage.dataSize);
if (pageSlice instanceof Promise) pageSlice = await pageSlice;
if (isThenable(pageSlice)) pageSlice = await pageSlice;
assert(pageSlice);
const pageData = readBytes(pageSlice, currentPage.dataSize);
@@ -299,7 +300,7 @@ export class OggDemuxer extends Demuxer {
let currentPos = currentPage.headerStartPos + currentPage.totalSize;
while (true) {
let headerSlice = this.reader.requestSliceRange(currentPos, MIN_PAGE_HEADER_SIZE, MAX_PAGE_HEADER_SIZE);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
if (!headerSlice) {
return null;
}
@@ -358,7 +359,7 @@ export class OggDemuxer extends Demuxer {
let currentPos = lastPacket.endPage.headerStartPos + lastPacket.endPage.totalSize;
while (true) {
let slice = this.reader.requestSliceRange(currentPos, MIN_PAGE_HEADER_SIZE, MAX_PAGE_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null;
}
@@ -658,7 +659,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
);
let searchSlice = this.demuxer.reader.requestSlice(searchStartPos, until - searchStartPos);
if (searchSlice instanceof Promise) searchSlice = await searchSlice;
if (isThenable(searchSlice)) searchSlice = await searchSlice;
assert(searchSlice);
const found = findNextPageHeader(searchSlice, until);
@@ -672,7 +673,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
MIN_PAGE_HEADER_SIZE,
MAX_PAGE_HEADER_SIZE,
);
if (headerSlice instanceof Promise) headerSlice = await headerSlice;
if (isThenable(headerSlice)) headerSlice = await headerSlice;
assert(headerSlice);
const page = readPageHeader(headerSlice);
@@ -685,7 +686,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
pageValid = true;
} else {
let pageSlice = this.demuxer.reader.requestSlice(page.headerStartPos, page.totalSize);
if (pageSlice instanceof Promise) pageSlice = await pageSlice;
if (isThenable(pageSlice)) pageSlice = await pageSlice;
assert(pageSlice);
// Validate the page by checking checksum
@@ -759,7 +760,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
const nextPos = currentPage.headerStartPos + currentPage.totalSize;
let slice = this.demuxer.reader.requestSliceRange(nextPos, MIN_PAGE_HEADER_SIZE, MAX_PAGE_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
assert(slice);
const nextPage = readPageHeader(slice);
+13 -4
View File
@@ -6,7 +6,16 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { assert, AsyncMutex, EventEmitter, isIso639Dash2LanguageCode, MaybePromise, Rotation, toArray } from './misc';
import {
assert,
AsyncMutex,
EventEmitter,
isIso639Dash2LanguageCode,
isThenable,
MaybePromise,
Rotation,
toArray,
} from './misc';
import { MetadataTags, TrackDisposition, validateMetadataTags, validateTrackDisposition } from './metadata';
import { Muxer } from './muxer';
import { OutputFormat } from './output-format';
@@ -451,7 +460,7 @@ export class Output<
}
const rootTargetResult = this._getRootTarget();
if (rootTargetResult instanceof Promise) {
if (isThenable(rootTargetResult)) {
throw new TypeError(errorMessage);
}
@@ -516,7 +525,7 @@ export class Output<
return result;
};
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then(handleResult);
} else {
return handleResult(result);
@@ -604,7 +613,7 @@ export class Output<
return target;
};
if (result instanceof Promise) {
if (isThenable(result)) {
return this._rootTargetPromise = result.then(handleResult);
} else {
return handleResult(result);
+4 -4
View File
@@ -7,7 +7,7 @@
*/
import { InputDisposedError } from './input';
import { assert, clamp, getUint24, MaybePromise, textDecoder, toDataView } from './misc';
import { assert, clamp, getUint24, isThenable, MaybePromise, textDecoder, toDataView } from './misc';
import { DEFAULT_MAX_READ_POSITION, DEFAULT_MIN_READ_POSITION, Source } from './source';
export class Reader {
@@ -47,7 +47,7 @@ export class Reader {
const end = start + length;
const result = this.source._read(start, end, DEFAULT_MIN_READ_POSITION, DEFAULT_MAX_READ_POSITION);
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then((x) => {
if (!x) {
return null;
@@ -95,7 +95,7 @@ export class Reader {
);
};
if (promisedAttempt instanceof Promise) {
if (isThenable(promisedAttempt)) {
return promisedAttempt.then(handleAttempt);
} else {
return handleAttempt(promisedAttempt);
@@ -121,7 +121,7 @@ export class Reader {
}
let slice = this.requestSliceRange(currentSize, 0, CHUNK_SIZE);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice || slice.length === 0) {
break;
+4 -3
View File
@@ -11,6 +11,7 @@ import {
clamp,
COLOR_PRIMARIES_MAP,
isAllowSharedBufferSource,
isThenable,
MATRIX_COEFFICIENTS_MAP,
Rotation,
SECOND_TO_MICROSECOND_FACTOR,
@@ -864,7 +865,7 @@ export class VideoSample implements Disposable {
if (this._data instanceof VideoSampleResource) {
let result = this._data.getDataPlanes();
if (result instanceof Promise) result = await result;
if (isThenable(result)) result = await result;
if (
!Array.isArray(result)
@@ -1022,7 +1023,7 @@ export class VideoSample implements Disposable {
}
const planes = this._data.getDataPlanes();
if (planes instanceof Promise) {
if (isThenable(planes)) {
throw new Error(
'Cannot convert a VideoSampleResource-backed VideoSample to VideoFrame if getDataPlanes() returns'
+ ' a promise.',
@@ -1586,7 +1587,7 @@ export class VideoSample implements Disposable {
// Description's finalized; let's see if a registered transformer wants to handle it
for (const transformer of registeredVideoSampleTransformers) {
let result = transformer(this, description);
if (result instanceof Promise) result = await result;
if (isThenable(result)) result = await result;
if (result !== null) {
return result;
+8 -7
View File
@@ -14,6 +14,7 @@ import {
closedIntervalsOverlap,
FilePath,
isNumber,
isThenable,
isWebKit,
MaybePromise,
mergeRequestInit,
@@ -328,7 +329,7 @@ export abstract class PathedSource extends Source {
return ref;
};
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then(handle);
} else {
return handle(result);
@@ -387,7 +388,7 @@ export class CustomPathedSource extends PathedSource {
return ref;
};
if (result instanceof Promise) {
if (isThenable(result)) {
this._rootRequest = result.then(handle);
} else {
handle(result);
@@ -894,7 +895,7 @@ export class UrlSource extends PathedSource {
return result;
};
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then(processResult);
} else {
return processResult(result);
@@ -1198,7 +1199,7 @@ export class UrlSource extends PathedSource {
for (const slice of uniqueSlices) {
const result = backing._read(slice.start, slice.start + slice.bytes.length);
if (result instanceof Promise) {
if (isThenable(result)) {
result.then((readResult) => {
if (readResult) {
// The backing's cache is empty at this point, so the read is guaranteed to produce
@@ -1459,7 +1460,7 @@ export class CustomSource extends Source {
const result = this._options.getSize();
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then((size) => {
if (!Number.isInteger(size) || size < 0) {
throw new TypeError('options.getSize must return or resolve to a non-negative integer.');
@@ -1485,7 +1486,7 @@ export class CustomSource extends Source {
const originalTargetPos = worker.targetPos;
let data = this._options.read(worker.currentPos, originalTargetPos);
if (data instanceof Promise) data = await data;
if (isThenable(data)) data = await data;
if (worker.aborted) {
break;
@@ -2706,7 +2707,7 @@ export class RangedSource extends Source {
return result;
};
if (result instanceof Promise) {
if (isThenable(result)) {
return result.then(processResult);
} else {
return processResult(result);
+9 -9
View File
@@ -12,7 +12,7 @@ import { Input } from '../input';
import { InputAudioTrackBacking } from '../input-track';
import { PacketRetrievalOptions } from '../media-sink';
import { DEFAULT_TRACK_DISPOSITION, MetadataTags } from '../metadata';
import { assert, UNDETERMINED_LANGUAGE } from '../misc';
import { assert, isThenable, UNDETERMINED_LANGUAGE } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { readAscii, readBytes, Reader, readU16, readU32, readU64 } from '../reader';
import { ID3_V2_HEADER_SIZE, parseId3V2Tag, readId3V2Header } from '../id3';
@@ -52,7 +52,7 @@ export class WaveDemuxer extends Demuxer {
async readMetadata() {
return this.metadataPromise ??= (async () => {
let slice = this.reader.requestSlice(0, 12);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
assert(slice);
const riffType = readAscii(slice, 4);
@@ -77,7 +77,7 @@ export class WaveDemuxer extends Demuxer {
while (totalFileSize === null || currentPos < totalFileSize) {
let slice = this.reader.requestSlice(currentPos, 8);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) break;
const chunkId = readAscii(slice, 4);
@@ -103,7 +103,7 @@ export class WaveDemuxer extends Demuxer {
// File and data chunk sizes are defined in here instead
let ds64Slice = this.reader.requestSlice(startPos, chunkSize);
if (ds64Slice instanceof Promise) ds64Slice = await ds64Slice;
if (isThenable(ds64Slice)) ds64Slice = await ds64Slice;
if (!ds64Slice) break;
const riffChunkSize = readU64(ds64Slice, littleEndian);
@@ -136,7 +136,7 @@ export class WaveDemuxer extends Demuxer {
private async parseFmtChunk(startPos: number, size: number, littleEndian: boolean) {
let slice = this.reader.requestSlice(startPos, size);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return; // File too short
let formatTag = readU16(slice, littleEndian);
@@ -206,7 +206,7 @@ export class WaveDemuxer extends Demuxer {
private async parseListChunk(startPos: number, size: number, littleEndian: boolean) {
let slice = this.reader.requestSlice(startPos, size);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return; // File too short
const infoType = readAscii(slice, 4);
@@ -303,7 +303,7 @@ export class WaveDemuxer extends Demuxer {
private async parseId3Chunk(startPos: number, size: number) {
// Parse ID3 tag embedded in WAV file (non-default, but used a lot in practice anyway)
let slice = this.reader.requestSlice(startPos, size);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) return; // File too short
const id3V2Header = readId3V2Header(slice);
@@ -489,7 +489,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
// requested slice actually exists.
let slice = this.demuxer.reader.requestSlice(this.demuxer.dataStart + startOffset, sizeInBytes);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
if (!slice) {
return null;
@@ -501,7 +501,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
data = PLACEHOLDER_DATA;
} else {
let slice = this.demuxer.reader.requestSlice(this.demuxer.dataStart + startOffset, sizeInBytes);
if (slice instanceof Promise) slice = await slice;
if (isThenable(slice)) slice = await slice;
assert(slice);
data = readBytes(slice, sizeInBytes);