// Web Worker loader import { Actor, Turn, Ref, __setNextActorId } from '../runtime/actor.js'; import { parentPort, threadId } from 'worker_threads'; import { Relay, spawnRelay } from '../transport/relay.js'; import { toInstance } from '../gen/worker.js'; const STARTING_ACTOR_ID = (threadId & (2 ** 20 - 1)) * 1000000000; __setNextActorId(STARTING_ACTOR_ID); type TaskState = | { readonly state: "start_pending" } | { readonly state: "starting" } | { readonly state: "shutdown_pending" } | { readonly state: "running", shutdownRef: Ref }; new Actor(t => { const p = parentPort!; let taskState: TaskState = { state: "start_pending" }; t.activeFacet.preventInertCheck(); spawnRelay(t, { nextLocalOid: STARTING_ACTOR_ID + 500000000, packetWriter: bs => p.postMessage(bs), setup(t: Turn, r: Relay) { p.on('message', bs => r.accept(bs)); p.on('close', () => Turn.for(t.activeFacet, t => t.stopActor())); }, initialRef: t.ref({ async assert(t, inst0) { const inst = toInstance(inst0); if (inst === void 0) return; if (taskState.state !== "start_pending") return; taskState = { state: "starting" }; const m = await import(inst.name); t.freshen(t => t.spawn(t => { t.activeFacet.actor.atExit(() => { console.log('Worker terminating'); process.exit(0); }); if (taskState.state === "shutdown_pending") { t.stopActor(); } else { taskState = { state: "running", shutdownRef: t.ref({ message(t) { t.stopActor(); } }), }; m.default(t, inst.argument); } })); }, retract(t) { if (taskState.state === "running") { t.message(taskState.shutdownRef, true); } else { taskState = { state: "shutdown_pending" }; } } }), // debug: true, }); });