@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 6.63 kB
JavaScript
import*as Common from"../../core/common/common.js";import*as Host from"../../core/host/host.js";import*as i18n from"../../core/i18n/i18n.js";import*as Bindings from"../../models/bindings/bindings.js";import*as TextUtils from"../../models/text_utils/text_utils.js";import*as TimelineModel from"../../models/timeline_model/timeline_model.js";import*as TraceEngine from"../../models/trace/trace.js";const UIStrings={malformedTimelineDataUnknownJson:"Malformed timeline data: Unknown JSON format",malformedTimelineInputWrongJson:"Malformed timeline input, wrong JSON brackets balance",malformedTimelineDataS:"Malformed timeline data: {PH1}",legacyTimelineFormatIsNot:"Legacy Timeline format is not supported.",malformedCpuProfileFormat:"Malformed CPU profile format"},str_=i18n.i18n.registerUIStrings("panels/timeline/TimelineLoader.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class TimelineLoader{client;tracingModel;canceledCallback;state;buffer;firstRawChunk;firstChunk;loadedBytes;totalSize;jsonTokenizer;filter;#e;#t;constructor(e,t){this.client=e,this.tracingModel=new TraceEngine.Legacy.TracingModel(t),this.canceledCallback=null,this.state=State.Initial,this.buffer="",this.firstRawChunk=!0,this.firstChunk=!0,this.loadedBytes=0,this.jsonTokenizer=new TextUtils.TextUtils.BalancedJSONTokenizer(this.writeBalancedJSON.bind(this),!0),this.filter=null,this.#t=new Promise((e=>{this.#e=e}))}static async loadFromFile(e,t){const i=new TimelineLoader(t),r=new Bindings.FileUtils.ChunkedFileReader(e,TransferChunkLengthBytes);return i.canceledCallback=r.cancel.bind(r),i.totalSize=e.size,setTimeout((async()=>{!await r.read(i)&&r.error()&&i.reportErrorAndCancelLoading(r.error().message)})),i}static loadFromEvents(e,t){const i=new TimelineLoader(t);return window.setTimeout((async()=>{i.addEvents(e)})),i}static getCpuProfileFilter(){const e=[];return e.push(TimelineModel.TimelineModel.RecordType.JSFrame),e.push(TimelineModel.TimelineModel.RecordType.JSIdleFrame),e.push(TimelineModel.TimelineModel.RecordType.JSSystemFrame),new TimelineModel.TimelineModelFilter.TimelineVisibleEventsFilter(e)}static loadFromCpuProfile(e,t,i){const r=new TimelineLoader(t,i);r.state=State.LoadingCPUProfileFromRecording;try{const t=TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(e,1,!0);r.filter=TimelineLoader.getCpuProfileFilter(),window.setTimeout((async()=>{r.addEvents(t)}))}catch(e){console.error(e.stack)}return r}static async loadFromURL(e,t){const i=new TimelineLoader(t),r=new Common.StringOutputStream.StringOutputStream;await t.loadingStarted();const n=Common.Settings.Settings.instance().moduleSetting("network.enable-remote-file-loading").get();return Host.ResourceLoader.loadAsStream(e,null,r,(async function(e,t,n){if(!e)return i.reportErrorAndCancelLoading(n.message);const o=r.data(),a=JSON.parse(o);if(Array.isArray(a.nodes))return i.state=State.LoadingCPUProfileFromFile,i.buffer=o,void await i.close();const s=Array.isArray(a.traceEvents)?a.traceEvents:a;i.addEvents(s)}),n),i}async addEvents(e){await(this.client?.loadingStarted());for(let t=0;t<e.length;t+=15e3){const i=e.slice(t,t+15e3);this.tracingModel.addEvents(i),await(this.client?.loadingProgress((t+i.length)/e.length)),await new Promise((e=>window.setTimeout(e)))}this.close()}async cancel(){this.tracingModel=null,this.client&&(await this.client.loadingComplete(null,null,!1),this.client=null),this.canceledCallback&&this.canceledCallback()}async write(e){if(!this.client)return Promise.resolve();if(this.loadedBytes+=e.length,this.firstRawChunk)await this.client.loadingStarted(),await new Promise((e=>requestAnimationFrame((()=>requestAnimationFrame(e)))));else{let e;this.totalSize&&(e=this.loadedBytes/this.totalSize,e=e>1?e-Math.floor(e):e),await this.client.loadingProgress(e)}if(this.firstRawChunk=!1,this.state===State.Initial)if(e.match(/^{(\s)*"nodes":(\s)*\[/))this.state=State.LoadingCPUProfileFromFile;else if("{"===e[0])this.state=State.LookingForEvents;else{if("["!==e[0])return this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataUnknownJson)),Promise.resolve();this.state=State.ReadingEvents}if(this.state===State.LoadingCPUProfileFromFile)return this.buffer+=e,Promise.resolve();if(this.state===State.LookingForEvents){const t='"traceEvents":',i=this.buffer.length-t.length;this.buffer+=e;const r=this.buffer.indexOf(t,i);if(-1===r)return Promise.resolve();e=this.buffer.slice(r+t.length),this.state=State.ReadingEvents}return this.state!==State.ReadingEvents||this.jsonTokenizer.write(e)||(this.state=State.SkippingTail,this.firstChunk&&this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineInputWrongJson))),Promise.resolve()}writeBalancedJSON(e){let t,i=e+"]";if(!this.firstChunk){const e=i.indexOf(",");-1!==e&&(i=i.slice(e+1)),i="["+i}try{t=JSON.parse(i)}catch(e){return void this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS,{PH1:e.toString()}))}if(this.firstChunk&&(this.firstChunk=!1,this.looksLikeAppVersion(t[0])))this.reportErrorAndCancelLoading(i18nString(UIStrings.legacyTimelineFormatIsNot));else try{this.tracingModel.addEvents(t)}catch(e){this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS,{PH1:e.toString()}))}}reportErrorAndCancelLoading(e){e&&Common.Console.Console.instance().error(e),this.cancel()}looksLikeAppVersion(e){return"string"==typeof e&&-1!==e.indexOf("Chrome")}async close(){this.client&&(await this.client.processingStarted(),await this.finalizeTrace())}isCpuProfile(){return this.state===State.LoadingCPUProfileFromFile||this.state===State.LoadingCPUProfileFromRecording}async finalizeTrace(){this.state===State.LoadingCPUProfileFromFile&&(this.parseCPUProfileFormat(this.buffer),this.buffer=""),this.tracingModel.tracingComplete(),await this.client.loadingComplete(this.tracingModel,this.filter,this.isCpuProfile()),this.#e?.()}traceFinalizedForTest(){return this.#t}parseCPUProfileFormat(e){let t;try{const i=JSON.parse(e);t=TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(i,1,!0)}catch(e){return void this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedCpuProfileFormat))}this.filter=TimelineLoader.getCpuProfileFilter(),this.tracingModel.addEvents(t)}}export const TransferChunkLengthBytes=5e6;export var State;!function(e){e.Initial="Initial",e.LookingForEvents="LookingForEvents",e.ReadingEvents="ReadingEvents",e.SkippingTail="SkippingTail",e.LoadingCPUProfileFromFile="LoadingCPUProfileFromFile",e.LoadingCPUProfileFromRecording="LoadingCPUProfileFromRecording"}(State||(State={}));