import { CancellableCallback, OriginMessageEvent, WorkerMessageData } from './WorkerConnector'; import { DEBUG } from '../config'; declare const self: WorkerGlobalScope; handleErrors(); const callbackState = new Map(); export default function createInterface(api: Record) { onmessage = async (message: OriginMessageEvent) => { const { data } = message; switch (data.type) { case 'callMethod': { const { messageId, name, args } = data; try { if (messageId) { const callback = (...callbackArgs: any[]) => { const lastArg = callbackArgs[callbackArgs.length - 1]; sendToOrigin({ type: 'methodCallback', messageId, callbackArgs, }, lastArg instanceof ArrayBuffer ? [lastArg] : undefined); }; callbackState.set(messageId, callback); args.push(callback as never); } const [response, arrayBuffers] = (await api[name](...args)) || []; if (messageId) { sendToOrigin( { type: 'methodResponse', messageId, response, }, arrayBuffers, ); } } catch (error) { if (DEBUG) { // eslint-disable-next-line no-console console.error(error); } if (messageId) { sendToOrigin({ type: 'methodResponse', messageId, error: { message: error.message }, }); } } if (messageId) { callbackState.delete(messageId); } break; } case 'cancelProgress': { const callback = callbackState.get(data.messageId); if (callback) { callback.isCanceled = true; } break; } } }; } function handleErrors() { self.onerror = (err) => { // eslint-disable-next-line no-console console.error(err); sendToOrigin({ type: 'unhandledError', error: { message: 'Uncaught exception in worker' } }); }; self.addEventListener('unhandledrejection', (err) => { // eslint-disable-next-line no-console console.error(err); sendToOrigin({ type: 'unhandledError', error: { message: 'Uncaught rejection in worker' } }); }); } function sendToOrigin(data: WorkerMessageData, arrayBuffers?: ArrayBuffer[]) { if (arrayBuffers) { postMessage(data, arrayBuffers); } else { postMessage(data); } }