multithreading
Version:
⚡ Multithreading functions in JavaScript to speedup heavy workloads, designed to feel like writing vanilla functions.
2 lines (1 loc) • 9.54 kB
JavaScript
var e,t;(e=Promise).withResolvers??(e.withResolvers=function(){var e,t,s=new this((function(s,n){e=s,t=n}));return{resolve:e,reject:t,promise:s}}),(t=import.meta).resolve??(t.resolve=async function(e,t){const{Module:{createRequire:s}}=await import("node:module");return s(import.meta.url).resolve(e,{...t?{paths:[t]}:{}})});const s=Symbol.for("events");class n{addEventListener(e,t,n){let o=this[s].get(e);o||this[s].set(e,o=[]),o.push(t)}dispatchEvent(e){if(e.target=e.currentTarget=this,this["on"+e.type])try{this["on"+e.type](e)}catch(e){console.error(e)}const t=this[s].get(e.type);return null==t||t.forEach((t=>{try{t.call(this,e)}catch(e){console.error(e)}})),!1}removeEventListener(e,t,n){let o=this[s].get(e);if(o){const e=o.indexOf(t);-1!==e&&o.splice(e,1)}}constructor(){Object.defineProperty(this,s,{value:new Map})}}class o{composedPath(){throw new Error("Method not implemented.")}initEvent(e,t,s){throw new Error("Method not implemented.")}preventDefault(){}stopImmediatePropagation(){}stopPropagation(){}constructor(e,t=null){this.bubbles=!1,this.cancelBubble=!1,this.cancelable=!1,this.composed=!1,this.currentTarget=null,this.defaultPrevented=!1,this.eventPhase=0,this.isTrusted=!1,this.returnValue=!1,this.srcElement=null,this.target=null,this.NONE=0,this.CAPTURING_PHASE=1,this.AT_TARGET=2,this.BUBBLING_PHASE=3,this.type=e,this.timeStamp=Date.now()}}var r;(r=globalThis).Worker??(r.Worker=(async()=>{const{default:e}=await import("node:worker_threads"),{URL:t,pathToFileURL:s,fileURLToPath:r}=await import("node:url"),a=Symbol.for("worker");return class extends n{postMessage(e,t){this[a].postMessage(e,t)}terminate(){this[a].terminate()}constructor(n,i={}){super(),this.onmessage=null,this.onmessageerror=null,this.onerror=null;const{name:c,type:l}=i;let p;if(/^data:/.test(n+=""))p=n;else{const e=s(process.cwd()+"/");p=r(new t(n,e))}const h=new e.Worker(new t(import.meta.url),{workerData:{mod:p,name:c,type:l}});Object.defineProperty(this,a,{value:h}),h.on("message",(e=>{const t=new o("message");t.data=e,this.dispatchEvent(t)})),h.on("error",(e=>{e.type="error",this.dispatchEvent(e)})),h.on("exit",(()=>{this.dispatchEvent(new o("close"))}))}}})());class a extends o{constructor(e){super("error"),this.colno=0,this.filename="",this.lineno=0,this.message="",Object.assign(this,e)}}var i=Worker instanceof Promise?(async()=>{const{default:e}=await import("node:worker_threads");return class extends n{postMessage(t,s){e.parentPort.postMessage(t,s)}close(){process.exit()}}})():void 0;class c extends o{constructor(e){super("unhandledrejection"),Object.assign(this,e)}}Worker instanceof Promise&&(async()=>{const{default:e}=await import("node:worker_threads"),{default:t}=await import("node:vm"),s=await i;return e.isMainThread||async function(){let{mod:t,name:r,type:i}=e.workerData;if(!t)return await Worker;const l=global.self=global;let p=[];function h(){const e=p;p=null,e.forEach((e=>{l.dispatchEvent(e)}))}e.parentPort.on("message",(e=>{const t=new o("message");t.data=e,null==p?l.dispatchEvent(t):p.push(t)})),e.parentPort.on("error",(e=>{e.type="Error",l.dispatchEvent(new a({error:e}))})),process.on("unhandledRejection",((e,t)=>{l.dispatchEvent(new c({reason:e,promise:t}))})),process.on("uncaughtException",((e,t)=>{l.dispatchEvent(new a({error:e}))}));let f=Object.getPrototypeOf(global);delete f.constructor,Object.defineProperties(s.prototype,f),f=Object.setPrototypeOf(global,new s),["postMessage","addEventListener","removeEventListener","dispatchEvent"].forEach((e=>{f[e]=f[e].bind(global)})),global.name=r;const u=/^data:/.test(t);if("module"===i)import(t).catch((e=>{if(u&&"Not supported"===e.message)return console.warn("Worker(): Importing data: URLs requires Node 12.10+. Falling back to classic worker."),n(t,r);console.error(e)})).then(h);else{try{u?n(t,r):require(t)}catch(e){console.error(e)}Promise.resolve().then(h)}}();function n(e,s){const{data:n}=function(e){let[t,s,n,o]=e.match(/^data: *([^;,]*)(?: *; *([^,]*))? *,(.*)$/)||[];if(!t)throw Error("Invalid Data URL.");if(n){if("base64"!==n.toLowerCase())throw Error('Unknown Data URL encoding "'+n+'"');o=Buffer.from(o,"base64").toString()}return{type:s,data:o}}(e);return t.runInThisContext(n,{filename:"worker.<"+(s||"data:")+">"})}})();const l=5,p=6,h=7,f=8,u=13,d=14,m="c",g="d",w="f",b="h",v="i",y="[90m",E="[31m",j="[36m",k="[39m";function M(e,t,s){e[0].postMessage({[m]:f,[g]:{[w]:t,[v]:s}})}function T(e,t,s,n,o,r,a){e.onmessage=i=>{switch(i.data[m]){case h:const c=i.data[g][b],f=i.data[g][v],{resolve:T}=n.get(c);T(f),n.delete(c);break;case l:{const n=i.data[g],o=t[n],r=s.get(o);r.push(e),1===r.length&&M(r,n,o);break}case p:{const n=i.data[g],r=n[w],a=t[r],c=s.get(a);if(c[0]!==e)break;const l=n[v];!function(e,t){if(Array.isArray(e))e.length=0,t.forEach((t=>e.push(t)));else if(e instanceof Map)e.clear(),t.forEach((([t,s])=>e.set(t,s)));else if(e instanceof Set)e.clear(),t.forEach((t=>e.add(t)));else{if("object"!=typeof e||null===e)throw new Error("Unsupported object type");for(const t in e)delete e[t];Object.assign(e,t)}}(a,l);for(const t of o)t!==e&&e.postMessage({[m]:u,[g]:{[w]:r,[v]:l}});c.shift(),c.length>0&&M(c,r,a);break}case d:{const e=i.data[g];e.message=function(e,t,s){const[n,...o]=e.stack.split("\n"),r=o.find((e=>e.includes("data:application/javascript;base64")));if(!r)return e.stack;const[a,i]=r.split(","),[c,l,p]=i.split(":"),h=parseInt(l),f=parseInt(p),u=t.split(/\r?\n/),d=Math.min(3,h-1),m=u.slice(h-(d+1),h+2),g=u[h-1].trimEnd().length-f;m.splice(d+1,0,E+" ".repeat(f-1)+"^".repeat(g)+" "+n+y);const w=o.indexOf(r);return o[w]=` at ${j}<Thread_${s}>${k}\n`+y+" "+m.join("\n ")+k,n.split(":").slice(1).join(":").trim()+"\n"+o.slice(0,w+1).join("\n")}(e,r,a),e.stack="",n.forEach((({reject:t})=>t(e)))}}}}async function P(e){const t=await import.meta.resolve(e);if(t.startsWith("http://")||t.startsWith("https://")||t.startsWith("npm:")||t.startsWith("node:"))return t;if("undefined"!=typeof window)return t;const{pathToFileURL:s}=await import("node:url");return s(t).toString()}async function O(e){}function x(e){}const R=new WeakMap,L=new WeakMap;function W(e,t){const s={debug:!1,maxThreads:"undefined"!=typeof navigator?navigator.hardwareConcurrency:4};let n;"function"==typeof e?n=e:(Object.assign(s,e),n=t);let o={};const r=[],a=new Map;R.set(n,r);let i=0;const c=(async()=>{const e=n.toString(),t=await async function(e){const t=e.indexOf("{")+1,s=e.slice(t,-1).trim().split(/(?:\s*[;\r\n]+\s*)+/),n=[];for(const e of s){if(!e.includes("yield "))continue;const t=e.split("yield ")[1];if(/^["'`]/.test(t)){const e=t.slice(1,-1);n.push({l:"import",[w]:e,m:await P(e)})}else n.push({l:"variable",[w]:t})}return n}(e),i=n();for(const e of t){const t=await i.next({});"variable"===e.l&&(o[e[w]]=t.value)}for(const e in o)L.set(o[e],[]);const c=['Promise.withResolvers??=function(){var e,t,n=new this((function(n,s){e=n,t=s}));return{resolve:e,reject:t,promise:n}};const e="c",t="d",n="i";function s(e,t){if(Array.isArray(e))e.length=0,t.forEach((t=>e.push(t)));else if(e instanceof Map)e.clear(),t.forEach((([t,n])=>e.set(t,n)));else if(e instanceof Set)e.clear(),t.forEach((t=>e.add(t)));else{if("object"!=typeof e||null===e)throw new Error("Unsupported object type");for(const t in e)delete e[t];Object.assign(e,t)}}globalThis.__internal=function(){const o={p:function*(){},n:""};globalThis.$claim=async function(n){const s=c.get(n);return r[s]++,i.has(s)||(i.set(s,Promise.withResolvers()),postMessage({[e]:5,[t]:s})),i.get(s).promise},globalThis.$unclaim=function(s){const o=c.get(s);--r[o]>0||(i.delete(o),postMessage({[e]:6,[t]:{f:o,[n]:s}}))};let a=[];const c=new WeakMap,i=new Map,r={};return self.addEventListener("unhandledrejection",(n=>{n.preventDefault(),postMessage({[e]:14,[t]:n.reason}),close()})),self.addEventListener("error",(n=>{n.preventDefault(),postMessage({[e]:14,[t]:n.error}),close()})),globalThis.onmessage=async l=>{switch(l.data[e]){case 4:!async function(e){e.j,a=e.g,o.n=e.n;const t=(e=>{const t={};for(const[n,s]of Object.entries(e))"object"==typeof s&&"e"in s?(s.e,t[n]=s):t[n]=s;return t})(e.a);for(const e in t){const n=t[e];n instanceof Object&&(c.set(n,e),r[e]=0)}Object.assign(globalThis,t)}(l.data[t]);break;case 12:!async function(s){const c=o.p(...s.b);let i,r=!1,l=!0;for(const e of a)if("import"===e.l){const t=await import(e.m);l&&(await c.next(),l=!1);const n=await c.next(t);if(n.done){r=!0,i=n.value;break}}else{const e=await c.next();if(e.done){r=!0,i=e.value;break}}r||(i=(await c.next()).value),postMessage({[e]:7,[t]:{h:s.h,[n]:i}})}(l.data[t]);break;case 8:!function(e){const t=e.f;s(globalThis[t],e[n]),i.get(t).resolve()}(l.data[t]);break;case 13:!async function(e){const t=e.f;s(globalThis[t],e[n])}(l.data[t])}},o}();\n',`__internal.p = ${e};`],l=(e=>{const t={};for(const[s,n]of Object.entries(e))t[s]="function"==typeof n?{e:2,value:n.toString()}:n;return t})(o);for(const[e,t]of Object.entries(l))2===t.e&&(c.unshift(`globalThis.${e} = ${t.value};`),delete l[e]);const p=c.join("\r\n");for(let e=0;e<s.maxThreads;e++){const n=new(await Worker)(encodeURI("data:application/javascript;base64,"+btoa(p)),{type:"module"});T(n,o,L,a,r,p,e),r.push(n),n.postMessage({[m]:4,[g]:{j:e,g:t,a:l,n:p,k:s.debug}})}})(),l=async(...e)=>{await c;const t=r[i%s.maxThreads],n=Promise.withResolvers();return a.set(i,n),t.postMessage({[m]:12,[g]:{[b]:i++,b:e}}),n.promise};return l.dispose=()=>{for(const e of r)e.terminate();R.delete(n),a.forEach((e=>e.reject("Disposed"))),a.clear()},l}export{O as $claim,x as $unclaim,W as threaded};