| 411 | } |
| 412 | |
| 413 | async function drainModuleResult<E extends ExecEncoding>( |
| 414 | events: ReadableStream<WorkspaceRuntimeEvent>, |
| 415 | encoding: E | undefined, |
| 416 | setReader: (reader: ReadableStreamDefaultReader<WorkspaceRuntimeEvent> | undefined) => void, |
| 417 | ): Promise<WorkspaceRuntimeResult<E>> { |
| 418 | const stdout: Uint8Array[] = []; |
| 419 | const stderr: Uint8Array[] = []; |
| 420 | let value: WorkspaceRuntimeResult<E>["value"]; |
| 421 | let exitCode = 1; |
| 422 | const reader = events.getReader(); |
| 423 | setReader(reader); |
| 424 | try { |
| 425 | while (true) { |
| 426 | const next = await reader.read(); |
| 427 | if (next.done) break; |
| 428 | const event = next.value; |
| 429 | if (event.name === "stdout") stdout.push(event.value); |
| 430 | if (event.name === "stderr") stderr.push(event.value); |
| 431 | if (event.name === "result") value = event.value; |
| 432 | if (event.name === "exit") exitCode = event.value; |
| 433 | } |
| 434 | } finally { |
| 435 | reader.releaseLock(); |
| 436 | setReader(undefined); |
| 437 | } |
| 438 | return { |
| 439 | status: exitCode === 0 ? "completed" : exitCode === 130 ? "cancelled" : "failed", |
| 440 | exitCode, |
| 441 | stdout: join(stdout, encoding) as WorkspaceRuntimeResult<E>["stdout"], |
| 442 | stderr: join(stderr, encoding) as WorkspaceRuntimeResult<E>["stderr"], |
| 443 | ...(value === undefined ? {} : { value }), |
| 444 | pushed: 0, |
| 445 | pulled: 0, |
| 446 | skipped: [] as SkippedEntry[], |
| 447 | sync: { status: "complete", applied: 0, skipped: [] }, |
| 448 | }; |
| 449 | } |
| 450 | |
| 451 | function isCancellationExitCode(exitCode: number) { |
| 452 | return exitCode === 129 || exitCode === 130 || exitCode === 137 || exitCode === 143; |