(stream: ReadableStream<Uint8Array>)
| 21 | * Used by SSH and Docker runtimes for capturing command output. |
| 22 | */ |
| 23 | export async function streamToString(stream: ReadableStream<Uint8Array>): Promise<string> { |
| 24 | const reader = stream.getReader(); |
| 25 | const decoder = new TextDecoder("utf-8"); |
| 26 | // Collect decoded chunks into an array and join at the end. |
| 27 | // Using += would build a deep V8 ConsString rope; subsequent regex/indexOf |
| 28 | // on that rope dereferences one pointer per character, causing O(n²)-class |
| 29 | // hangs on large newline-free payloads (e.g. minified CSS from web_fetch). |
| 30 | const chunks: string[] = []; |
| 31 | |
| 32 | try { |
| 33 | while (true) { |
| 34 | const { done, value } = await reader.read(); |
| 35 | if (done) break; |
| 36 | chunks.push(decoder.decode(value, { stream: true })); |
| 37 | } |
| 38 | // Final flush |
| 39 | const tail = decoder.decode(); |
| 40 | if (tail) chunks.push(tail); |
| 41 | return chunks.join(""); |
| 42 | } finally { |
| 43 | reader.releaseLock(); |
| 44 | } |
| 45 | } |
no test coverage detected