| 29 | }; |
| 30 | |
| 31 | const waitForReadyPort = async (proc: Subprocess<"ignore", "pipe", "pipe">): Promise<number> => |
| 32 | new Promise((resolveReady, rejectReady) => { |
| 33 | const timer = setTimeout( |
| 34 | () => rejectReady(new Error("packed binary did not report ready in time")), |
| 35 | READY_TIMEOUT_MS, |
| 36 | ); |
| 37 | let stdout = ""; |
| 38 | let stderr = ""; |
| 39 | const finish = (result: number | Error): void => { |
| 40 | clearTimeout(timer); |
| 41 | if (result instanceof Error) rejectReady(result); |
| 42 | else resolveReady(result); |
| 43 | }; |
| 44 | void proc.exited.then((code) => { |
| 45 | finish(new Error(`packed binary exited before ready with code ${code}: ${stderr}`)); |
| 46 | }); |
| 47 | void (async () => { |
| 48 | const reader = proc.stdout.getReader(); |
| 49 | const decoder = new TextDecoder(); |
| 50 | try { |
| 51 | while (true) { |
| 52 | const chunk = await reader.read(); |
| 53 | if (chunk.done) return; |
| 54 | stdout += decoder.decode(chunk.value); |
| 55 | const match = stdout.match(/EXECUTOR_READY:(\d+)/); |
| 56 | if (match) { |
| 57 | finish(Number(match[1])); |
| 58 | return; |
| 59 | } |
| 60 | } |
| 61 | } catch (cause) { |
| 62 | finish(cause instanceof Error ? cause : new Error(String(cause))); |
| 63 | } |
| 64 | })(); |
| 65 | void (async () => { |
| 66 | const reader = proc.stderr.getReader(); |
| 67 | const decoder = new TextDecoder(); |
| 68 | while (true) { |
| 69 | const chunk = await reader.read(); |
| 70 | if (chunk.done) return; |
| 71 | stderr += decoder.decode(chunk.value); |
| 72 | } |
| 73 | })().catch(() => undefined); |
| 74 | }); |
| 75 | |
| 76 | const main = async (): Promise<void> => { |
| 77 | const fixture = await mkdtemp(join(tmpdir(), "executor-packed-apps-fixture-")); |