import*as e from"../../../core/platform/platform.js";class r{promise;trigger;cancel;label;#e;constructor(r,t){const{promise:n,resolve:s,reject:i}=e.PromiseUtilities.promiseWithResolvers();this.promise=n.then((()=>this.#e())),this.trigger=s,this.cancel=i,this.label=r,this.#e=t}set handler(e){this.#e=e}}class t extends Event{static eventName="renderqueueempty";constructor(){super(t.eventName)}}class n extends Event{static eventName="newframe";constructor(){super(n.eventName)}}let s;const i="Unnamed read",o="Unnamed write",a="Unnamed scroll",l=1500;globalThis.__getRenderCoordinatorPendingFrames=function(){return d.pendingFramesCount()};class d extends EventTarget{static instance({forceNew:e=!1}={}){return s&&!e||(s=new d),s}static pendingFramesCount(){if(!s)throw new Error("No render coordinator instance found.");return s.hasPendingWork()?1:0}observe=!1;recordStorageLimit=100;observeOnlyNamed=!0;#r=[];#t=[];#n=[];#s=0;hasPendingWork(){return 0!==this.#t.length||0!==this.#n.length}done(e){return this.hasPendingWork()||e?.waitForWork?new Promise((e=>this.addEventListener("renderqueueempty",(()=>e()),{once:!0}))):(this.#i("[Queue empty]"),Promise.resolve())}async read(e,r){if("string"==typeof e){if(!r)throw new Error("Read called with label but no callback");return this.#o(r,"read",e)}return this.#o(e,"read",i)}async write(e,r){if("string"==typeof e){if(!r)throw new Error("Write called with label but no callback");return this.#o(r,"write",e)}return this.#o(e,"write",o)}takeRecords(){const e=[...this.#r];return this.#r.length=0,e}async scroll(e,r){if("string"==typeof e){if(!r)throw new Error("Scroll called with label but no callback");return this.#o(r,"read",e)}return this.#o(e,"read",a)}#o(e,t,n){const s=![i,o,a].includes(n);n=`${"read"===t?"[Read]":"[Write]"}: ${n}`;let l=null;switch(t){case"read":l=this.#t;break;case"write":l=this.#n;break;default:throw new Error(`Unknown action: ${t}`)}let d=s?l.find((e=>e.label===n)):void 0;return d?d.handler=e:(d=new r(n,e),l.push(d)),this.#a(),d.promise}#a(){0!==this.#s||(this.#s=requestAnimationFrame((async()=>{if(!this.hasPendingWork())return this.dispatchEvent(new t),window.dispatchEvent(new t),this.#i("[Queue empty]"),void(this.#s=0);this.dispatchEvent(new n),this.#i("[New frame]");const e=this.#t;this.#t=[];const r=this.#n;this.#n=[];for(const r of e)this.#i(r.label),r.trigger();try{await Promise.race([Promise.all(e.map((e=>e.promise))),new Promise(((e,r)=>{window.setTimeout((()=>r(new Error("Readers took over 1500ms. Possible deadlock?"))),l)}))])}catch(r){this.#l(e,r)}for(const e of r)this.#i(e.label),e.trigger();try{await Promise.race([Promise.all(r.map((e=>e.promise))),new Promise(((e,r)=>{window.setTimeout((()=>r(new Error("Writers took over 1500ms. Possible deadlock?"))),l)}))])}catch(e){this.#l(r,e)}this.#s=0,this.#a()})))}#l(e,r){for(const t of e)t.cancel(r)}cancelPending(){const e=new Error;this.#l(this.#t,e),this.#l(this.#n,e)}#i(e){if(!this.observe||!e)return;if(!(e.endsWith(i)||e.endsWith(o)||e.endsWith(a))||!this.observeOnlyNamed)for(this.#r.push({time:performance.now(),value:e});this.#r.length>this.recordStorageLimit;)this.#r.shift()}}var h=Object.freeze({__proto__:null,RenderCoordinatorQueueEmptyEvent:t,RenderCoordinatorNewFrameEvent:n,RenderCoordinator:d});export{h as RenderCoordinator};
