* Returns a Writer for pushing data to this stream incrementally. * Only available when no body source was provided at creation time * or via setBody(). Non-writable streams return an already-closed Writer. * @type {object}
()
| 2114 | * @type {object} |
| 2115 | */ |
| 2116 | get writer() { |
| 2117 | assertIsQuicStream(this); |
| 2118 | const inner = this.#inner; |
| 2119 | if (inner.writer !== undefined) return inner.writer; |
| 2120 | if (inner.outboundSet) { |
| 2121 | throw new ERR_INVALID_STATE( |
| 2122 | 'Stream outbound already configured with a body source'); |
| 2123 | } |
| 2124 | |
| 2125 | const handle = this.#handle; |
| 2126 | const stream = this; |
| 2127 | let closed = false; |
| 2128 | let errored = false; |
| 2129 | let error = null; |
| 2130 | let totalBytesWritten = 0; |
| 2131 | let drainWakeup = null; |
| 2132 | |
| 2133 | // Drain callback - C++ fires this when send buffer has space |
| 2134 | stream[kDrain] = () => { |
| 2135 | if (drainWakeup) { |
| 2136 | drainWakeup.resolve(true); |
| 2137 | drainWakeup = null; |
| 2138 | } |
| 2139 | }; |
| 2140 | |
| 2141 | // A note on backpressure handling: per the stream/iter spec, the default |
| 2142 | // backpressure policy for writers is strict, meaning that if the stream |
| 2143 | // signals backpressure additional writes are rejected until the buffer has |
| 2144 | // capacity again. |
| 2145 | |
| 2146 | function writeSync(chunk) { |
| 2147 | // If the stream is closed, errored, or write-ended, we cannot accept |
| 2148 | // more data. Refuse the sync write. |
| 2149 | // If a drain is already pending, another operation is waiting |
| 2150 | // for capacity. Refuse the sync write. |
| 2151 | if (closed || errored || stream.#inner.state.writeEnded || drainWakeup != null) { |
| 2152 | return false; |
| 2153 | } |
| 2154 | chunk = toUint8Array(chunk); |
| 2155 | const len = TypedArrayPrototypeGetByteLength(chunk); |
| 2156 | if (len === 0) return true; |
| 2157 | // Refuse the write only when there is no available capacity at |
| 2158 | // all. When writeDesiredSize > 0 we allow the write even if the |
| 2159 | // chunk is larger than the remaining capacity -- the C++ side |
| 2160 | // will accept the data into the DataQueue and |
| 2161 | // UpdateWriteDesiredSize() will drop writeDesiredSize toward 0, |
| 2162 | // at which point the standard drain mechanism takes over. |
| 2163 | // This follows the Web Streams model where writes beyond the HWM |
| 2164 | // succeed and backpressure applies to *subsequent* writes. |
| 2165 | if (stream.#inner.state.writeDesiredSize === 0) return false; |
| 2166 | const result = handle.write([chunk]); |
| 2167 | if (result === undefined) return false; |
| 2168 | totalBytesWritten += len; |
| 2169 | return true; |
| 2170 | } |
| 2171 | |
| 2172 | async function write(chunk, options = kEmptyObject) { |
| 2173 | validateObject(options, 'options'); |
no test coverage detected