From ee23db6c447a4305269953ad38f1c58d50e16468 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 21 Oct 2026 10:01:40 -0700 Subject: [PATCH] fix(js/qmux): document the exported members the build now requires @moq/qmux landed alongside the doc-comment build check from #6163, and its WebTransport-shaped members had no doc comments, so `bun run build` fails for every JS-touching change on main. Co-Authored-By: Claude Opus 5.5 --- js/qmux/src/error.ts | 4 ++++ js/qmux/src/session.ts | 12 +++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/js/qmux/src/error.ts b/js/qmux/src/error.ts index 56b33ae87c1..d8aaa95d5fa 100644 --- a/js/qmux/src/error.ts +++ b/js/qmux/src/error.ts @@ -10,7 +10,9 @@ * socket error, decode failure, ...). */ export class SessionError extends Error implements Pick { + /** Always `"session"`: the whole session failed, not one stream. */ readonly source = "session" as const; + /** Always `null`: a session failure carries no stream error code. */ readonly streamErrorCode = null; constructor(message: string, options?: { cause?: unknown }) { @@ -28,7 +30,9 @@ export class SessionError extends Error implements Pick { + /** Always `"stream"`: one stream was reset, not the whole session. */ readonly source = "stream" as const; + /** The application error code the reset carried. */ readonly streamErrorCode: number; constructor(code: number, message = "stream reset") { diff --git a/js/qmux/src/session.ts b/js/qmux/src/session.ts index 9f0de0ee1f0..f27e0e99165 100644 --- a/js/qmux/src/session.ts +++ b/js/qmux/src/session.ts @@ -500,6 +500,7 @@ interface StreamFlowState { recvConsumed: bigint; } +/** A `WebTransport` session carried over a WebSocket, for hosts without native WebTransport. */ export default class Session implements WebTransport { // The transport: a native `WebSocketStream` when the platform has one (real // backpressure), otherwise the `WebSocketStream` ponyfill over a plain @@ -531,27 +532,32 @@ export default class Session implements WebTransport { // with the actual version derived from `ws.protocol`. #version: WireFormat = "webtransport"; + #protocol = ""; /** The negotiated application-level subprotocol, or empty string if none. * * The prefix is stripped; this returns only the application protocol name. */ - #protocol = ""; get protocol(): string { return this.#protocol; } + /** Resolves once the WebSocket opens and the session can carry streams. */ readonly ready: Promise; #readyResolve: () => void; #readyReject: (err: Error) => void; + /** Resolves with the close code and reason on a clean close, or rejects with a {@link SessionError}. */ readonly closed: Promise; #closedResolve: (info: WebTransportCloseInfo) => void; #closedReject: (err: Error) => void; + /** Bidirectional streams the peer opens, in arrival order. */ readonly incomingBidirectionalStreams: ReadableStream; #incomingBidirectionalQueue: IncomingStreamQueue; + /** Unidirectional streams the peer opens, in arrival order. */ readonly incomingUnidirectionalStreams: ReadableStream>; #incomingUnidirectionalQueue: IncomingStreamQueue>; + /** Unreliable datagrams sent and received as QMux DATAGRAM frames. */ readonly datagrams = new Datagrams((data) => this.#sendDatagram(data)); // Flow control state @@ -1755,6 +1761,7 @@ export default class Session implements WebTransport { }); } + /** Open a bidirectional stream, waiting for the peer to grant stream credit. */ async createBidirectionalStream(options?: WebTransportSendStreamOptions): Promise { await this.ready; @@ -1834,6 +1841,7 @@ export default class Session implements WebTransport { return { readable: recvStream.readable, writable: writer }; } + /** Open a send-only stream, waiting for the peer to grant stream credit. */ async createUnidirectionalStream(options?: WebTransportSendStreamOptions): Promise> { await this.ready; @@ -2012,6 +2020,7 @@ export default class Session implements WebTransport { void sleep(Nano.fromMilli(Milli(100))).then(() => this.#transportClose()); } + /** Close the session with an application code and reason; a no-op once closed. */ close(info?: { closeCode?: number; reason?: string }) { if (this.#closed) return; const code = info?.closeCode ?? 0; @@ -2033,6 +2042,7 @@ export default class Session implements WebTransport { this.#wss?.setHighWaterMark?.(this.#sendBufferSize); } + /** Always `"default"`: the underlying TCP connection does its own congestion control. */ get congestionControl(): string { return "default"; }