const SOURCE_MODE = "linuxcnc-interpreter-wasm"; const SEMANTIC_BOUNDARY = "linuxcnc_interpreter_wasm_canonical_events"; export async function createLinuxCncInterpreterWorkerRuntime({ sdkModuleUrl, workerUrl = new URL("./linuxcnc-interpreter-worker.js", import.meta.url).href, } = {}) { if (typeof Worker !== "function") { throw new Error("Web Worker is not available in this runtime"); } const worker = new Worker(workerUrl, { type: "module" }); const request = createWorkerRequest(worker); const readiness = await request("init", { sdkModuleUrl }); const runtime = { apiName: "web-rtcp-5axis-linuxcnc-interpreter-worker-runtime", loaded: true, sourceMode: SOURCE_MODE, semanticBoundary: SEMANTIC_BOUNDARY, executionContext: "worker", workerUrl, readiness() { return { ...readiness, apiName: "web-rtcp-5axis-linuxcnc-interpreter-worker-runtime-readiness", executionContext: "worker", workerUrl, }; }, runProgram(programText) { return request("runProgram", { programText }); }, runMachineFileProgram(options = {}) { return request("runMachineFileProgram", options); }, terminate() { worker.terminate(); }, }; return runtime; } function createWorkerRequest(worker) { let nextId = 1; const pending = new Map(); worker.addEventListener("message", (event) => { const { id, ok, value, error } = event.data || {}; const request = pending.get(id); if (!request) return; pending.delete(id); if (ok) { request.resolve(value); } else { request.reject(new Error(error || "LinuxCNC interpreter worker request failed")); } }); worker.addEventListener("error", (event) => { const error = new Error(event.message || "LinuxCNC interpreter worker error"); for (const request of pending.values()) { request.reject(error); } pending.clear(); }); return function request(type, payload = {}) { const id = nextId++; return new Promise((resolve, reject) => { pending.set(id, { resolve, reject }); worker.postMessage({ id, type, payload }); }); }; }