// Web Worker loader import { Actor, Turn, Assertion, Handle, Ref, __setNextActorId } from './actor.js'; import { IdentityMap, Record } from 'preserves'; import { parentPort, threadId } from 'worker_threads'; import { Relay, spawnRelay } from './relay.js'; const _Instance = Symbol.for('Instance'); const Instance = Record.makeConstructor<{moduleName: string, arg: Assertion}>()( _Instance, ['moduleName', 'arg']); const STARTING_ACTOR_ID = (threadId & (2 ** 20 - 1)) * 1000000000; __setNextActorId(STARTING_ACTOR_ID); Turn.for(new Actor(), t => { const p = parentPort!; 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.actor, t => t.quit())); }, initialRef: t.ref({ handleMap: new IdentityMap(), async assert(t, inst, handle) { if (!Instance.isClassOf(inst)) return; const m = await import(Instance._.moduleName(inst)); t.freshen(t => t.spawn(t => { const q = (t: Turn) => { this.handleMap.delete(handle); t.quit(); }; if (this.handleMap.has(handle)) { q(t); } else { this.handleMap.set(handle, t.ref({ message: q })); m.default(t, Instance._.arg(inst)); } })); }, retract(t, handle) { const r = this.handleMap.get(handle); if (r === void 0) { this.handleMap.set(handle, false); } else { t.message(r as Ref, true); } } }), // debug: true, }); });