function requireWorkerUrl(value) { if (typeof value === "string" && value.length > 0) { return value; } if (value instanceof URL) { return value; } throw new Error("workerUrl must be a non-empty string or URL."); } function makeRequestId() { return `tool-db-worker-${Date.now()}-${Math.random().toString(16).slice(2)}`; } export function createLinuxCncToolDbBrowserWorkerAdapter({ workerUrl, workerFactory = (url) => new Worker(url, { type: "module" }), timeoutMs = 5000, } = {}) { const normalizedWorkerUrl = requireWorkerUrl(workerUrl); let worker = null; const pending = new Map(); let runtimeExecutionReady = false; let startStatus = "blocked_browser_python_wasm_runtime_missing"; function rejectPending(error) { for (const { reject, timer } of pending.values()) { clearTimeout(timer); reject(error); } pending.clear(); } function request(type, payload = {}) { if (!worker) { return Promise.reject(new Error("Tool DB browser worker is not started.")); } const id = makeRequestId(); return new Promise((resolve, reject) => { const timer = setTimeout(() => { pending.delete(id); reject(new Error(`timeout waiting for Tool DB browser worker ${type}.`)); }, timeoutMs); pending.set(id, { resolve, reject, timer }); worker.postMessage({ id, type, ...payload }); }); } function handleMessage(event) { const message = event.data ?? {}; const waiter = pending.get(message.id); if (!waiter) { return; } pending.delete(message.id); clearTimeout(waiter.timer); if (message.ok === false) { waiter.reject(new Error(message.error ?? `Tool DB browser worker ${message.type ?? "request"} failed.`)); return; } waiter.resolve(message); } return { runtimeMode: "browser-python-wasm-worker", async start() { worker = workerFactory(normalizedWorkerUrl); worker.addEventListener("message", handleMessage); worker.addEventListener("error", (event) => { rejectPending(new Error(event.message ?? "Tool DB browser worker error.")); }); const result = await request("start"); runtimeExecutionReady = result.runtimeExecutionReady === true; startStatus = result.status ?? (runtimeExecutionReady ? "browser_python_wasm_runtime_ready" : "blocked_browser_python_wasm_runtime_missing"); return { status: startStatus, runtimeExecutionReady, }; }, async writeLine(line) { if (runtimeExecutionReady !== true) { throw new Error(`${startStatus}: browser Tool DB runtime is not execution-ready.`); } await request("writeLine", { line }); }, async readLine() { if (runtimeExecutionReady !== true) { throw new Error(`${startStatus}: browser Tool DB runtime is not execution-ready.`); } const result = await request("readLine"); return result.line; }, close() { rejectPending(new Error("Tool DB browser worker closed.")); worker?.terminate(); worker = null; }, }; }