novy-syndicate/src/wload.ts

54 lines
1.9 KiB
TypeScript

// 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<Handle, false | Ref>(),
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,
});
});