import type { ExportRequest, ExportResult, WorkerInbound, WorkerOutbound } from "../types"; /** * Main-thread handle to the export worker. The worker owns the heavy pixel work * (decode → transform → encode); here we just correlate requests/responses by id * and hand back a promise. The source bytes are transferred (not copied). */ let worker: Worker | null = null; let seq = 0; const pending = new Map void; reject: (e: Error) => void }>(); function getWorker(): Worker { if (worker) return worker; worker = new Worker(new URL("../workers/export.worker.ts", import.meta.url), { type: "module", name: "wimp-export", }); worker.onmessage = (e: MessageEvent) => { const { id, response } = e.data; const entry = pending.get(id); if (!entry) return; pending.delete(id); if (response.ok) entry.resolve(response); else entry.reject(new Error(response.error)); }; worker.onerror = (e: ErrorEvent) => { const message = e.message || "The export worker crashed."; for (const [, entry] of pending) entry.reject(new Error(message)); pending.clear(); // Drop the broken worker; the next request spins up a fresh one. worker?.terminate(); worker = null; }; return worker; } export function exportImage(req: ExportRequest): Promise { const w = getWorker(); const id = ++seq; const message: WorkerInbound = { id, request: req }; return new Promise((resolve, reject) => { pending.set(id, { resolve, reject }); w.postMessage(message, { transfer: [req.bytes] }); }); }