import initWasm, { Core } from "./pkg/yawn_core.js"; import { SharedProfile } from "./profile.js"; let core; let profile; // While a relocation is staged, every request except its commit waits here. let awaitingCommit = false; const queue = []; const fail = code => { throw new Error(code); }; async function handle(message) { try { let result; if (message?.type === "init") { if (core || !(message.canvas instanceof OffscreenCanvas)) fail("INIT"); const wasm = await initWasm(); core = new Core(message.arenaBytes); profile = new SharedProfile(message.profileBuffer); core.on_profile(json => profile.write(json)); await core.initialize(message.canvas); const buffer = wasm.memory.buffer; if (!(buffer instanceof SharedArrayBuffer)) fail("WASM_MEMORY_NOT_SHARED"); result = { buffer, rows: JSON.parse(core.rows()), features: JSON.parse(core.features()) }; } else { if (!core) fail("UNINITIALIZED"); switch (message?.type) { case "create-rows": result = JSON.parse(core.create_rows(message.name, message.rows, message.stride, message.format)); awaitingCommit = result.commit; break; case "create-rows-batch": result = JSON.parse(core.create_rows_batch(JSON.stringify(message.rows))); awaitingCommit = result.commit.length > 0; break; case "commit-rows": awaitingCommit = false; core.commit_rows(JSON.stringify(message.names)); break; case "delete-rows": core.delete_rows(message.name); break; case "allocate-object": result = JSON.parse(core.allocate_object(message.name, message.count ?? 1)); awaitingCommit = result.commit; break; case "delete-object": core.delete_object(message.name, message.id); break; case "sync-rows": core.sync_rows(message.name, message.first ?? 0, message.count); break; case "compile-graph": result = core.compile_graph(message.serialized); break; case "switch-loadout": core.switch_loadout(message.id); break; case "upload-texture": core.upload_texture(message.name, message.mipLevel, message.image); break; case "delete-texture": core.delete_texture(message.name); break; case "play": core.play(); break; case "pause": core.pause(); break; case "set-fps": core.set_fps(message.fps); break; case "set-profiler": result = core.set_profiler(Boolean(message.enabled)); profile.clear(); break; default: fail("MESSAGE"); } } postMessage({ request: message.request, result }); } catch (error) { postMessage({ request: message?.request, error: error?.message ?? "CORE_ERROR" }); } } addEventListener("message", async ({ data: message }) => { if (awaitingCommit && message?.type !== "commit-rows") { queue.push(message); return; } await handle(message); while (!awaitingCommit && queue.length) await handle(queue.shift()); });