// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { Deferred, getDeferred, isWritableStream, isWritableStreamDefaultWriter, isWritableStreamLocked, setPromiseIsHandledToTrue, writableStreamCloseQueuedOrInFlight, writableStreamDefaultWriterAbort, writableStreamDefaultWriterClose, writableStreamDefaultWriterGetDesiredSize, writableStreamDefaultWriterRelease, writableStreamDefaultWriterWrite, } from "./internals.ts"; import * as sym from "./symbols.ts"; import type { WritableStreamImpl } from "./writable_stream.ts"; import { customInspect } from "../console.ts"; import { assert } from "../../util.ts"; import { setFunctionName } from "../util.ts"; export class WritableStreamDefaultWriterImpl implements WritableStreamDefaultWriter { [sym.closedPromise]: Deferred; [sym.ownerWritableStream]: WritableStreamImpl; [sym.readyPromise]: Deferred; constructor(stream: WritableStreamImpl) { if (!isWritableStream(stream)) { throw new TypeError("Invalid stream."); } if (isWritableStreamLocked(stream)) { throw new TypeError("Cannot create a writer for a locked stream."); } this[sym.ownerWritableStream] = stream; stream[sym.writer] = this; const state = stream[sym.state]; if (state === "writable") { if ( !writableStreamCloseQueuedOrInFlight(stream) && stream[sym.backpressure] ) { this[sym.readyPromise] = getDeferred(); } else { this[sym.readyPromise] = { promise: Promise.resolve() }; } this[sym.closedPromise] = getDeferred(); } else if (state === "erroring") { this[sym.readyPromise] = { promise: Promise.reject(stream[sym.storedError]), }; setPromiseIsHandledToTrue(this[sym.readyPromise].promise); this[sym.closedPromise] = getDeferred(); } else if (state === "closed") { this[sym.readyPromise] = { promise: Promise.resolve() }; this[sym.closedPromise] = { promise: Promise.resolve() }; } else { assert(state === "errored"); const storedError = stream[sym.storedError]; this[sym.readyPromise] = { promise: Promise.reject(storedError) }; setPromiseIsHandledToTrue(this[sym.readyPromise].promise); this[sym.closedPromise] = { promise: Promise.reject(storedError) }; setPromiseIsHandledToTrue(this[sym.closedPromise].promise); } } get closed(): Promise { if (!isWritableStreamDefaultWriter(this)) { return Promise.reject( new TypeError("Invalid WritableStreamDefaultWriter.") ); } return this[sym.closedPromise].promise; } get desiredSize(): number | null { if (!isWritableStreamDefaultWriter(this)) { throw new TypeError("Invalid WritableStreamDefaultWriter."); } if (!this[sym.ownerWritableStream]) { throw new TypeError("WritableStreamDefaultWriter has no owner."); } return writableStreamDefaultWriterGetDesiredSize(this); } get ready(): Promise { if (!isWritableStreamDefaultWriter(this)) { return Promise.reject( new TypeError("Invalid WritableStreamDefaultWriter.") ); } return this[sym.readyPromise].promise; } // eslint-disable-next-line @typescript-eslint/no-explicit-any abort(reason: any): Promise { if (!isWritableStreamDefaultWriter(this)) { return Promise.reject( new TypeError("Invalid WritableStreamDefaultWriter.") ); } if (!this[sym.ownerWritableStream]) { Promise.reject( new TypeError("WritableStreamDefaultWriter has no owner.") ); } return writableStreamDefaultWriterAbort(this, reason); } close(): Promise { if (!isWritableStreamDefaultWriter(this)) { return Promise.reject( new TypeError("Invalid WritableStreamDefaultWriter.") ); } const stream = this[sym.ownerWritableStream]; if (!stream) { Promise.reject( new TypeError("WritableStreamDefaultWriter has no owner.") ); } if (writableStreamCloseQueuedOrInFlight(stream)) { Promise.reject( new TypeError("Stream is in an invalid state to be closed.") ); } return writableStreamDefaultWriterClose(this); } releaseLock(): void { if (!isWritableStreamDefaultWriter(this)) { throw new TypeError("Invalid WritableStreamDefaultWriter."); } const stream = this[sym.ownerWritableStream]; if (!stream) { return; } assert(stream[sym.writer]); writableStreamDefaultWriterRelease(this); } write(chunk: W): Promise { if (!isWritableStreamDefaultWriter(this)) { return Promise.reject( new TypeError("Invalid WritableStreamDefaultWriter.") ); } if (!this[sym.ownerWritableStream]) { Promise.reject( new TypeError("WritableStreamDefaultWriter has no owner.") ); } return writableStreamDefaultWriterWrite(this, chunk); } [customInspect](): string { return `${this.constructor.name} { closed: Promise, desiredSize: ${String( this.desiredSize )}, ready: Promise }`; } } setFunctionName(WritableStreamDefaultWriterImpl, "WritableStreamDefaultWriter");