coincident
Version:
An Atomics based Proxy to simplify, and synchronize, Worker related tasks
82 lines (74 loc) • 2.19 kB
JavaScript
import { APPLY } from 'js-proxy/traps';
import DEBUG from '../debug.js';
import {
isChannel,
withResolvers,
} from 'sabayon/shared';
import mainProxy from './main.js';
const $ = String;
const { parse: p, stringify: s } = JSON;
const initValues = () => ['', true, 0, null];
const event = {
data: null,
stopImmediatePropagation() {},
preventDefault() {},
};
export default (ws, options) => {
const { parse = p, stringify = s } = options;
const resolvers = new Map;
let [CHANNEL, init, id, __main__] = initValues();
return {
onclose: () => {
for (const [_, resolve] of resolvers) resolve();
resolvers.clear();
[] = initValues();
},
onmessage: async (buffer) => {
try {
const data = parse($(buffer));
event.data = data;
if (isChannel(event, CHANNEL)) {
if (init) {
init = false;
[] = data;
__main__ = mainProxy(
// options.import = name => valid(name) && name
options?.import || $,
(TRAP, ref, ...args) => {
let promise, resolve;
if (TRAP === APPLY) {
({ promise, resolve } = withResolvers());
resolvers.set(id, resolve);
args.push(id++);
}
ws.send(stringify([CHANNEL, null, [TRAP, ref, ...args]]));
return promise;
}
);
ws.send('');
}
else {
const [_, id, TRAP, ref, ...args] = data;
if (id == null) {
resolvers.get(ref)(...args);
resolvers.delete(ref);
}
else {
let result;
try {
if (DEBUG) console.log('awaiting', TRAP, ref, ...args);
result = await __main__(TRAP, ref, ...args);
if (DEBUG) console.log('returned', result);
}
catch (_) {
result = _;
}
ws.send(stringify([CHANNEL, id, result]));
}
}
}
}
catch(_) {}
}
};
};