UNPKG

accordant

Version:
60 lines (51 loc) 1.61 kB
import * as channel from '@webreflection/channel/main'; import { withResolvers } from './utils.js'; export const broadcast = Symbol(); const references = new WeakMap; const proxyHandler = { get(channel, name) { return async (...args) => { if (name === broadcast) channel.postMessage([true, this.uuid, args]); else { const id = this.id++; const { promise, resolve, reject } = withResolvers(); this.ids.set(id, r => (r instanceof Error ? reject : resolve)(r)); channel.postMessage([id, name, args]); return promise; } }; }, has: () => false, ownKeys: () => [], }; const createProxy = (port, broadcast) => { const ids = new Map; const uuid = crypto.randomUUID(); const channel = port.createChannel('accordant'); channel.addEventListener('message', ({ data }) => { const [id, result] = data; if (typeof id === 'number') { ids.get(id)(result); ids.delete(id); } else if (result !== uuid) { broadcast?.(...data.at(2)); } }); return new Proxy(channel, { ...proxyHandler, uuid, ids, id: 0 }); }; const create = (Class, url, options) => { const w = new Class(url, options); const port = Class === channel.Worker ? w : w.port; const proxy = createProxy(port, options?.[broadcast]); references.set(proxy, w); return proxy; }; export const proxied = proxy => references.get(proxy); export function SharedWorker(url, options) { return create(channel.SharedWorker, url, options); } export function Worker(url, options) { return create(channel.Worker, url, options); }