fix: surface StreamTarget write errors instead of swallowing them (#305)

* fix: await StreamTarget writes to prevent overlapping OPFS operations

* no need for flush

* preserve fire and forget writes

* Remove pendingWrites, add missing mutex acquire to ADTS muxer finalize method

---------

Co-authored-by: Vanilagy <[email protected]>
This commit is contained in:
Igor Samokhovets
2026-02-24 11:21:13 +00:00
committed by GitHub
co-authored by Vanilagy
parent 48f9bda91a
commit 31147d6e96
3 changed files with 151 additions and 3 deletions
+4 -1
View File
@@ -111,5 +111,8 @@ export class AdtsMuxer extends Muxer {
throw new Error('ADTS does not support subtitles.');
}
async finalize() {}
async finalize() {
const release = await this.mutex.acquire(); // Required so that finalize() can't resolve before other calls
release();
}
}
+17 -2
View File
@@ -215,6 +215,7 @@ export class StreamTargetWriter extends Writer {
private lastWriteEnd = 0;
private lastFlushEnd = 0;
private writer: WritableStreamDefaultWriter<StreamTargetChunk> | null = null;
private writeError: unknown = null;
// These variables regard chunked mode:
private chunked: boolean;
@@ -267,6 +268,11 @@ export class StreamTargetWriter extends Writer {
}
async flush() {
if (this.writeError !== null) {
// eslint-disable-next-line @typescript-eslint/only-throw-error
throw this.writeError;
}
if (this.pos > this.lastWriteEnd) {
// There's a "void" between the last written byte and the next byte we're about to write. Let's pad that
// void with zeroes explicitly.
@@ -329,11 +335,12 @@ export class StreamTargetWriter extends Writer {
throw new Error('Internal error: Monotonicity violation.');
}
// Write out the data immediately
void this.writer.write({
type: 'write',
data: chunk.data,
position: chunk.start,
}).catch((error) => {
this.writeError ??= error;
});
this.lastFlushEnd = chunk.start + chunk.data.byteLength;
@@ -440,6 +447,8 @@ export class StreamTargetWriter extends Writer {
type: 'write',
data: chunk.data.subarray(section.start, section.end),
position,
}).catch((error) => {
this.writeError ??= error;
});
this.lastFlushEnd = chunk.start + section.end;
@@ -449,12 +458,18 @@ export class StreamTargetWriter extends Writer {
}
}
finalize() {
async finalize() {
if (this.chunked) {
this.tryToFlushChunks(true);
}
if (this.writeError !== null) {
// eslint-disable-next-line @typescript-eslint/only-throw-error
throw this.writeError;
}
assert(this.writer);
await this.writer.ready;
return this.writer.close();
}