import init, {ludus} from "./rudus.js"; let initialized_wasm = false onmessage = run // exposed in rust as: // async fn io (out: String) -> Result // rust calls this to perform io export function io (out) { // only send messages if we have some if (out.length > 0) postMessage(out) // make an event handler that captures and delivers messages from the main thread // because our promise resolution isn't about calculating a value but setting a global variable, we can't asyncify it // explicitly return a promise return new Promise((resolve, reject) => { // deliver the response to ludus when we get a response from the main thread onmessage = (e) => { resolve(JSON.stringify(e.data)) } // cancel the response if it takes too long setTimeout(() => reject("io took too long"), 500) }) } // set as default event handler from main thread async function run(e) { // we must NEVER run `await init()` twice if (!initialized_wasm) { // this must come before the init call initialized_wasm = true await init() console.log("Worker: Ludus has been initialized.") } // the data is always an array; we only really expect one member tho let msgs = e.data for (const msg of msgs) { // evaluate source if we get some if (msg.verb === "run" && typeof msg.data === 'string') { // temporarily stash an empty function so we don't keep calling this one if we receive additional messages onmessage = () => {} // actually run the ludus--which will call `io`--and replace `run` as the event handler for ipc await ludus(msg.data) // once we've returned from `ludus`, make this the event handler again onmessage = run } else { // report and swallow any malformed startup messages console.log("Worker: Did not get valid startup message. Instead got:") console.log(e.data) } } }