UNPKG

@webreflection/coincident

Version:

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

2 lines (1 loc) 6.1 kB
import{withResolvers as e,ACTION_INIT as t,isChannel as r}from"sabayon/shared";const n="apply",s="ownKeys",o="destruct",a="2d28b248-43f8-4fdc-b78e-514b8111e549",c="="+a,i="-"+a,l=c+"-ws",u=i+"-ws";const p="destroy";const{stringify:f}=JSON,d=(g=f,({byteOffset:e=0}={})=>(t,r)=>{const n=g(t),s=n.length,o=2*s+e;r.byteLength<o&&r.grow(o);const a=new Uint16Array(r,e,s);for(let e=0;e<s;e++)a[e]=n.charCodeAt(e);return s});var g;const{assign:y,create:h}=Object;let m="coincident-",w=!0;try{new SharedArrayBuffer(4,{maxByteLength:8}),m+=crypto.randomUUID()}catch(e){w=!1,m+=Math.random().toString(36).substring(2)}const b={byteOffset:2*Int32Array.BYTES_PER_ELEMENT,useUTF16:!0,circular:!0},v=new Map,T=e=>e,E=(e,t,r)=>{const n="then"!==t;return n&&(e[t]=r),n},M=()=>Promise.withResolvers(),k="InstallTrigger"in globalThis?m:"",{notify:x}=Atomics;var S=e=>{const t=e?.transform,r=(e?.encoder||d)(b);class n extends globalThis.Worker{constructor(e,n){const{port1:s,port2:o}=new MessageChannel,[a,c]=((e=T,t=0)=>[r=>{const n=M();do{r=e(t++)}while(v.has(r));return v.set(r,n),[r,n]},(e,t,r)=>{const n=v.get(e);v.delete(e),r?n.reject(r):n.resolve(t)}])(),i=new Map,l=h(null);let u="";super(e,y({type:"module"},n)).proxy=new Proxy(l,{get:(e,r)=>{if("then"===r)return;let n=i.get(r);return n||i.set(r,n=(...e)=>{const[n,o]=a();return s.postMessage([n,r,t?e.map(t):e]),(({promise:e},t)=>{if(u){const r=setTimeout(console.warn,3e3,`💀🔒 - is proxy.${u}() awaiting proxy.${t}() ?`);e=e.then((e=>(clearTimeout(r),e)),(e=>(clearTimeout(r),Promise.reject(e))))}return e})(o,r)}),n},set:E}),super.postMessage(k,[o]),w&&k&&super.addEventListener("message",(e=>{const{data:t}=e;t?.ID===k&&((e=>{e.stopImmediatePropagation(),e.preventDefault()})(e),s.onmessage(t))})),s.onmessage=async({data:e})=>{const[n,o,a]=e,i=typeof n;if("number"===i)c(n,o,a);else{u=o;const e=await(async(e,t,r,n)=>{const s=[e,null,null];try{const e=await t(...r);s[1]=n?n(e):e}catch(e){s[2]=e}return s})(n,l[o],a,t);if(u="","string"===i)s.postMessage(e);else{const t=e[2]||e[1];n[1]=void 0===t?0:r(t,n.buffer),n[0]=1,x(n,0)}}}}}return{Worker:n,native:w}};const P="array",L="function",W="null",R="number",A="object",I="string",O="symbol",D="undefined";var U=Object.fromEntries([P,"bigint","boolean",L,W,R,A,I,O,D].map(((e,t)=>[e,t])));const{[s]:j}=Reflect,$=new Map(j(Symbol).filter((e=>typeof Symbol[e]===O)).map((e=>[Symbol[e],e]))),_=e=>$.get(e)||`.${Symbol.keyFor(e)||""}`,B=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`%c${String(t)}`,"font-weight:bold","collected"),e(t)})),F=Object.create(null),{addEventListener:N}=EventTarget.prototype,C=new WeakMap;Reflect.defineProperty(EventTarget.prototype,"addEventListener",{value(e,t,...r){const n=r.at(0)?.invoke;if(n){let t=C.get(this);t||(t=new Map,C.set(this,t)),t.set(e,[].concat(n)),delete r[0].invoke}return N.call(this,e,t,...r)}});const{isArray:J}=Array,{isView:z}=ArrayBuffer;var K=(e,t)=>{const{clear:r,drop:a,get:c,hold:i}=(()=>{const e=new Map,t=new Map;let r=0;return{clear:()=>{e.clear(),t.clear()},drop:r=>{const[n,s]=typeof r===R?[t,e]:[e,t],o=n.has(r);return o&&(s.delete(n.get(r)),n.delete(r)),o},get:e=>t.get(e),hold:n=>{if(!e.has(n)){let s;for(;t.has(s=r++););e.set(n,s),t.set(s,n)}return e.get(n)}}})(),l=new Map,u=e=>{l.delete(e),t(o,e)},f=e=>{const t=typeof e;switch(t){case A:return null===e?[U[W],e]:e===globalThis?[U[A],null]:J(e)?[U[P],i(e)]:[U[A],z(e)?e:i(e)];case L:return[U[L],i(e)];case O:return[U[O],_(e)];default:return[U[t],e]}},d=([e,r])=>{switch(e){case U[A]:if(null===r)return globalThis;if(typeof r===R)return c(r);if(!z(r))for(const e in r)r[e]=d(r[e]);return r;case U[P]:return typeof r===R?c(r):r.map(d);case U[L]:switch(typeof r){case R:return c(r);case I:{let e=l.get(r)?.deref();return e||(e=((e,t,{debug:r,handler:n,return:s,token:o=e}=F)=>{const a=s||new Proxy(e,n||F),c=[a,[t,e,!!r]];return!1!==o&&c.push(o),B.register(...c),a})(r,u,{token:!1,return:function(...e){return e.length&&e[0]instanceof Event&&(e=>{const{currentTarget:t,target:r,type:n}=e,s=C.get(t||r)?.get(n);if(s)for(const t of s)e[t]()})(e[0]),t(n,r,f(this),e.map(f)).then(d)}}),l.set(r,new WeakRef(e))),e}}case U[O]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of $)if(r===e)return t})(r);default:return r}},g=(e,t,r)=>f(e(t,...r.map(d))),y=t=>import(e(t)),h=new Set;return(e,t,...n)=>{if(e===p)r();else if(e===o)h.has(t)||a(t);else{const r=Reflect[e],o=null==t?globalThis:c(t);switch(e){case"defineProperty":{const[e,t]=n.map(d);return f(r(o,e,t))}case"getOwnPropertyDescriptor":{const e=r(o,...n.map(d));if(e){const{get:t,set:r,value:n}=e;t&&(e.get=f(t)),r&&(e.set=f(r)),n&&(e.value=f(n))}return[U[e?A:D],e]}case s:return[U[P],r(o).map(f)];case"get":if(null==t){const e="import"===n[0][1]?f(y):g(r,o,n);return h.add(e[1]),e}default:return g(r,o,n)}}}},V=e=>{const t=e?.import,r=S(e);class n extends r.Worker{constructor(e,r){const{proxy:n}=super(e,r);n[c]=K(r?.import||t||(e=>new URL(e,location.href)),n[i])}terminate(){this.proxy[c](p),super.terminate()}}return{...r,Worker:n}};class Y{constructor(e,t){this._=e,this.$=t}get data(){return this.$}preventDefault(){this._.preventDefault()}stopImmediatePropagation(){this._.stopImmediatePropagation()}}const{WebSocket:q}=globalThis,{parse:G,stringify:H}=JSON;var Q=s=>{s={parse:G,stringify:H,...s};const{parse:o,stringify:a,ws:c}=s,i=V(s);class p extends i.Worker{#e=null;constructor(s,...i){let p=0;const f=crypto.randomUUID(),d=new Map,{proxy:g}=super(s,...i),{[u]:y}=g,{promise:h,resolve:m}=e(),w=this.#e=new q(c);g[l]=async(...t)=>{await h;const{promise:r,resolve:n}=e();return d.set(p,n),w.send(a([f,p++,...t])),r},w.addEventListener("close",(()=>{super.terminate()})),w.addEventListener("open",(()=>{w.send(a([f,t]))})),w.addEventListener("message",(async e=>{e.data||m();try{const t=o(e.data);if(r(new Y(e,t),f)){let[e,r,s]=t;if(null==r){const[e,t,...o]=s,c=e===n;c&&(r=o.pop());try{s=await y(e,t,...o)}catch(e){s=e}c&&w.send(a([f,null,e,r,s]))}else d.get(r)(s),d.delete(r)}}catch(e){}}))}terminate(){this.#e.close(),super.terminate()}}return{...i,Worker:p}};export{Q as default};