UNPKG

coincident

Version:

An Atomics based Proxy to simplify, and synchronize, Worker related tasks

92 lines (81 loc) 1.99 kB
// (c) Andrea Giammarchi - MIT import { Atomics, Int32Array, SharedArrayBuffer, Worker as $Worker, ignore, polyfill, } from 'sabayon/main'; import { ACTION_INIT, ACTION_WAIT, ACTION_NOTIFY, actionLength, actionFill, actionWait, createProxy, isChannel, transfer, } from './shared.js'; /** * @typedef {Object} MainOptions * @prop {(text: string, ...args:any) => any} [parse=JSON.parse] * @prop {(value: any, ...args:any) => string} [stringify=JSON.stringify] * @prop {(value: any) => any} [transform] */ /** * @callback Coincident * @param {MainOptions} [options] * @returns {{Worker: import('./ts.js').CoincidentWorker, polyfill: boolean, transfer: (...args: Transferable[]) => Transferable[]}} */ export default /** @type {Coincident} */ ({ parse, stringify, transform, } = JSON) => { const waitLength = actionLength(stringify, transform); class Worker extends $Worker { constructor(url, options) { const CHANNEL = crypto.randomUUID(); const map = new Map; const results = new Map; super(url, options); this.proxy = createProxy( [ CHANNEL, bytes => new Int32Array(new SharedArrayBuffer(bytes)), ignore, false, parse, polyfill, (...args) => this.postMessage(...args), transform, Atomics.waitAsync, ], map, ); this.postMessage(ignore([CHANNEL, ACTION_INIT, options])); this.addEventListener('message', event => { if (isChannel(event, CHANNEL)) { const [_, ACTION, ...rest] = event.data; switch (ACTION) { case ACTION_WAIT: { actionWait(waitLength, results, map, rest); break; } case ACTION_NOTIFY: { actionFill(results, rest); break; } } } }); } } return { Worker, polyfill, transfer, }; };