(options = kEmptyObject)
| 2255 | } |
| 2256 | |
| 2257 | async function end(options = kEmptyObject) { |
| 2258 | validateObject(options, 'options'); |
| 2259 | const { signal } = options; |
| 2260 | if (signal !== undefined) { |
| 2261 | validateAbortSignal(signal, 'options.signal'); |
| 2262 | signal.throwIfAborted(); |
| 2263 | // TODO(@jasnell): The stream/iter spec allows individual sync end |
| 2264 | // calls to be canceled via an AbortSignal. We currently do not support |
| 2265 | // this, but we can add before the impl is graduated from experimental. |
| 2266 | // At most we do here is check for signal abort at the start of the call. |
| 2267 | } |
| 2268 | |
| 2269 | // Per the streams/iter spec, endSync and end follow a try-fallback |
| 2270 | // pattern. That is, callers should try endSync first and if it returns |
| 2271 | // -1, then they should call and await end(). This is a signal that sync |
| 2272 | // end is not currently possible. However, we always support sync end |
| 2273 | // here unless the stream is already errored. |
| 2274 | // While the user should have already called endSync, we call it again |
| 2275 | // here to actually process the end request. At worst it's called twice. |
| 2276 | const n = endSync(); |
| 2277 | |
| 2278 | // A return value of -1 indicates that endSync was not yet able to |
| 2279 | // process the end request, either because we are errored or because we |
| 2280 | // are awaiting drain. If we're errored, throw the error. If we're waiting |
| 2281 | // for drain, await it and then try ending again. |
| 2282 | |
| 2283 | if (n >= 0) return n; |
| 2284 | if (errored) throw error; |
| 2285 | |
| 2286 | drainWakeup ??= PromiseWithResolvers(); |
| 2287 | try { |
| 2288 | await drainWakeup.promise; |
| 2289 | } finally { |
| 2290 | drainWakeup = null; |
| 2291 | } |
| 2292 | return endSync(); |
| 2293 | } |
| 2294 | |
| 2295 | function fail(reason) { |
| 2296 | if (closed || errored) return; |
no test coverage detected