|
4 | 4 | const common = require('../common'); |
5 | 5 |
|
6 | 6 | const assert = require('assert'); |
| 7 | +const { once } = require('events'); |
7 | 8 |
|
8 | 9 | const { |
9 | 10 | newReadableStreamFromStreamReadable, |
10 | 11 | } = require('internal/webstreams/adapters'); |
11 | 12 |
|
12 | 13 | const { |
13 | 14 | Duplex, |
| 15 | + PassThrough, |
14 | 16 | Readable, |
15 | 17 | } = require('stream'); |
16 | 18 |
|
@@ -188,11 +190,75 @@ const { |
188 | 190 | } |
189 | 191 |
|
190 | 192 | { |
191 | | - const readable = new Readable(); |
192 | | - readable.destroy(); |
193 | | - const readableStream = newReadableStreamFromStreamReadable(readable); |
194 | | - const reader = readableStream.getReader(); |
195 | | - reader.closed.then(common.mustCall()); |
| 193 | + /** |
| 194 | + * Runs the same assertion across finalize-before/after and |
| 195 | + * default/BYOB adapter creation orders. |
| 196 | + * @param {(readable: Readable) => void | Promise<void>} finalize |
| 197 | + * Finalizes the source stream before or after adaptation. |
| 198 | + * @param {(readAndAssert: () => Promise<void>, reader: ReadableStreamReader) => Promise<void>} postAssert |
| 199 | + * Asserts the resulting web stream state for the current case. |
| 200 | + */ |
| 201 | + function testConfluence(finalize, postAssert) { |
| 202 | + const cases = [false, true].flatMap((finalizeFirst) => [false, true].map((isBYOB) => ({ finalizeFirst, isBYOB }))); |
| 203 | + Promise.all(cases.map(async (case_) => { |
| 204 | + try { |
| 205 | + const { isBYOB } = case_; |
| 206 | + const readable = new PassThrough(); |
| 207 | + if (case_.finalizeFirst) { |
| 208 | + await finalize(readable); |
| 209 | + } |
| 210 | + /** @type {ReadableStream} */ |
| 211 | + const readableStream = newReadableStreamFromStreamReadable(readable, { type: isBYOB ? 'bytes' : undefined }); |
| 212 | + const reader = readableStream.getReader({ mode: isBYOB ? 'byob' : undefined }); |
| 213 | + if (!case_.finalizeFirst) { |
| 214 | + await finalize(readable); |
| 215 | + } |
| 216 | + |
| 217 | + const readAndAssert = common.mustCall(() => reader.read(isBYOB ? new Uint8Array(1) : undefined).then((result) => { |
| 218 | + assert.deepStrictEqual(result, { value: isBYOB ? new Uint8Array(0) : undefined, done: true }); |
| 219 | + })); |
| 220 | + await postAssert(readAndAssert, reader); |
| 221 | + } catch (cause) { |
| 222 | + throw new Error(`Case failed: ${JSON.stringify(case_)}`, { cause }); |
| 223 | + } |
| 224 | + })).then(common.mustCall()); |
| 225 | + } |
| 226 | + const error = new Error('boom'); |
| 227 | + // Ending the readable without an error => closes the readableStream without an error |
| 228 | + testConfluence( |
| 229 | + async (readable) => { |
| 230 | + readable.resume(); |
| 231 | + readable.end(); |
| 232 | + await once(readable, 'end'); |
| 233 | + }, |
| 234 | + common.mustCall(async (readAndAssert, reader) => { |
| 235 | + await readAndAssert(); |
| 236 | + await reader.closed; |
| 237 | + }, 4) |
| 238 | + ); |
| 239 | + // Prematurely destroying the stream.Readable without an error |
| 240 | + // => errors the ReadableStream with a premature close error |
| 241 | + testConfluence( |
| 242 | + (readable) => readable.destroy(), |
| 243 | + common.mustCall(async (readAndAssert, reader) => { |
| 244 | + const errorPredicate = { code: 'ABORT_ERR' }; |
| 245 | + await assert.rejects(readAndAssert(), errorPredicate); |
| 246 | + await assert.rejects(reader.closed, errorPredicate); |
| 247 | + }, 4) |
| 248 | + ); |
| 249 | + // Destroying the readable with an error => errors the readableStream |
| 250 | + testConfluence( |
| 251 | + common.mustCall((readable) => { |
| 252 | + readable.on('error', common.mustCall((reason) => { |
| 253 | + assert.strictEqual(reason, error); |
| 254 | + })); |
| 255 | + readable.destroy(error); |
| 256 | + }, 4), |
| 257 | + common.mustCall(async (readAndAssert, reader) => { |
| 258 | + await assert.rejects(readAndAssert(), error); |
| 259 | + await assert.rejects(reader.closed, error); |
| 260 | + }, 4) |
| 261 | + ); |
196 | 262 | } |
197 | 263 |
|
198 | 264 | { |
|
0 commit comments