rudus/pkg/worker.js
2025-07-01 16:59:42 -04:00

56 lines
1.9 KiB
JavaScript

import init, {ludus} from "./rudus.js";
let initialized_wasm = false
onmessage = run
// exposed in rust as:
// async fn io (out: String) -> Result<JsValue, JsValue>
// 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)
}
}
}