| 18 | * })(); |
| 19 | */ |
| 20 | export default function workerize(code, options) { |
| 21 | let exports = {}; |
| 22 | let exportsObjName = `__xpo${Math.random().toString().substring(2)}__`; |
| 23 | if (typeof code==='function') code = `(${Function.prototype.toString.call(code)})(${exportsObjName})`; |
| 24 | code = toCjs(code, exportsObjName, exports) + `\n(${Function.prototype.toString.call(setup)})(self,${exportsObjName},{})`; |
| 25 | let url = URL.createObjectURL(new Blob([code],{ type: 'text/javascript' })), |
| 26 | worker = new Worker(url, options), |
| 27 | term = worker.terminate, |
| 28 | callbacks = {}, |
| 29 | counter = 0, |
| 30 | i; |
| 31 | worker.kill = signal => { |
| 32 | worker.postMessage({ type: 'KILL', signal }); |
| 33 | setTimeout(worker.terminate); |
| 34 | }; |
| 35 | worker.terminate = () => { |
| 36 | URL.revokeObjectURL(url); |
| 37 | term.call(worker); |
| 38 | }; |
| 39 | worker.call = (method, params) => new Promise( (resolve, reject) => { |
| 40 | let id = `rpc${++counter}`; |
| 41 | callbacks[id] = [resolve, reject]; |
| 42 | worker.postMessage({ type: 'RPC', id, method, params }); |
| 43 | }); |
| 44 | worker.rpcMethods = {}; |
| 45 | setup(worker, worker.rpcMethods, callbacks); |
| 46 | worker.expose = methodName => { |
| 47 | worker[methodName] = function() { |
| 48 | return worker.call(methodName, [].slice.call(arguments)); |
| 49 | }; |
| 50 | }; |
| 51 | for (i in exports) if (!(i in worker)) worker.expose(i); |
| 52 | return worker; |
| 53 | } |
| 54 | |
| 55 | function setup(ctx, rpcMethods, callbacks) { |
| 56 | ctx.addEventListener('message', ({ data }) => { |