coincident
Version:
An Atomics based Proxy to simplify, and synchronize, Worker related tasks
2 lines (1 loc) • 8.6 kB
JavaScript
const e="apply",t="ownKeys",r="destruct",s="c70de905-a212-4eca-80aa-dad8bd4e677b",n="="+s,a="-"+s,o=n+"-ws",c=a+"-ws";const{ArrayBuffer:i,Atomics:l,Promise:p}=globalThis,{isArray:u}=Array,{create:f,getPrototypeOf:d,values:g}=Object,y=d(Int32Array),h=f(l),w=()=>p.withResolvers();let m=0;const v=new Map,b=(e,t)=>class extends e{constructor(e,...r){super(e,...r),e instanceof t&&v.set(this,[m++,0,w()])}},k=new WeakSet,E=e=>(k.add(e),e),M=(e,t)=>{const{data:r}=e,s=u(r)&&(r.at(0)===t||0===r.at(1)&&!t);return s&&(e.stopImmediatePropagation(),e.preventDefault()),s},A=e=>null!==e&&"object"==typeof e&&!k.has(e),x=new WeakMap,T=(e,t,r)=>{if(v.has(e))t.set(e,v.get(e)[0]);else if(!(e instanceof y||e instanceof i))for(const s of g(e))A(s)&&!r.has(s)&&(r.add(s),T(s,t,r))},W=(...e)=>({value:new p((t=>{let r=new Worker("data:application/javascript,onmessage%3De%3D%3EpostMessage(!Atomics.wait(...e.data))");r.onmessage=()=>t("ok"),r.postMessage(e)}))}),S=(e,t,r)=>{for(const[r,s]of t)x.set(r,[s,e.currentTarget]);(({currentTarget:e,type:t,origin:r,lastEventId:s,source:n,ports:a},o)=>{e.dispatchEvent(new MessageEvent(t,{data:o,origin:r,lastEventId:s,source:n,ports:a}))})(e,r)},I="destroy";let{BigInt64Array:P,Int32Array:U,SharedArrayBuffer:L,Worker:R}=globalThis,D=e=>e,j=!1;const O=e=>({...e,type:"module"});try{new L(4),R=class extends R{constructor(e,t){super(e,O(t))}},h.waitAsync||(h.waitAsync=W)}catch(e){const t=crypto.randomUUID(),r=new Map,s=(e,t,r,...s)=>{e.addEventListener(t,r,...s)},n=({serviceWorker:e},n,a)=>{let o,c=!0;s(e,"message",(e=>{if(M(e,t)){const[s,n,a]=e.data,c=[n,a].join(","),i=e=>{r.delete(c),o.postMessage([t,n,a,e])},l=r.get(c);if(l)i(l);else{const{promise:e,resolve:t}=w();r.set(c,t),e.then(i)}}})),e.getRegistration(n).then((t=>t??e.register(n))).then((function t(r){c=c&&!!e.controller,o=r.installing||r.waiting||r.active,"activated"===o.state?c?a():location.reload():s(o,"statechange",(()=>t(r)),{once:!0})}))};D=E,j=!0,h.notify=(e,s)=>{const[n,a]=(e=>x.get(e))(e),o=[n,s].join(","),c=r.get(o);return c?c(e):r.set(o,e),a.postMessage([t,1,e,n,s]),0},h.waitAsync=(e,...t)=>{const[r,s]=((e,t)=>{const r=v.get(e),[s,n,{promise:a}]=r;return r[1]=t,[s,a]})(e,...t);return{value:s}},L=class extends i{},P=b(P,L),U=b(U,L);let a=null;R=class extends R{constructor(e,r){let o=r?.serviceWorker||"";if(o){if(o=new URL(o,location.href).href,r={...r,serviceWorker:o},!a){const{promise:e,resolve:t}=w();n(navigator,o,t),a=e}a.then((()=>super.postMessage([t,3])))}super(e,O(r)),super.postMessage([t,0,r]),s(this,"message",(e=>{if(M(e,t)){const[t,r,...s]=e.data;switch(r){case 1:((e,t,r)=>{for(const[s,[n,a,{resolve:o}]]of v)if(t===n&&r===a){for(let t=0;t<e.length;t++)s[t]=e[t];v.delete(s),o("ok");break}})(...s);break;case 2:S(e,...s)}}}))}postMessage(e,...r){return super.postMessage(((e,t)=>{const r=new Map;return A(t)&&T(t,r,new Set),r.size?[e,2,r,t]:t})(t,e),...r)}}}const{BYTES_PER_ELEMENT:$}=Int32Array,{BYTES_PER_ELEMENT:_}=Uint16Array,{notify:B}=h,N=new TextDecoder("utf-16"),z=new WeakSet,F=(...e)=>(z.add(e),e);let J="";let Y=0;const C=([e,t,r,s,n,a,o,c,i],l)=>(...p)=>{let u=""!==J,f=0;u&&"="!==J[0]&&"-"!==J[0]&&(f=((e,t)=>setTimeout(console.warn,3e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(l,J));const d=Y++;let g=[];z.has(p.at(-1)||g)&&z.delete(g=p.pop());const y=r(c?p.map(c):p);let h=t(2*$);return o([e,2,l,d,h,y,s],{transfer:g}),i(h,0).value.then((()=>{u&&clearTimeout(f);const r=h[1];if(!r)return;const s=_*r;return h=t(s+s%$),o([e,1,d,h]),i(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=a?e.subarray(0,r):e.slice(0,r);return n(N.decode(t))}))}))};var K=({parse:e,stringify:t,transform:r}=JSON)=>{const s=((e,t)=>async(r,s,[n,a,o,c,i])=>{i&&(J=n);try{const n=await r(...c);if(void 0!==n){const r=e(t?t(n):n);s.set(a,r),o[1]=r.length}}finally{i&&(J=""),o[0]=1,B(o,0)}})(t,r);return{Worker:class extends R{constructor(t,n){const a=crypto.randomUUID(),o=new Map,c=new Map;super(t,n),this.proxy=((e,t)=>new Proxy(t,{get:(t,r)=>{let s;return"then"!==r&&(s=t.get(r),s||(s=C(e,r),t.set(r,s))),s},set:(e,t,r)=>"then"!==t&&!!e.set(t,r)}))([a,e=>new U(new L(e)),D,!1,e,j,(...e)=>this.postMessage(...e),r,h.waitAsync],o),this.postMessage(D([a,0,n])),this.addEventListener("message",(e=>{if(M(e,a)){const[t,r,...n]=e.data;switch(r){case 2:((e,t,r,s)=>{const[n]=s,a=r.get(n);if(!a)throw new Error(`Unknown proxy.${n}()`);e(a,t,s)})(s,c,o,n);break;case 1:((e,[t,r])=>{const s=e.get(t);e.delete(t);for(let e=new Uint16Array(r.buffer),t=0,{length:n}=s;t<n;t++)e[t]=s.charCodeAt(t);B(r,0)})(c,n)}}}))}},polyfill:j,transfer:F}};const q="array",G="function",H="null",Q="number",V="object",X="string",Z="symbol",ee="undefined";var te=Object.fromEntries([q,"bigint","boolean",G,H,Q,V,X,Z,ee].map(((e,t)=>[e,t])));const{[t]:re}=Reflect,se=new Map(re(Symbol).filter((e=>typeof Symbol[e]===Z)).map((e=>[Symbol[e],e]))),ne=e=>se.get(e)||`.${Symbol.keyFor(e)||""}`,ae=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`%c${String(t)}`,"font-weight:bold","collected"),e(t)})),oe=Object.create(null),{addEventListener:ce}=EventTarget.prototype,ie=new WeakMap;Reflect.defineProperty(EventTarget.prototype,"addEventListener",{value(e,t,...r){const s=r.at(0)?.invoke;if(s){let t=ie.get(this);t||(t=new Map,ie.set(this,t)),t.set(e,[].concat(s)),delete r[0].invoke}return ce.call(this,e,t,...r)}});const{isArray:le}=Array;var pe=(s,n)=>{const{clear:a,drop:o,get:c,hold:i}=(()=>{const e=new Map,t=new Map;let r=0;return{clear:()=>{e.clear(),t.clear()},drop:r=>{const[s,n]=typeof r===Q?[t,e]:[e,t],a=s.has(r);return a&&(n.delete(s.get(r)),s.delete(r)),a},get:e=>t.get(e),hold:s=>{if(!e.has(s)){let n;for(;t.has(n=r++););e.set(s,n),t.set(n,s)}return e.get(s)}}})(),l=new Map,p=e=>{l.delete(e),n(r,e)},u=e=>{const t=typeof e;switch(t){case V:return null===e?[te[H],e]:e===globalThis?[te[V],null]:le(e)?[te[q],i(e)]:[te[V],e instanceof y?e:i(e)];case G:return[te[G],i(e)];case Z:return[te[Z],ne(e)];default:return[te[t],e]}},f=([t,r])=>{switch(t){case te[V]:if(null===r)return globalThis;if(typeof r===Q)return c(r);if(!(r instanceof y))for(const e in r)r[e]=f(r[e]);return r;case te[q]:return typeof r===Q?c(r):r.map(f);case te[G]:switch(typeof r){case Q:return c(r);case X:{let t=l.get(r)?.deref();return t||(t=((e,t,{debug:r,handler:s,return:n,token:a=e}=oe)=>{const o=n||new Proxy(e,s||oe),c=[o,[t,e,!!r]];return!1!==a&&c.push(a),ae.register(...c),o})(r,p,{token:!1,return:function(...t){return t.length&&t[0]instanceof Event&&(e=>{const{currentTarget:t,target:r,type:s}=e,n=ie.get(t||r)?.get(s);if(n)for(const t of n)e[t]()})(t[0]),n(e,r,u(this),t.map(u)).then(f)}}),l.set(r,new WeakRef(t))),t}}case te[Z]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of se)if(r===e)return t})(r);default:return r}},d=(e,t,r)=>u(e(t,...r.map(f))),g=e=>import(s(e)),h=new Set;return(e,s,...n)=>{if(e===I)a();else if(e===r)h.has(s)||o(s);else{const r=Reflect[e],a=null==s?globalThis:c(s);switch(e){case"defineProperty":{const[e,t]=n.map(f);return u(r(a,e,t))}case"getOwnPropertyDescriptor":{const e=r(a,...n.map(f));if(e){const{get:t,set:r,value:s}=e;t&&(e.get=u(t)),r&&(e.set=u(r)),s&&(e.value=u(s))}return[te[e?V:ee],e]}case t:return[te[q],r(a).map(u)];case"get":if(null==s){const e="import"===n[0][1]?u(g):d(r,a,n);return h.add(e[1]),e}default:return d(r,a,n)}}}},ue=e=>{const t=e?.import,r=K(e);class s extends r.Worker{constructor(e,r){const{proxy:s}=super(e,r);s[n]=pe(r?.import||t||(e=>new URL(e,location.href)),s[a])}terminate(){this.proxy[n](I),super.terminate()}}return{...r,Worker:s}};class fe{constructor(e,t){this._=e,this.$=t}get data(){return this.$}preventDefault(){this._.preventDefault()}stopImmediatePropagation(){this._.stopImmediatePropagation()}}const{WebSocket:de}=globalThis,{parse:ge,stringify:ye}=JSON;var he=t=>{t={parse:ge,stringify:ye,...t};const{parse:r,stringify:s,ws:n}=t,a=ue(t);class i extends a.Worker{#e=null;constructor(t,...a){let i=0;const l=crypto.randomUUID(),p=new Map,{proxy:u}=super(t,...a),{[c]:f}=u,{promise:d,resolve:g}=w(),y=this.#e=new de(n);u[o]=async(...e)=>{await d;const{promise:t,resolve:r}=w();return p.set(i,r),y.send(s([l,i++,...e])),t},y.addEventListener("close",(()=>{super.terminate()})),y.addEventListener("open",(()=>{y.send(s([l,0]))})),y.addEventListener("message",(async t=>{t.data||g();try{const n=r(t.data);if(M(new fe(t,n),l)){let[t,r,a]=n;if(null==r){const[t,n,...o]=a,c=t===e;c&&(r=o.pop());try{a=await f(t,n,...o)}catch(e){a=e}c&&y.send(s([l,null,t,r,a]))}else p.get(r)(a),p.delete(r)}}catch(e){}}))}terminate(){this.#e.close(),super.terminate()}}return{...a,Worker:i}};export{he as default};