|
14 | 14 |
|
15 | 15 | import assert from 'node:assert' |
16 | 16 | import { test, describe, after } from 'node:test' |
17 | | -import { Duplex } from 'node:stream' |
| 17 | +import { Duplex, Readable } from 'node:stream' |
18 | 18 | import { $, chalk, fs, path, dotenv } from '../src/index.ts' |
19 | 19 | import { |
20 | 20 | echo, |
@@ -365,6 +365,46 @@ describe('goods', () => { |
365 | 365 | assert(p3.includes('GitHub')) |
366 | 366 | }) |
367 | 367 |
|
| 368 | + test('reader error in _read is caught and destroys stream', async () => { |
| 369 | + // responseToReadable (private) assigns an async _read to a Readable. |
| 370 | + // This test verifies the behavioral contract: when a web ReadableStream |
| 371 | + // reader rejects, the error must surface via the Node.js Readable's |
| 372 | + // 'error' event (via rs.destroy) rather than as an unhandled rejection. |
| 373 | + const error = new Error('stream read failed') |
| 374 | + const webStream = new ReadableStream({ |
| 375 | + start(controller) { |
| 376 | + controller.enqueue(new TextEncoder().encode('ok')) |
| 377 | + }, |
| 378 | + pull() { |
| 379 | + throw error |
| 380 | + }, |
| 381 | + }) |
| 382 | + const reader = webStream.getReader() |
| 383 | + const rs = new Readable({ read() {} }) |
| 384 | + |
| 385 | + rs._read = async () => { |
| 386 | + try { |
| 387 | + const result = await reader.read() |
| 388 | + rs.push(result.done ? null : Buffer.from(result.value)) |
| 389 | + } catch (err) { |
| 390 | + rs.destroy(err as Error) |
| 391 | + } |
| 392 | + } |
| 393 | + |
| 394 | + // First read should succeed |
| 395 | + const firstChunk = await new Promise<Buffer | null>((resolve) => { |
| 396 | + rs.once('data', resolve) |
| 397 | + }) |
| 398 | + assert.ok(firstChunk) |
| 399 | + assert.equal(firstChunk.toString(), 'ok') |
| 400 | + |
| 401 | + // Second read triggers the error in pull(), which should be caught |
| 402 | + const receivedError = await new Promise<Error>((resolve) => { |
| 403 | + rs.on('error', resolve) |
| 404 | + }) |
| 405 | + assert.equal(receivedError.message, 'stream read failed') |
| 406 | + }) |
| 407 | + |
368 | 408 | describe('dotenv', () => { |
369 | 409 | test('parse()', () => { |
370 | 410 | assert.deepEqual(dotenv.parse(''), {}) |
|
0 commit comments