scratch-storage
Version:
Load and store project and asset files for Scratch 3.0
2 lines • 4.53 kB
JavaScript
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.ScratchStorage=t():e.ScratchStorage=t()}(self,()=>(()=>{"use strict";const e="Queue cost limit exceeded",t="Task aborted",s="Task cancelled",i="Task cost exceeds maximum bucket size";function n(){let e,t;return{promise:new Promise((s,i)=>{e=s,t=i}),resolve:e,reject:t}}var r=class{cost;promise;run;cancel;constructor(e,t={}){this.cost=t.cost??1;let{promise:s,resolve:i,reject:r}=n();this.promise=s,this.cancel=e=>{r(e)},this.run=async()=>{try{i(await e())}catch(e){r(e)}}}},o=class{burstLimit;sustainRate;queueCostLimit;concurrencyLimit;tokenCount;runningTasks=0;pendingTaskRecords=[];lastRefillTime=Date.now();onTaskAdded=n().resolve;onTaskFinished=n().resolve;constructor(e){this.burstLimit=e.burstLimit,this.sustainRate=e.sustainRate,this.tokenCount=e.startingTokens??e.burstLimit,this.queueCostLimit=e.queueCostLimit??1/0,this.concurrencyLimit=e.concurrency??1,this.runTasks()}get length(){return this.pendingTaskRecords.length}get options(){return{burstLimit:this.burstLimit,sustainRate:this.sustainRate,startingTokens:this.tokenCount,queueCostLimit:this.queueCostLimit,concurrency:this.concurrencyLimit}}do(s,n={}){let o=new r(s,n);return o.cost>this.burstLimit?Promise.reject(Error(i)):this.queueCostLimit<1/0&&this.pendingTaskRecords.reduce((e,t)=>e+t.cost,o.cost)>this.queueCostLimit?Promise.reject(Error(e)):(this.pendingTaskRecords.push(o),n.signal?.addEventListener("abort",()=>{this.cancel(o.promise,Error(t))}),this.onTaskAdded(),o.promise)}cancel(e,t){let i=this.pendingTaskRecords.findIndex(t=>t.promise===e);if(-1!==i){let[e]=this.pendingTaskRecords.splice(i,1);return e.cancel(t??Error(s)),!0}return!1}cancelAll(e){let t=this.pendingTaskRecords;return this.pendingTaskRecords=[],e??=Error(s),t.forEach(t=>{t.cancel(e)}),t.length}refillAndSpend(e){return this.refill(),this.spend(e)}refill(){let e=Date.now(),t=e-this.lastRefillTime;if(t<=0)return;this.lastRefillTime=e;let s=t/1e3*this.sustainRate;this.tokenCount=Math.min(this.burstLimit,this.tokenCount+s)}spend(e){return this.tokenCount>=e&&(this.tokenCount-=e,!0)}async runTasks(){for(;;){let e=this.pendingTaskRecords.shift();if(!e){let{promise:e,resolve:t}=n();this.onTaskAdded=t,await e;continue}if(e.cost>this.burstLimit)e.cancel(Error(i));else if(this.refillAndSpend(e.cost)){if(this.runningTasks>=this.concurrencyLimit){let{promise:e,resolve:t}=n();this.onTaskFinished=t,await e}this.runTask(e)}else{this.pendingTaskRecords.unshift(e);let t=Math.max(e.cost-this.tokenCount,0),s=Math.ceil(1e3*t/this.sustainRate);await new Promise(e=>setTimeout(e,s))}}}async runTask(e){this.runningTasks++;try{await e.run()}finally{this.runningTasks--,this.onTaskFinished()}}};const a={burstLimit:64,sustainRate:64,concurrency:64},u=new class{queues;defaultOptions;constructor(e,t){this.queues=new Map(t),this.defaultOptions=e}create(e,t={}){let s=new o({...this.defaultOptions,...t});return this.queues.set(e,s),s}get(e){return this.queues.get(e)}getOrCreate(e,t={}){return this.get(e)??this.create(e,t)}options(){return{...this.defaultOptions}}}({burstLimit:5,sustainRate:1,concurrency:1});const c=globalThis.Headers;var l;!function(e){e.ProjectId="X-Project-ID",e.RunId="X-Run-ID"}(l||(l={}));const h=new c,d=e=>{if((()=>{if(!("undefined"!=typeof self&&self&&self.location&&self.location.search&&self.location.search.split(/[?&]/)||[]).includes("scratchMetadata=1"))return!1;for(const e of h)return!0;return!1})()){const t=Object.assign({},e);if(t.headers=new c(h),e&&e.headers){const s=e.headers instanceof c?e.headers:new c(e.headers);for(const[e,i]of s.entries())t.headers.set(e,i)}return t}return e};let f=0;const m=[];let p;return postMessage({support:{fetch:!0}}),self.addEventListener("message",async e=>{let{data:t}=e;0!==f||p||(p=setInterval(()=>{m.length&&(postMessage(m.slice(),m.map(e=>e.buffer).filter(Boolean)),m.length=0),0===f&&(clearInterval(p),p=void 0)},1)),f++;try{const e=await((e,t,s)=>{t=d(t);let i=null==s?void 0:s.queueName;return i||(e=new Request(e,t),i=new URL(e.url).hostname),u.getOrCreate(i,null==s?void 0:s.queueOptions).do(()=>fetch(e,t))})(t.url,t.options,{queueOptions:a}),s={id:t.id};if(e.ok)s.buffer=await e.arrayBuffer();else{if(404!==e.status)throw e.status;s.buffer=null}m.push(s)}catch(e){m.push({id:t.id,error:(null==e?void 0:e.message)||"Failed request: ".concat(t.url)})}finally{f--}}),{}})());
//# sourceMappingURL=fetch-worker.25c6e93858c0586d2d39.js.map