coincident
Version:
An Atomics based Proxy to simplify, and synchronize, Worker related tasks
65 lines (60 loc) • 1.78 kB
JavaScript
import nextResolver from 'next-resolver';
import local from 'reflected-ffi/local';
import { isArray } from 'reflected-ffi/utils';
import { MAIN_WS } from './constants.js';
import { decode, encode } from './direct.js';
const { String } = globalThis;
export default (ws, options) => {
const [ next, resolve ] = nextResolver(String);
const module = options?.import || (name => import(name));
const resolvers = new Set;
let coincident = -1, main, end;
return {
onclose: () => {
for (const resolve of resolvers) resolve();
resolvers.clear();
coincident = 0;
end?.();
},
onmessage: async (buffer) => {
if (coincident < 0) {
coincident = 0;
try {
const data = decode(buffer);
if (isArray(data) && data.at(0) === MAIN_WS) {
coincident = 1;
const { direct, reflect, terminate } = local({
...options,
module,
buffer: true,
reflect(...args) {
const [uid, promise] = next();
ws.send(encode([uid, args]));
resolvers.add(resolve.bind(null, uid));
return promise;
},
});
main = reflect;
end = terminate;
}
}
catch(_) {}
}
else if (coincident > 0) {
const data = decode(buffer);
if (typeof data[0] === 'string')
resolve.apply(null, data);
else {
try {
data[1] = await main(...data[1]);
}
catch(error) {
data[1] = null;
data[2] = error;
}
ws.send(encode(data));
}
}
}
};
};