This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhuyujia-webhopper/collector/adg-linux/resources/inspector/timeline/timeline_module.js
little_stone bd2d50cf35 code update
2022-05-05 20:41:28 +08:00

1168 lines
255 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Timeline.CountersGraph=class extends UI.VBox{constructor(delegate){super();this.element.id='memory-graphs-container';this._delegate=delegate;this._calculator=new Timeline.CountersGraph.Calculator();this._header=new UI.HBox();this._header.element.classList.add('timeline-memory-header');this._header.show(this.element);this._toolbar=new UI.Toolbar('timeline-memory-toolbar');this._header.element.appendChild(this._toolbar.element);this._graphsContainer=new UI.VBox();this._graphsContainer.show(this.element);const canvasWidget=new UI.VBoxWithResizeCallback(this._resize.bind(this));canvasWidget.show(this._graphsContainer.element);this._createCurrentValuesBar();this._canvasContainer=canvasWidget.element;this._canvasContainer.id='memory-graphs-canvas-container';this._canvas=this._canvasContainer.createChild('canvas');this._canvas.id='memory-counters-graph';this._canvasContainer.addEventListener('mouseover',this._onMouseMove.bind(this),true);this._canvasContainer.addEventListener('mousemove',this._onMouseMove.bind(this),true);this._canvasContainer.addEventListener('mouseleave',this._onMouseLeave.bind(this),true);this._canvasContainer.addEventListener('click',this._onClick.bind(this),true);this._timelineGrid=new PerfUI.TimelineGrid();this._canvasContainer.appendChild(this._timelineGrid.dividersElement);this._counters=[];this._counterUI=[];this._countersByName={};this._countersByName['jsHeapSizeUsed']=this._createCounter(Common.UIString('JS Heap'),Common.UIString('JS Heap: %s'),'hsl(220, 90%, 43%)',Number.bytesToString);this._countersByName['documents']=this._createCounter(Common.UIString('Documents'),Common.UIString('Documents: %s'),'hsl(0, 90%, 43%)');this._countersByName['nodes']=this._createCounter(Common.UIString('Nodes'),Common.UIString('Nodes: %s'),'hsl(120, 90%, 43%)');this._countersByName['jsEventListeners']=this._createCounter(Common.UIString('Listeners'),Common.UIString('Listeners: %s'),'hsl(38, 90%, 43%)');this._gpuMemoryCounter=this._createCounter(Common.UIString('GPU Memory'),Common.UIString('GPU Memory [KB]: %s'),'hsl(300, 90%, 43%)',Number.bytesToString);this._countersByName['gpuMemoryUsedKB']=this._gpuMemoryCounter;}
setModel(model,track){if(this._model)
this._model.removeEventListener(Timeline.PerformanceModel.Events.WindowChanged,this._onWindowChanged,this);this._model=model;if(this._model)
this._model.addEventListener(Timeline.PerformanceModel.Events.WindowChanged,this._onWindowChanged,this);this._calculator.setZeroTime(model?model.timelineModel().minimumRecordTime():0);for(let i=0;i<this._counters.length;++i){this._counters[i].reset();this._counterUI[i].reset();}
this.scheduleRefresh();this._track=track;if(!track)
return;const events=track.syncEvents();for(let i=0;i<events.length;++i){const event=events[i];if(event.name!==TimelineModel.TimelineModel.RecordType.UpdateCounters)
continue;const counters=event.args.data;if(!counters)
return;for(const name in counters){const counter=this._countersByName[name];if(counter)
counter.appendSample(event.startTime,counters[name]);}
const gpuMemoryLimitCounterName='gpuMemoryLimitKB';if(gpuMemoryLimitCounterName in counters)
this._gpuMemoryCounter.setLimit(counters[gpuMemoryLimitCounterName]);}}
_createCurrentValuesBar(){this._currentValuesBar=this._graphsContainer.element.createChild('div');this._currentValuesBar.id='counter-values-bar';}
_createCounter(uiName,uiValueTemplate,color,formatter){const counter=new Timeline.CountersGraph.Counter();this._counters.push(counter);this._counterUI.push(new Timeline.CountersGraph.CounterUI(this,uiName,uiValueTemplate,color,counter,formatter));return counter;}
resizerElement(){return this._header.element;}
_resize(){const parentElement=this._canvas.parentElement;this._canvas.width=parentElement.clientWidth*window.devicePixelRatio;this._canvas.height=parentElement.clientHeight*window.devicePixelRatio;this._calculator.setDisplayWidth(this._canvas.width);this.refresh();}
_onWindowChanged(event){const window=(event.data.window);this._calculator.setWindow(window.left,window.right);this.scheduleRefresh();}
scheduleRefresh(){UI.invokeOnceAfterBatchUpdate(this,this.refresh);}
draw(){this._clear();for(const counter of this._counters){counter._calculateVisibleIndexes(this._calculator);counter._calculateXValues(this._canvas.width);}
for(const counterUI of this._counterUI)
counterUI._drawGraph(this._canvas);}
_onClick(event){const x=event.x-this._canvasContainer.totalOffsetLeft();let minDistance=Infinity;let bestTime;for(const counterUI of this._counterUI){if(!counterUI.counter.times.length)
continue;const index=counterUI._recordIndexAt(x);const distance=Math.abs(x*window.devicePixelRatio-counterUI.counter.x[index]);if(distance<minDistance){minDistance=distance;bestTime=counterUI.counter.times[index];}}
if(bestTime!==undefined){this._delegate.selectEntryAtTime(this._track.events.length?this._track.events:this._track.asyncEvents,bestTime);}}
_onMouseLeave(event){delete this._markerXPosition;this._clearCurrentValueAndMarker();}
_clearCurrentValueAndMarker(){for(let i=0;i<this._counterUI.length;i++)
this._counterUI[i]._clearCurrentValueAndMarker();}
_onMouseMove(event){const x=event.x-this._canvasContainer.totalOffsetLeft();this._markerXPosition=x;this._refreshCurrentValues();}
_refreshCurrentValues(){if(this._markerXPosition===undefined)
return;for(let i=0;i<this._counterUI.length;++i)
this._counterUI[i].updateCurrentValue(this._markerXPosition);}
refresh(){this._timelineGrid.updateDividers(this._calculator);this.draw();this._refreshCurrentValues();}
_clear(){const ctx=this._canvas.getContext('2d');ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);}};Timeline.CountersGraph.Counter=class{constructor(){this.times=[];this.values=[];}
appendSample(time,value){if(this.values.length&&this.values.peekLast()===value)
return;this.times.push(time);this.values.push(value);}
reset(){this.times=[];this.values=[];}
setLimit(value){this._limitValue=value;}
_calculateBounds(){let maxValue;let minValue;for(let i=this._minimumIndex;i<=this._maximumIndex;i++){const value=this.values[i];if(minValue===undefined||value<minValue)
minValue=value;if(maxValue===undefined||value>maxValue)
maxValue=value;}
minValue=minValue||0;maxValue=maxValue||1;if(this._limitValue){if(maxValue>this._limitValue*0.5)
maxValue=Math.max(maxValue,this._limitValue);minValue=Math.min(minValue,this._limitValue);}
return{min:minValue,max:maxValue};}
_calculateVisibleIndexes(calculator){const start=calculator.minimumBoundary();const end=calculator.maximumBoundary();this._minimumIndex=Number.constrain(this.times.upperBound(start)-1,0,this.times.length-1);this._maximumIndex=Number.constrain(this.times.lowerBound(end),0,this.times.length-1);this._minTime=start;this._maxTime=end;}
_calculateXValues(width){if(!this.values.length)
return;const xFactor=width/(this._maxTime-this._minTime);this.x=new Array(this.values.length);for(let i=this._minimumIndex+1;i<=this._maximumIndex;i++)
this.x[i]=xFactor*(this.times[i]-this._minTime);}};Timeline.CountersGraph.CounterUI=class{constructor(countersPane,title,currentValueLabel,graphColor,counter,formatter){this._countersPane=countersPane;this.counter=counter;this._formatter=formatter||Number.withThousandsSeparator;this._setting=Common.settings.createSetting('timelineCountersGraph-'+title,true);this._setting.setTitle(title);this._filter=new UI.ToolbarSettingCheckbox(this._setting,title);this._filter.inputElement.classList.add('-theme-preserve');const color=Common.Color.parse(graphColor).setAlpha(0.5).asString(Common.Color.Format.RGBA);if(color){this._filter.element.backgroundColor=color;this._filter.element.borderColor='transparent';}
this._filter.inputElement.addEventListener('click',this._toggleCounterGraph.bind(this));countersPane._toolbar.appendToolbarItem(this._filter);this._range=this._filter.element.createChild('span','range');this._value=countersPane._currentValuesBar.createChild('span','memory-counter-value');this._value.style.color=graphColor;this.graphColor=graphColor;this.limitColor=Common.Color.parse(graphColor).setAlpha(0.3).asString(Common.Color.Format.RGBA);this.graphYValues=[];this._verticalPadding=10;this._currentValueLabel=currentValueLabel;this._marker=countersPane._canvasContainer.createChild('div','memory-counter-marker');this._marker.style.backgroundColor=graphColor;this._clearCurrentValueAndMarker();}
reset(){this._range.textContent='';}
setRange(minValue,maxValue){const min=this._formatter(minValue);const max=this._formatter(maxValue);this._range.textContent=Common.UIString('[%s\xa0\u2013\xa0%s]',min,max);}
_toggleCounterGraph(event){this._value.classList.toggle('hidden',!this._filter.checked());this._countersPane.refresh();}
_recordIndexAt(x){return this.counter.x.upperBound(x*window.devicePixelRatio,null,this.counter._minimumIndex+1,this.counter._maximumIndex+1)-
1;}
updateCurrentValue(x){if(!this.visible()||!this.counter.values.length||!this.counter.x)
return;const index=this._recordIndexAt(x);const value=Number.withThousandsSeparator(this.counter.values[index]);this._value.textContent=Common.UIString(this._currentValueLabel,value);const y=this.graphYValues[index]/window.devicePixelRatio;this._marker.style.left=x+'px';this._marker.style.top=y+'px';this._marker.classList.remove('hidden');}
_clearCurrentValueAndMarker(){this._value.textContent='';this._marker.classList.add('hidden');}
_drawGraph(canvas){const ctx=canvas.getContext('2d');const width=canvas.width;const height=canvas.height-2*this._verticalPadding;if(height<=0){this.graphYValues=[];return;}
const originY=this._verticalPadding;const counter=this.counter;const values=counter.values;if(!values.length)
return;const bounds=counter._calculateBounds();const minValue=bounds.min;const maxValue=bounds.max;this.setRange(minValue,maxValue);if(!this.visible())
return;const yValues=this.graphYValues;const maxYRange=maxValue-minValue;const yFactor=maxYRange?height/(maxYRange):1;ctx.save();ctx.lineWidth=window.devicePixelRatio;if(ctx.lineWidth%2)
ctx.translate(0.5,0.5);ctx.beginPath();let value=values[counter._minimumIndex];let currentY=Math.round(originY+height-(value-minValue)*yFactor);ctx.moveTo(0,currentY);let i=counter._minimumIndex;for(;i<=counter._maximumIndex;i++){const x=Math.round(counter.x[i]);ctx.lineTo(x,currentY);const currentValue=values[i];if(typeof currentValue!=='undefined')
value=currentValue;currentY=Math.round(originY+height-(value-minValue)*yFactor);ctx.lineTo(x,currentY);yValues[i]=currentY;}
yValues.length=i;ctx.lineTo(width,currentY);ctx.strokeStyle=this.graphColor;ctx.stroke();if(counter._limitValue){const limitLineY=Math.round(originY+height-(counter._limitValue-minValue)*yFactor);ctx.moveTo(0,limitLineY);ctx.lineTo(width,limitLineY);ctx.strokeStyle=this.limitColor;ctx.stroke();}
ctx.closePath();ctx.restore();}
visible(){return this._filter.checked();}};Timeline.CountersGraph.Calculator=class{setZeroTime(time){this._zeroTime=time;}
computePosition(time){return(time-this._minimumBoundary)/this.boundarySpan()*this._workingArea;}
setWindow(minimumBoundary,maximumBoundary){this._minimumBoundary=minimumBoundary;this._maximumBoundary=maximumBoundary;}
setDisplayWidth(clientWidth){this._workingArea=clientWidth;}
formatValue(value,precision){return Number.preciseMillisToString(value-this.zeroTime(),precision);}
maximumBoundary(){return this._maximumBoundary;}
minimumBoundary(){return this._minimumBoundary;}
zeroTime(){return this._zeroTime;}
boundarySpan(){return this._maximumBoundary-this._minimumBoundary;}};;Timeline.ExtensionTracingSession=class{constructor(provider,performanceModel){this._provider=provider;this._performanceModel=performanceModel;this._completionCallback;this._completionPromise=new Promise(fulfill=>{this._completionCallback=fulfill;});this._timeOffset=0;}
loadingStarted(){}
processingStarted(){}
loadingProgress(progress){}
loadingComplete(tracingModel){if(!tracingModel)
return;this._performanceModel.addExtensionEvents(this._provider.longDisplayName(),tracingModel,this._timeOffset);this._completionCallback();}
complete(url,timeOffsetMicroseconds){if(!url){this._completionCallback();return;}
this._timeOffset=timeOffsetMicroseconds;Timeline.TimelineLoader.loadFromURL(url,this);}
start(){this._provider.start(this);}
stop(){this._provider.stop();return this._completionPromise;}};;Timeline.PerformanceModel=class extends Common.Object{constructor(){super();this._mainTarget=null;this._tracingModel=null;this._filters=[];this._timelineModel=new TimelineModel.TimelineModel();this._frameModel=new TimelineModel.TimelineFrameModel(event=>Timeline.TimelineUIUtils.eventStyle(event).category.name);this._filmStripModel=null;this._irModel=new TimelineModel.TimelineIRModel();this._window={left:0,right:Infinity};this._extensionTracingModels=[];this._recordStartTime=undefined;}
setMainTarget(target){this._mainTarget=target;}
setRecordStartTime(time){this._recordStartTime=time;}
recordStartTime(){return this._recordStartTime;}
setFilters(filters){this._filters=filters;}
filters(){return this._filters;}
isVisible(event){return this._filters.every(f=>f.accept(event));}
setTracingModel(model){this._tracingModel=model;this._timelineModel.setEvents(model);let inputEvents=null;let animationEvents=null;for(const track of this._timelineModel.tracks()){if(track.type===TimelineModel.TimelineModel.TrackType.Input)
inputEvents=track.asyncEvents;if(track.type===TimelineModel.TimelineModel.TrackType.Animation)
animationEvents=track.asyncEvents;}
if(inputEvents||animationEvents)
this._irModel.populate(inputEvents||[],animationEvents||[]);const mainTracks=this._timelineModel.tracks().filter(track=>track.type===TimelineModel.TimelineModel.TrackType.MainThread&&track.forMainFrame&&track.events.length);const threadData=mainTracks.map(track=>{const event=track.events[0];return{thread:event.thread,time:event.startTime};});this._frameModel.addTraceEvents(this._mainTarget,this._timelineModel.inspectedTargetEvents(),threadData);for(const entry of this._extensionTracingModels){entry.model.adjustTime(this._tracingModel.minimumRecordTime()+(entry.timeOffset/1000)-this._recordStartTime);}
this._autoWindowTimes();}
addExtensionEvents(title,model,timeOffset){this._extensionTracingModels.push({model:model,title:title,timeOffset:timeOffset});if(!this._tracingModel)
return;model.adjustTime(this._tracingModel.minimumRecordTime()+(timeOffset/1000)-this._recordStartTime);this.dispatchEventToListeners(Timeline.PerformanceModel.Events.ExtensionDataAdded);}
tracingModel(){if(!this._tracingModel)
throw'call setTracingModel before accessing PerformanceModel';return this._tracingModel;}
timelineModel(){return this._timelineModel;}
filmStripModel(){if(this._filmStripModel)
return this._filmStripModel;if(!this._tracingModel)
throw'call setTracingModel before accessing PerformanceModel';this._filmStripModel=new SDK.FilmStripModel(this._tracingModel);return this._filmStripModel;}
frames(){return this._frameModel.frames();}
frameModel(){return this._frameModel;}
interactionRecords(){return this._irModel.interactionRecords();}
extensionInfo(){return this._extensionTracingModels;}
dispose(){if(this._tracingModel)
this._tracingModel.dispose();for(const extensionEntry of this._extensionTracingModels)
extensionEntry.model.dispose();}
filmStripModelFrame(frame){const screenshotTime=frame.idle?frame.startTime:frame.endTime;const filmStripFrame=this._filmStripModel.frameByTimestamp(screenshotTime);return filmStripFrame&&filmStripFrame.timestamp-frame.endTime<10?filmStripFrame:null;}
save(stream){const backingStorage=(this._tracingModel.backingStorage());return backingStorage.writeToStream(stream);}
setWindow(window,animate){this._window=window;this.dispatchEventToListeners(Timeline.PerformanceModel.Events.WindowChanged,{window,animate});}
window(){return this._window;}
_autoWindowTimes(){const timelineModel=this._timelineModel;let tasks=[];for(const track of timelineModel.tracks()){if(track.type===TimelineModel.TimelineModel.TrackType.MainThread&&track.forMainFrame)
tasks=track.tasks;}
if(!tasks.length){this.setWindow({left:timelineModel.minimumRecordTime(),right:timelineModel.maximumRecordTime()});return;}
function findLowUtilizationRegion(startIndex,stopIndex){const threshold=0.1;let cutIndex=startIndex;let cutTime=(tasks[cutIndex].startTime+tasks[cutIndex].endTime)/2;let usedTime=0;const step=Math.sign(stopIndex-startIndex);for(let i=startIndex;i!==stopIndex;i+=step){const task=tasks[i];const taskTime=(task.startTime+task.endTime)/2;const interval=Math.abs(cutTime-taskTime);if(usedTime<threshold*interval){cutIndex=i;cutTime=taskTime;usedTime=0;}
usedTime+=task.duration;}
return cutIndex;}
const rightIndex=findLowUtilizationRegion(tasks.length-1,0);const leftIndex=findLowUtilizationRegion(0,rightIndex);let leftTime=tasks[leftIndex].startTime;let rightTime=tasks[rightIndex].endTime;const span=rightTime-leftTime;const totalSpan=timelineModel.maximumRecordTime()-timelineModel.minimumRecordTime();if(span<totalSpan*0.1){leftTime=timelineModel.minimumRecordTime();rightTime=timelineModel.maximumRecordTime();}else{leftTime=Math.max(leftTime-0.05*span,timelineModel.minimumRecordTime());rightTime=Math.min(rightTime+0.05*span,timelineModel.maximumRecordTime());}
this.setWindow({left:leftTime,right:rightTime});}};Timeline.PerformanceModel.Events={ExtensionDataAdded:Symbol('ExtensionDataAdded'),WindowChanged:Symbol('WindowChanged')};Timeline.PerformanceModel.Window;;Timeline.TimelineController=class{constructor(target,client){this._tracingManager=target.model(SDK.TracingManager);this._performanceModel=new Timeline.PerformanceModel();this._performanceModel.setMainTarget(target);this._client=client;const backingStorage=new Bindings.TempFileBackingStorage();this._tracingModel=new SDK.TracingModel(backingStorage);this._extensionSessions=[];SDK.targetManager.observeModels(SDK.CPUProfilerModel,this);}
mainTarget(){return this._tracingManager.target();}
startRecording(options,providers){this._extensionTraceProviders=Extensions.extensionServer.traceProviders().slice();function disabledByDefault(category){return'disabled-by-default-'+category;}
const categoriesArray=['-*','devtools.timeline','v8.execute',disabledByDefault('devtools.timeline'),disabledByDefault('devtools.timeline.frame'),SDK.TracingModel.TopLevelEventCategory,TimelineModel.TimelineModel.Category.Console,TimelineModel.TimelineModel.Category.UserTiming];categoriesArray.push(TimelineModel.TimelineModel.Category.LatencyInfo);if(Runtime.experiments.isEnabled('timelineFlowEvents'))
categoriesArray.push('devtools.timeline.async');if(Runtime.experiments.isEnabled('timelineV8RuntimeCallStats')&&options.enableJSSampling)
categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling'));if(Runtime.experiments.isEnabled('timelineTracingJSProfile')&&options.enableJSSampling){categoriesArray.push(disabledByDefault('v8.cpu_profiler'));if(Common.moduleSetting('highResolutionCpuProfiling').get())
categoriesArray.push(disabledByDefault('v8.cpu_profiler.hires'));}
categoriesArray.push(disabledByDefault('devtools.timeline.stack'));if(Runtime.experiments.isEnabled('timelineInvalidationTracking'))
categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking'));if(options.capturePictures){categoriesArray.push(disabledByDefault('devtools.timeline.layers'),disabledByDefault('devtools.timeline.picture'),disabledByDefault('blink.graphics_context_annotations'));}
if(options.captureFilmStrip)
categoriesArray.push(disabledByDefault('devtools.screenshot'));this._extensionSessions=providers.map(provider=>new Timeline.ExtensionTracingSession(provider,this._performanceModel));this._extensionSessions.forEach(session=>session.start());const startPromise=this._startRecordingWithCategories(categoriesArray.join(','),options.enableJSSampling);this._performanceModel.setRecordStartTime(Date.now());return startPromise;}
async stopRecording(){const tracingStoppedPromises=[];tracingStoppedPromises.push(new Promise(resolve=>this._tracingCompleteCallback=resolve));tracingStoppedPromises.push(this._stopProfilingOnAllModels());this._tracingManager.stop();tracingStoppedPromises.push(SDK.targetManager.resumeAllTargets());this._client.loadingStarted();const extensionCompletionPromises=this._extensionSessions.map(session=>session.stop());if(extensionCompletionPromises.length){tracingStoppedPromises.push(Promise.race([Promise.all(extensionCompletionPromises),new Promise(r=>setTimeout(r,5000))]));}
await Promise.all(tracingStoppedPromises);this._allSourcesFinished();return this._performanceModel;}
modelAdded(cpuProfilerModel){if(this._profiling)
cpuProfilerModel.startRecording();}
modelRemoved(cpuProfilerModel){}
_startProfilingOnAllModels(){this._profiling=true;const models=SDK.targetManager.models(SDK.CPUProfilerModel);return Promise.all(models.map(model=>model.startRecording()));}
_addCpuProfile(targetId,cpuProfile){if(!cpuProfile){Common.console.warn(Common.UIString('CPU profile for a target is not available.'));return;}
if(!this._cpuProfiles)
this._cpuProfiles=new Map();this._cpuProfiles.set(targetId,cpuProfile);}
_stopProfilingOnAllModels(){const models=this._profiling?SDK.targetManager.models(SDK.CPUProfilerModel):[];this._profiling=false;const promises=[];for(const model of models){const targetId=model.target().id();const modelPromise=model.stopRecording().then(this._addCpuProfile.bind(this,targetId));promises.push(modelPromise);}
return Promise.all(promises);}
_startRecordingWithCategories(categories,enableJSSampling){SDK.targetManager.suspendAllTargets();const profilingStartedPromise=enableJSSampling&&!Runtime.experiments.isEnabled('timelineTracingJSProfile')?this._startProfilingOnAllModels():Promise.resolve();const samplingFrequencyHz=Common.moduleSetting('highResolutionCpuProfiling').get()?10000:1000;const options='sampling-frequency='+samplingFrequencyHz;return profilingStartedPromise.then(()=>this._tracingManager.start(this,categories,options));}
traceEventsCollected(events){this._tracingModel.addEvents(events);}
tracingComplete(){this._tracingCompleteCallback();this._tracingCompleteCallback=null;}
_allSourcesFinished(){this._client.processingStarted();setTimeout(()=>this._finalizeTrace(),0);}
_finalizeTrace(){this._injectCpuProfileEvents();this._tracingModel.tracingComplete();this._client.loadingComplete(this._tracingModel);}
_injectCpuProfileEvent(pid,tid,cpuProfile){if(!cpuProfile)
return;const cpuProfileEvent=({cat:SDK.TracingModel.DevToolsMetadataEventCategory,ph:SDK.TracingModel.Phase.Instant,ts:this._tracingModel.maximumRecordTime()*1000,pid:pid,tid:tid,name:TimelineModel.TimelineModel.RecordType.CpuProfile,args:{data:{cpuProfile:cpuProfile}}});this._tracingModel.addEvents([cpuProfileEvent]);}
_injectCpuProfileEvents(){if(!this._cpuProfiles)
return;const metadataEventTypes=TimelineModel.TimelineModel.DevToolsMetadataEvent;const metadataEvents=this._tracingModel.devToolsMetadataEvents();const mainMetaEvent=metadataEvents.filter(event=>event.name===metadataEventTypes.TracingStartedInPage).peekLast();if(!mainMetaEvent)
return;const pid=mainMetaEvent.thread.process().id();const mainCpuProfile=this._cpuProfiles.get(this._tracingManager.target().id());this._injectCpuProfileEvent(pid,mainMetaEvent.thread.id(),mainCpuProfile);const workerMetaEvents=metadataEvents.filter(event=>event.name===metadataEventTypes.TracingSessionIdForWorker);for(const metaEvent of workerMetaEvents){const workerId=metaEvent.args['data']['workerId'];const cpuProfile=this._cpuProfiles.get(workerId);this._injectCpuProfileEvent(metaEvent.thread.process().id(),metaEvent.args['data']['workerThreadId'],cpuProfile);}
this._cpuProfiles=null;}
tracingBufferUsage(usage){this._client.recordingProgress(usage);}
eventsRetrievalProgress(progress){this._client.loadingProgress(progress);}};Timeline.TimelineController.Client=function(){};Timeline.TimelineController.Client.prototype={recordingProgress(usage){},};Timeline.TimelineController.RecordingOptions;;Timeline.TimelineDetailsView=class extends UI.VBox{constructor(delegate){super();this.element.classList.add('timeline-details');this._detailsLinkifier=new Components.Linkifier();this._badgePool=new ProductRegistry.BadgePool();this._badgePool.setShowTitles(true);this._tabbedPane=new UI.TabbedPane();this._tabbedPane.show(this.element);const tabIds=Timeline.TimelineDetailsView.Tab;this._defaultDetailsWidget=new UI.VBox();this._defaultDetailsWidget.element.classList.add('timeline-details-view');this._defaultDetailsContentElement=this._defaultDetailsWidget.element.createChild('div','timeline-details-view-body vbox');this._defaultDetailsContentElement.tabIndex=0;this._appendTab(tabIds.Details,Common.UIString('Summary'),this._defaultDetailsWidget);this.setPreferredTab(tabIds.Details);this._rangeDetailViews=new Map();const bottomUpView=new Timeline.BottomUpTimelineTreeView();this._appendTab(tabIds.BottomUp,Common.UIString('Bottom-Up'),bottomUpView);this._rangeDetailViews.set(tabIds.BottomUp,bottomUpView);const callTreeView=new Timeline.CallTreeTimelineTreeView();this._appendTab(tabIds.CallTree,Common.UIString('Call Tree'),callTreeView);this._rangeDetailViews.set(tabIds.CallTree,callTreeView);const eventsView=new Timeline.EventsTimelineTreeView(delegate);this._appendTab(tabIds.EventLog,Common.UIString('Event Log'),eventsView);this._rangeDetailViews.set(tabIds.EventLog,eventsView);this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected,this._tabSelected,this);}
setModel(model,track){if(this._model)
this._model.removeEventListener(Timeline.PerformanceModel.Events.WindowChanged,this._onWindowChanged,this);this._model=model;if(this._model)
this._model.addEventListener(Timeline.PerformanceModel.Events.WindowChanged,this._onWindowChanged,this);this._track=track;this._tabbedPane.closeTabs([Timeline.TimelineDetailsView.Tab.PaintProfiler,Timeline.TimelineDetailsView.Tab.LayerViewer],false);for(const view of this._rangeDetailViews.values())
view.setModel(model,track);this._lazyPaintProfilerView=null;this._lazyLayersView=null;this.setSelection(null);}
_setContent(node){const allTabs=this._tabbedPane.otherTabs(Timeline.TimelineDetailsView.Tab.Details);for(let i=0;i<allTabs.length;++i){if(!this._rangeDetailViews.has(allTabs[i]))
this._tabbedPane.closeTab(allTabs[i]);}
this._defaultDetailsContentElement.removeChildren();this._defaultDetailsContentElement.appendChild(node);}
_updateContents(){const view=this._rangeDetailViews.get(this._tabbedPane.selectedTabId||'');if(view){const window=this._model.window();view.updateContents(this._selection||Timeline.TimelineSelection.fromRange(window.left,window.right));}}
_appendTab(id,tabTitle,view,isCloseable){this._tabbedPane.appendTab(id,tabTitle,view,undefined,undefined,isCloseable);if(this._preferredTabId!==this._tabbedPane.selectedTabId)
this._tabbedPane.selectTab(id);}
headerElement(){return this._tabbedPane.headerElement();}
setPreferredTab(tabId){this._preferredTabId=tabId;}
_onWindowChanged(event){if(!this._selection)
this._updateContentsFromWindow();}
_updateContentsFromWindow(){if(!this._model)
return;const window=this._model.window();this._updateSelectedRangeStats(window.left,window.right);this._updateContents();}
setSelection(selection){this._detailsLinkifier.reset();this._badgePool.reset();this._selection=selection;if(!this._selection){this._updateContentsFromWindow();return;}
switch(this._selection.type()){case Timeline.TimelineSelection.Type.TraceEvent:const event=(this._selection.object());Timeline.TimelineUIUtils.buildTraceEventDetails(event,this._model.timelineModel(),this._detailsLinkifier,this._badgePool,true).then(fragment=>this._appendDetailsTabsForTraceEventAndShowDetails(event,fragment));break;case Timeline.TimelineSelection.Type.Frame:const frame=(this._selection.object());const filmStripFrame=this._model.filmStripModelFrame(frame);this._setContent(Timeline.TimelineUIUtils.generateDetailsContentForFrame(frame,filmStripFrame));if(frame.layerTree){const layersView=this._layersView();layersView.showLayerTree(frame.layerTree);if(!this._tabbedPane.hasTab(Timeline.TimelineDetailsView.Tab.LayerViewer))
this._appendTab(Timeline.TimelineDetailsView.Tab.LayerViewer,Common.UIString('Layers'),layersView);}
break;case Timeline.TimelineSelection.Type.NetworkRequest:const request=(this._selection.object());Timeline.TimelineUIUtils.buildNetworkRequestDetails(request,this._model.timelineModel(),this._detailsLinkifier,this._badgePool).then(this._setContent.bind(this));break;case Timeline.TimelineSelection.Type.Range:this._updateSelectedRangeStats(this._selection.startTime(),this._selection.endTime());break;}
this._updateContents();}
_tabSelected(event){if(!event.data.isUserGesture)
return;this.setPreferredTab(event.data.tabId);this._updateContents();}
_layersView(){if(this._lazyLayersView)
return this._lazyLayersView;this._lazyLayersView=new Timeline.TimelineLayersView(this._model.timelineModel(),this._showSnapshotInPaintProfiler.bind(this));return this._lazyLayersView;}
_paintProfilerView(){if(this._lazyPaintProfilerView)
return this._lazyPaintProfilerView;this._lazyPaintProfilerView=new Timeline.TimelinePaintProfilerView(this._model.frameModel());return this._lazyPaintProfilerView;}
_showSnapshotInPaintProfiler(snapshot){const paintProfilerView=this._paintProfilerView();paintProfilerView.setSnapshot(snapshot);if(!this._tabbedPane.hasTab(Timeline.TimelineDetailsView.Tab.PaintProfiler)){this._appendTab(Timeline.TimelineDetailsView.Tab.PaintProfiler,Common.UIString('Paint Profiler'),paintProfilerView,true);}
this._tabbedPane.selectTab(Timeline.TimelineDetailsView.Tab.PaintProfiler,true);}
_appendDetailsTabsForTraceEventAndShowDetails(event,content){this._setContent(content);if(event.name===TimelineModel.TimelineModel.RecordType.Paint||event.name===TimelineModel.TimelineModel.RecordType.RasterTask)
this._showEventInPaintProfiler(event);}
_showEventInPaintProfiler(event){const paintProfilerModel=SDK.targetManager.models(SDK.PaintProfilerModel)[0];if(!paintProfilerModel)
return;const paintProfilerView=this._paintProfilerView();const hasProfileData=paintProfilerView.setEvent(paintProfilerModel,event);if(!hasProfileData)
return;if(this._tabbedPane.hasTab(Timeline.TimelineDetailsView.Tab.PaintProfiler))
return;this._appendTab(Timeline.TimelineDetailsView.Tab.PaintProfiler,Common.UIString('Paint Profiler'),paintProfilerView);}
_updateSelectedRangeStats(startTime,endTime){if(!this._model||!this._track)
return;const aggregatedStats=Timeline.TimelineUIUtils.statsForTimeRange(this._track.syncEvents(),startTime,endTime);const startOffset=startTime-this._model.timelineModel().minimumRecordTime();const endOffset=endTime-this._model.timelineModel().minimumRecordTime();const contentHelper=new Timeline.TimelineDetailsContentHelper(null,null);contentHelper.addSection(ls`Range: ${Number.millisToString(startOffset)} \u2013 ${Number.millisToString(endOffset)}`);const pieChart=Timeline.TimelineUIUtils.generatePieChart(aggregatedStats);contentHelper.appendElementRow('',pieChart);this._setContent(contentHelper.fragment);}};Timeline.TimelineDetailsView.Tab={Details:'Details',EventLog:'EventLog',CallTree:'CallTree',BottomUp:'BottomUp',PaintProfiler:'PaintProfiler',LayerViewer:'LayerViewer'};;Timeline.TimelineLoader=class{constructor(client){this._client=client;this._backingStorage=new Bindings.TempFileBackingStorage();this._tracingModel=new SDK.TracingModel(this._backingStorage);this._canceledCallback=null;this._state=Timeline.TimelineLoader.State.Initial;this._buffer='';this._firstRawChunk=true;this._firstChunk=true;this._loadedBytes=0;this._totalSize;this._jsonTokenizer=new TextUtils.TextUtils.BalancedJSONTokenizer(this._writeBalancedJSON.bind(this),true);}
static loadFromFile(file,client){const loader=new Timeline.TimelineLoader(client);const fileReader=new Bindings.ChunkedFileReader(file,Timeline.TimelineLoader.TransferChunkLengthBytes);loader._canceledCallback=fileReader.cancel.bind(fileReader);loader._totalSize=file.size;fileReader.read(loader).then(success=>{if(!success)
this._reportErrorAndCancelLoading(fileReader.error().message);});return loader;}
static loadFromEvents(events,client){const loader=new Timeline.TimelineLoader(client);setTimeout(async()=>{const eventsPerChunk=5000;client.loadingStarted();for(let i=0;i<events.length;i+=eventsPerChunk){const chunk=events.slice(i,i+eventsPerChunk);loader._tracingModel.addEvents(chunk);client.loadingProgress((i+chunk.length)/events.length);await new Promise(r=>setTimeout(r));}
loader.close();});return loader;}
static loadFromURL(url,client){const loader=new Timeline.TimelineLoader(client);Host.ResourceLoader.loadAsStream(url,null,loader);return loader;}
cancel(){this._tracingModel=null;this._backingStorage.reset();this._client.loadingComplete(null);this._client=null;if(this._canceledCallback)
this._canceledCallback();}
write(chunk){if(!this._client)
return Promise.resolve();this._loadedBytes+=chunk.length;if(this._firstRawChunk)
this._client.loadingStarted();else
this._client.loadingProgress(this._totalSize?this._loadedBytes/this._totalSize:undefined);this._firstRawChunk=false;if(this._state===Timeline.TimelineLoader.State.Initial){if(chunk.startsWith('{"nodes":[')){this._state=Timeline.TimelineLoader.State.LoadingCPUProfileFormat;}else if(chunk[0]==='{'){this._state=Timeline.TimelineLoader.State.LookingForEvents;}else if(chunk[0]==='['){this._state=Timeline.TimelineLoader.State.ReadingEvents;}else{this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline data: Unknown JSON format'));return Promise.resolve();}}
if(this._state===Timeline.TimelineLoader.State.LoadingCPUProfileFormat){this._buffer+=chunk;return Promise.resolve();}
if(this._state===Timeline.TimelineLoader.State.LookingForEvents){const objectName='"traceEvents":';const startPos=this._buffer.length-objectName.length;this._buffer+=chunk;const pos=this._buffer.indexOf(objectName,startPos);if(pos===-1)
return Promise.resolve();chunk=this._buffer.slice(pos+objectName.length);this._state=Timeline.TimelineLoader.State.ReadingEvents;}
if(this._state!==Timeline.TimelineLoader.State.ReadingEvents)
return Promise.resolve();if(this._jsonTokenizer.write(chunk))
return Promise.resolve();this._state=Timeline.TimelineLoader.State.SkippingTail;if(this._firstChunk)
this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline input, wrong JSON brackets balance'));return Promise.resolve();}
_writeBalancedJSON(data){let json=data+']';if(!this._firstChunk){const commaIndex=json.indexOf(',');if(commaIndex!==-1)
json=json.slice(commaIndex+1);json='['+json;}
let items;try{items=(JSON.parse(json));}catch(e){this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline data: %s',e.toString()));return;}
if(this._firstChunk){this._firstChunk=false;if(this._looksLikeAppVersion(items[0])){this._reportErrorAndCancelLoading(Common.UIString('Legacy Timeline format is not supported.'));return;}}
try{this._tracingModel.addEvents(items);}catch(e){this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline data: %s',e.toString()));}}
_reportErrorAndCancelLoading(message){if(message)
Common.console.error(message);this.cancel();}
_looksLikeAppVersion(item){return typeof item==='string'&&item.indexOf('Chrome')!==-1;}
close(){if(!this._client)
return;this._client.processingStarted();setTimeout(()=>this._finalizeTrace(),0);}
_finalizeTrace(){if(this._state===Timeline.TimelineLoader.State.LoadingCPUProfileFormat){this._parseCPUProfileFormat(this._buffer);this._buffer='';}
this._tracingModel.tracingComplete();this._client.loadingComplete(this._tracingModel);}
_parseCPUProfileFormat(text){let traceEvents;try{const profile=JSON.parse(text);traceEvents=TimelineModel.TimelineJSProfileProcessor.buildTraceProfileFromCpuProfile(profile);}catch(e){this._reportErrorAndCancelLoading(Common.UIString('Malformed CPU profile format'));return;}
this._tracingModel.addEvents(traceEvents);}};Timeline.TimelineLoader.TransferChunkLengthBytes=5000000;Timeline.TimelineLoader.Client=function(){};Timeline.TimelineLoader.Client.prototype={loadingStarted(){},loadingProgress(progress){},processingStarted(){},loadingComplete(tracingModel){},};Timeline.TimelineLoader.State={Initial:Symbol('Initial'),LookingForEvents:Symbol('LookingForEvents'),ReadingEvents:Symbol('ReadingEvents'),SkippingTail:Symbol('SkippingTail'),LoadingCPUProfileFormat:Symbol('LoadingCPUProfileFormat')};;Timeline.TimelineEventOverview=class extends PerfUI.TimelineOverviewBase{constructor(id,title){super();this.element.id='timeline-overview-'+id;this.element.classList.add('overview-strip');this._model=null;if(title)
this.element.createChild('div','timeline-overview-strip-title').textContent=title;}
setModel(model){this._model=model;}
_renderBar(begin,end,position,height,color){const x=begin;const width=end-begin;const ctx=this.context();ctx.fillStyle=color;ctx.fillRect(x,position,width,height);}};Timeline.TimelineEventOverviewInput=class extends Timeline.TimelineEventOverview{constructor(){super('input',null);}
update(){super.update();if(!this._model)
return;const height=this.height();const descriptors=Timeline.TimelineUIUtils.eventDispatchDesciptors();const descriptorsByType=new Map();let maxPriority=-1;for(const descriptor of descriptors){for(const type of descriptor.eventTypes)
descriptorsByType.set(type,descriptor);maxPriority=Math.max(maxPriority,descriptor.priority);}
const minWidth=2*window.devicePixelRatio;const timeOffset=this._model.timelineModel().minimumRecordTime();const timeSpan=this._model.timelineModel().maximumRecordTime()-timeOffset;const canvasWidth=this.width();const scale=canvasWidth/timeSpan;for(let priority=0;priority<=maxPriority;++priority){for(const track of this._model.timelineModel().tracks()){for(let i=0;i<track.events.length;++i){const event=track.events[i];if(event.name!==TimelineModel.TimelineModel.RecordType.EventDispatch)
continue;const descriptor=descriptorsByType.get(event.args['data']['type']);if(!descriptor||descriptor.priority!==priority)
continue;const start=Number.constrain(Math.floor((event.startTime-timeOffset)*scale),0,canvasWidth);const end=Number.constrain(Math.ceil((event.endTime-timeOffset)*scale),0,canvasWidth);const width=Math.max(end-start,minWidth);this._renderBar(start,start+width,0,height,descriptor.color);}}}}};Timeline.TimelineEventOverviewNetwork=class extends Timeline.TimelineEventOverview{constructor(){super('network',Common.UIString('NET'));}
update(){super.update();if(!this._model)
return;const timelineModel=this._model.timelineModel();const bandHeight=this.height()/2;const timeOffset=timelineModel.minimumRecordTime();const timeSpan=timelineModel.maximumRecordTime()-timeOffset;const canvasWidth=this.width();const scale=canvasWidth/timeSpan;const highPath=new Path2D();const lowPath=new Path2D();const priorities=Protocol.Network.ResourcePriority;const highPrioritySet=new Set([priorities.VeryHigh,priorities.High,priorities.Medium]);for(const request of timelineModel.networkRequests()){const path=highPrioritySet.has(request.priority)?highPath:lowPath;const s=Math.max(Math.floor((request.startTime-timeOffset)*scale),0);const e=Math.min(Math.ceil((request.endTime-timeOffset)*scale+1),canvasWidth);path.rect(s,0,e-s,bandHeight-1);}
const ctx=this.context();ctx.save();ctx.fillStyle='hsl(214, 60%, 60%)';ctx.fill((highPath));ctx.translate(0,bandHeight);ctx.fillStyle='hsl(214, 80%, 80%)';ctx.fill((lowPath));ctx.restore();}};Timeline.TimelineEventOverviewCPUActivity=class extends Timeline.TimelineEventOverview{constructor(){super('cpu-activity',Common.UIString('CPU'));this._backgroundCanvas=this.element.createChild('canvas','fill background');}
resetCanvas(){super.resetCanvas();this._backgroundCanvas.width=this.element.clientWidth*window.devicePixelRatio;this._backgroundCanvas.height=this.element.clientHeight*window.devicePixelRatio;}
update(){super.update();if(!this._model)
return;const timelineModel=this._model.timelineModel();const quantSizePx=4*window.devicePixelRatio;const width=this.width();const height=this.height();const baseLine=height;const timeOffset=timelineModel.minimumRecordTime();const timeSpan=timelineModel.maximumRecordTime()-timeOffset;const scale=width/timeSpan;const quantTime=quantSizePx/scale;const categories=Timeline.TimelineUIUtils.categories();const categoryOrder=['idle','loading','painting','rendering','scripting','other'];const otherIndex=categoryOrder.indexOf('other');const idleIndex=0;console.assert(idleIndex===categoryOrder.indexOf('idle'));for(let i=idleIndex+1;i<categoryOrder.length;++i)
categories[categoryOrder[i]]._overviewIndex=i;const backgroundContext=this._backgroundCanvas.getContext('2d');for(const track of timelineModel.tracks()){if(track.type===TimelineModel.TimelineModel.TrackType.MainThread&&track.forMainFrame)
drawThreadEvents(this.context(),track.events);else
drawThreadEvents(backgroundContext,track.events);}
applyPattern(backgroundContext);function drawThreadEvents(ctx,events){const quantizer=new Timeline.Quantizer(timeOffset,quantTime,drawSample);let x=0;const categoryIndexStack=[];const paths=[];const lastY=[];for(let i=0;i<categoryOrder.length;++i){paths[i]=new Path2D();paths[i].moveTo(0,height);lastY[i]=height;}
function drawSample(counters){let y=baseLine;for(let i=idleIndex+1;i<categoryOrder.length;++i){const h=(counters[i]||0)/quantTime*height;y-=h;paths[i].bezierCurveTo(x,lastY[i],x,y,x+quantSizePx/2,y);lastY[i]=y;}
x+=quantSizePx;}
function onEventStart(e){const index=categoryIndexStack.length?categoryIndexStack.peekLast():idleIndex;quantizer.appendInterval(e.startTime,index);categoryIndexStack.push(Timeline.TimelineUIUtils.eventStyle(e).category._overviewIndex||otherIndex);}
function onEventEnd(e){quantizer.appendInterval(e.endTime,categoryIndexStack.pop());}
TimelineModel.TimelineModel.forEachEvent(events,onEventStart,onEventEnd);quantizer.appendInterval(timeOffset+timeSpan+quantTime,idleIndex);for(let i=categoryOrder.length-1;i>0;--i){paths[i].lineTo(width,height);ctx.fillStyle=categories[categoryOrder[i]].color;ctx.fill(paths[i]);}}
function applyPattern(ctx){const step=4*window.devicePixelRatio;ctx.save();ctx.lineWidth=step/Math.sqrt(8);for(let x=0.5;x<width+height;x+=step){ctx.moveTo(x,0);ctx.lineTo(x-height,height);}
ctx.globalCompositeOperation='destination-out';ctx.stroke();ctx.restore();}}};Timeline.TimelineEventOverviewResponsiveness=class extends Timeline.TimelineEventOverview{constructor(){super('responsiveness',null);}
update(){super.update();if(!this._model)
return;const height=this.height();const timeOffset=this._model.timelineModel().minimumRecordTime();const timeSpan=this._model.timelineModel().maximumRecordTime()-timeOffset;const scale=this.width()/timeSpan;const frames=this._model.frames();const ctx=(this.context());const fillPath=new Path2D();const markersPath=new Path2D();for(let i=0;i<frames.length;++i){const frame=frames[i];if(!frame.hasWarnings())
continue;paintWarningDecoration(frame.startTime,frame.duration);}
for(const track of this._model.timelineModel().tracks()){const events=track.events;for(let i=0;i<events.length;++i){if(!TimelineModel.TimelineData.forEvent(events[i]).warning)
continue;paintWarningDecoration(events[i].startTime,events[i].duration);}}
ctx.fillStyle='hsl(0, 80%, 90%)';ctx.strokeStyle='red';ctx.lineWidth=2*window.devicePixelRatio;ctx.fill(fillPath);ctx.stroke(markersPath);function paintWarningDecoration(time,duration){const x=Math.round(scale*(time-timeOffset));const w=Math.round(scale*duration);fillPath.rect(x,0,w,height);markersPath.moveTo(x+w,0);markersPath.lineTo(x+w,height);}}};Timeline.TimelineFilmStripOverview=class extends Timeline.TimelineEventOverview{constructor(){super('filmstrip',null);this.reset();}
update(){super.update();const frames=this._model?this._model.filmStripModel().frames():[];if(!frames.length)
return;const drawGeneration=Symbol('drawGeneration');this._drawGeneration=drawGeneration;this._imageByFrame(frames[0]).then(image=>{if(this._drawGeneration!==drawGeneration)
return;if(!image||!image.naturalWidth||!image.naturalHeight)
return;const imageHeight=this.height()-2*Timeline.TimelineFilmStripOverview.Padding;const imageWidth=Math.ceil(imageHeight*image.naturalWidth/image.naturalHeight);const popoverScale=Math.min(200/image.naturalWidth,1);this._emptyImage=new Image(image.naturalWidth*popoverScale,image.naturalHeight*popoverScale);this._drawFrames(imageWidth,imageHeight);});}
_imageByFrame(frame){let imagePromise=this._frameToImagePromise.get(frame);if(!imagePromise){imagePromise=frame.imageDataPromise().then(data=>UI.loadImageFromData(data));this._frameToImagePromise.set(frame,imagePromise);}
return imagePromise;}
_drawFrames(imageWidth,imageHeight){if(!imageWidth||!this._model)
return;const filmStripModel=this._model.filmStripModel();if(!filmStripModel.frames().length)
return;const padding=Timeline.TimelineFilmStripOverview.Padding;const width=this.width();const zeroTime=filmStripModel.zeroTime();const spanTime=filmStripModel.spanTime();const scale=spanTime/width;const context=this.context();const drawGeneration=this._drawGeneration;context.beginPath();for(let x=padding;x<width;x+=imageWidth+2*padding){const time=zeroTime+(x+imageWidth/2)*scale;const frame=filmStripModel.frameByTimestamp(time);if(!frame)
continue;context.rect(x-0.5,0.5,imageWidth+1,imageHeight+1);this._imageByFrame(frame).then(drawFrameImage.bind(this,x));}
context.strokeStyle='#ddd';context.stroke();function drawFrameImage(x,image){if(this._drawGeneration!==drawGeneration||!image)
return;context.drawImage(image,x,1,imageWidth,imageHeight);}}
overviewInfoPromise(x){if(!this._model||!this._model.filmStripModel().frames().length)
return Promise.resolve((null));const time=this.calculator().positionToTime(x);const frame=this._model.filmStripModel().frameByTimestamp(time);if(frame===this._lastFrame)
return Promise.resolve(this._lastElement);const imagePromise=frame?this._imageByFrame(frame):Promise.resolve(this._emptyImage);return imagePromise.then(createFrameElement.bind(this));function createFrameElement(image){const element=createElementWithClass('div','frame');if(image)
element.createChild('div','thumbnail').appendChild(image);this._lastFrame=frame;this._lastElement=element;return element;}}
reset(){this._lastFrame=undefined;this._lastElement=null;this._frameToImagePromise=new Map();this._imageWidth=0;}};Timeline.TimelineFilmStripOverview.Padding=2;Timeline.TimelineEventOverviewFrames=class extends Timeline.TimelineEventOverview{constructor(){super('framerate',Common.UIString('FPS'));}
update(){super.update();if(!this._model)
return;const frames=this._model.frames();if(!frames.length)
return;const height=this.height();const padding=1*window.devicePixelRatio;const baseFrameDurationMs=1e3/60;const visualHeight=height-2*padding;const timeOffset=this._model.timelineModel().minimumRecordTime();const timeSpan=this._model.timelineModel().maximumRecordTime()-timeOffset;const scale=this.width()/timeSpan;const baseY=height-padding;const ctx=this.context();const bottomY=baseY+10*window.devicePixelRatio;let x=0;let y=bottomY;const lineWidth=window.devicePixelRatio;const offset=lineWidth&1?0.5:0;const tickDepth=1.5*window.devicePixelRatio;ctx.beginPath();ctx.moveTo(0,y);for(let i=0;i<frames.length;++i){const frame=frames[i];x=Math.round((frame.startTime-timeOffset)*scale)+offset;ctx.lineTo(x,y);ctx.lineTo(x,y+tickDepth);y=frame.idle?bottomY:Math.round(baseY-visualHeight*Math.min(baseFrameDurationMs/frame.duration,1))-offset;ctx.lineTo(x,y+tickDepth);ctx.lineTo(x,y);}
const lastFrame=frames.peekLast();x=Math.round((lastFrame.startTime+lastFrame.duration-timeOffset)*scale)+offset;ctx.lineTo(x,y);ctx.lineTo(x,bottomY);ctx.fillStyle='hsl(110, 50%, 88%)';ctx.strokeStyle='hsl(110, 50%, 60%)';ctx.lineWidth=lineWidth;ctx.fill();ctx.stroke();}};Timeline.TimelineEventOverviewMemory=class extends Timeline.TimelineEventOverview{constructor(){super('memory',Common.UIString('HEAP'));this._heapSizeLabel=this.element.createChild('div','memory-graph-label');}
resetHeapSizeLabels(){this._heapSizeLabel.textContent='';}
update(){super.update();const ratio=window.devicePixelRatio;if(!this._model){this.resetHeapSizeLabels();return;}
const tracks=this._model.timelineModel().tracks().filter(track=>track.type===TimelineModel.TimelineModel.TrackType.MainThread&&track.forMainFrame);const trackEvents=tracks.map(track=>track.events);const lowerOffset=3*ratio;let maxUsedHeapSize=0;let minUsedHeapSize=100000000000;const minTime=this._model.timelineModel().minimumRecordTime();const maxTime=this._model.timelineModel().maximumRecordTime();function isUpdateCountersEvent(event){return event.name===TimelineModel.TimelineModel.RecordType.UpdateCounters;}
for(let i=0;i<trackEvents.length;i++)
trackEvents[i]=trackEvents[i].filter(isUpdateCountersEvent);function calculateMinMaxSizes(event){const counters=event.args.data;if(!counters||!counters.jsHeapSizeUsed)
return;maxUsedHeapSize=Math.max(maxUsedHeapSize,counters.jsHeapSizeUsed);minUsedHeapSize=Math.min(minUsedHeapSize,counters.jsHeapSizeUsed);}
for(let i=0;i<trackEvents.length;i++)
trackEvents[i].forEach(calculateMinMaxSizes);minUsedHeapSize=Math.min(minUsedHeapSize,maxUsedHeapSize);const lineWidth=1;const width=this.width();const height=this.height()-lowerOffset;const xFactor=width/(maxTime-minTime);const yFactor=(height-lineWidth)/Math.max(maxUsedHeapSize-minUsedHeapSize,1);const histogram=new Array(width);function buildHistogram(event){const counters=event.args.data;if(!counters||!counters.jsHeapSizeUsed)
return;const x=Math.round((event.startTime-minTime)*xFactor);const y=Math.round((counters.jsHeapSizeUsed-minUsedHeapSize)*yFactor);histogram[x]=Math.max(histogram[x]||0,y);}
for(let i=0;i<trackEvents.length;i++)
trackEvents[i].forEach(buildHistogram);const ctx=this.context();const heightBeyondView=height+lowerOffset+lineWidth;ctx.translate(0.5,0.5);ctx.beginPath();ctx.moveTo(-lineWidth,heightBeyondView);let y=0;let isFirstPoint=true;let lastX=0;for(let x=0;x<histogram.length;x++){if(typeof histogram[x]==='undefined')
continue;if(isFirstPoint){isFirstPoint=false;y=histogram[x];ctx.lineTo(-lineWidth,height-y);}
const nextY=histogram[x];if(Math.abs(nextY-y)>2&&Math.abs(x-lastX)>1)
ctx.lineTo(x,height-y);y=nextY;ctx.lineTo(x,height-y);lastX=x;}
ctx.lineTo(width+lineWidth,height-y);ctx.lineTo(width+lineWidth,heightBeyondView);ctx.closePath();ctx.fillStyle='hsla(220, 90%, 70%, 0.2)';ctx.fill();ctx.lineWidth=lineWidth;ctx.strokeStyle='hsl(220, 90%, 70%)';ctx.stroke();this._heapSizeLabel.textContent=Common.UIString('%s \u2013 %s',Number.bytesToString(minUsedHeapSize),Number.bytesToString(maxUsedHeapSize));}};Timeline.Quantizer=class{constructor(startTime,quantDuration,callback){this._lastTime=startTime;this._quantDuration=quantDuration;this._callback=callback;this._counters=[];this._remainder=quantDuration;}
appendInterval(time,group){let interval=time-this._lastTime;if(interval<=this._remainder){this._counters[group]=(this._counters[group]||0)+interval;this._remainder-=interval;this._lastTime=time;return;}
this._counters[group]=(this._counters[group]||0)+this._remainder;this._callback(this._counters);interval-=this._remainder;while(interval>=this._quantDuration){const counters=[];counters[group]=this._quantDuration;this._callback(counters);interval-=this._quantDuration;}
this._counters=[];this._counters[group]=interval;this._lastTime=time;this._remainder=this._quantDuration-interval;}};;Timeline.TimelineFilters={};Timeline.TimelineFilters.IsLong=class extends TimelineModel.TimelineModelFilter{constructor(){super();this._minimumRecordDuration=0;}
setMinimumRecordDuration(value){this._minimumRecordDuration=value;}
accept(event){const duration=event.endTime?event.endTime-event.startTime:0;return duration>=this._minimumRecordDuration;}};Timeline.TimelineFilters.Category=class extends TimelineModel.TimelineModelFilter{constructor(){super();}
accept(event){return!Timeline.TimelineUIUtils.eventStyle(event).category.hidden;}};Timeline.TimelineFilters.RegExp=class extends TimelineModel.TimelineModelFilter{constructor(regExp){super();this._regExp;this.setRegExp(regExp||null);}
setRegExp(regExp){this._regExp=regExp;}
regExp(){return this._regExp;}
accept(event){return!this._regExp||Timeline.TimelineUIUtils.testContentMatching(event,this._regExp);}};;Timeline.TimelineFlameChartDataProvider=class extends Common.Object{constructor(){super();this.reset();this._font='11px '+Host.fontFamily();this._timelineData=null;this._currentLevel=0;this._performanceModel=null;this._model=null;this._minimumBoundary=0;this._maximumBoundary=0;this._timeSpan=0;this._consoleColorGenerator=new Common.Color.Generator({min:30,max:55},{min:70,max:100,count:6},50,0.7);this._extensionColorGenerator=new Common.Color.Generator({min:210,max:300},{min:70,max:100,count:6},70,0.7);this._headerLevel1=this._buildGroupStyle({shareHeaderLine:false});this._headerLevel2=this._buildGroupStyle({padding:2,nestingLevel:1,collapsible:false});this._staticHeader=this._buildGroupStyle({collapsible:false});this._framesHeader=this._buildGroupStyle({useFirstLineForOverview:true});this._screenshotsHeader=this._buildGroupStyle({useFirstLineForOverview:true,nestingLevel:1,collapsible:false,itemsHeight:150});this._interactionsHeaderLevel1=this._buildGroupStyle({useFirstLineForOverview:true});this._interactionsHeaderLevel2=this._buildGroupStyle({padding:2,nestingLevel:1});this._flowEventIndexById=new Map();}
_buildGroupStyle(extra){const defaultGroupStyle={padding:4,height:17,collapsible:true,color:UI.themeSupport.patchColorText('#222',UI.ThemeSupport.ColorUsage.Foreground),backgroundColor:UI.themeSupport.patchColorText('white',UI.ThemeSupport.ColorUsage.Background),font:this._font,nestingLevel:0,shareHeaderLine:true};return(Object.assign(defaultGroupStyle,extra));}
setModel(performanceModel){this.reset();this._performanceModel=performanceModel;this._model=performanceModel&&performanceModel.timelineModel();}
groupTrack(group){return group._track||null;}
entryTitle(entryIndex){const entryTypes=Timeline.TimelineFlameChartDataProvider.EntryType;const entryType=this._entryType(entryIndex);if(entryType===entryTypes.Event){const event=(this._entryData[entryIndex]);if(event.phase===SDK.TracingModel.Phase.AsyncStepInto||event.phase===SDK.TracingModel.Phase.AsyncStepPast)
return event.name+':'+event.args['step'];if(event._blackboxRoot)
return Common.UIString('Blackboxed');const name=Timeline.TimelineUIUtils.eventStyle(event).title;const detailsText=Timeline.TimelineUIUtils.buildDetailsTextForTraceEvent(event,this._model.targetByEvent(event));if(event.name===TimelineModel.TimelineModel.RecordType.JSFrame&&detailsText)
return detailsText;return detailsText?Common.UIString('%s (%s)',name,detailsText):name;}
if(entryType===entryTypes.ExtensionEvent){const event=(this._entryData[entryIndex]);return event.name;}
if(entryType===entryTypes.Screenshot)
return'';let title=this._entryIndexToTitle[entryIndex];if(!title){title=Common.UIString('Unexpected entryIndex %d',entryIndex);console.error(title);}
return title;}
textColor(index){const event=this._entryData[index];return event&&event._blackboxRoot?'#888':Timeline.FlameChartStyle.textColor;}
entryFont(index){return this._font;}
reset(){this._currentLevel=0;this._timelineData=null;this._entryData=[];this._entryParent=[];this._entryTypeByLevel=[];this._entryIndexToTitle=[];this._markers=[];this._asyncColorByCategory=new Map();this._asyncColorByInteractionPhase=new Map();this._extensionInfo=[];this._screenshotImageCache=new Map();}
maxStackDepth(){return this._currentLevel;}
timelineData(){if(this._timelineData)
return this._timelineData;this._timelineData=new PerfUI.FlameChart.TimelineData([],[],[],[]);if(!this._model)
return this._timelineData;this._flowEventIndexById.clear();this._minimumBoundary=this._model.minimumRecordTime();this._timeSpan=this._model.isEmpty()?1000:this._model.maximumRecordTime()-this._minimumBoundary;this._currentLevel=0;if(this._model.isGenericTrace())
this._processGenericTrace();else
this._processInspectorTrace();return this._timelineData;}
_processGenericTrace(){const processGroupStyle=this._buildGroupStyle({shareHeaderLine:false});const threadGroupStyle=this._buildGroupStyle({padding:2,nestingLevel:1,shareHeaderLine:false});const eventEntryType=Timeline.TimelineFlameChartDataProvider.EntryType.Event;const tracksByProcess=new Multimap();for(const track of this._model.tracks())
tracksByProcess.set(track.thread.process(),track);for(const process of tracksByProcess.keysArray()){if(tracksByProcess.size>1){const name=`${process.name()} ${process.id()}`;this._appendHeader(name,processGroupStyle,false);}
for(const track of tracksByProcess.get(process)){const group=this._appendSyncEvents(track,track.events,track.name,threadGroupStyle,eventEntryType,true);if(!this._timelineData.selectedGroup||track.name===TimelineModel.TimelineModel.BrowserMainThreadName)
this._timelineData.selectedGroup=group;}}}
_processInspectorTrace(){this._appendFrameBars();this._appendInteractionRecords();const eventEntryType=Timeline.TimelineFlameChartDataProvider.EntryType.Event;const weight=track=>{switch(track.type){case TimelineModel.TimelineModel.TrackType.Input:return 0;case TimelineModel.TimelineModel.TrackType.Animation:return 1;case TimelineModel.TimelineModel.TrackType.UserTiming:return 2;case TimelineModel.TimelineModel.TrackType.Console:return 3;case TimelineModel.TimelineModel.TrackType.MainThread:return track.forMainFrame?4:5;case TimelineModel.TimelineModel.TrackType.Worker:return 6;case TimelineModel.TimelineModel.TrackType.Raster:return 7;case TimelineModel.TimelineModel.TrackType.GPU:return 8;case TimelineModel.TimelineModel.TrackType.Other:return 9;}};const tracks=this._model.tracks().slice();tracks.stableSort((a,b)=>weight(a)-weight(b));let rasterCount=0;for(const track of tracks){switch(track.type){case TimelineModel.TimelineModel.TrackType.Input:this._appendAsyncEventsGroup(track,ls`Input`,track.asyncEvents,this._interactionsHeaderLevel2,eventEntryType,false);break;case TimelineModel.TimelineModel.TrackType.Animation:this._appendAsyncEventsGroup(track,ls`Animation`,track.asyncEvents,this._interactionsHeaderLevel2,eventEntryType,false);break;case TimelineModel.TimelineModel.TrackType.UserTiming:this._appendAsyncEventsGroup(track,ls`User Timing`,track.asyncEvents,this._headerLevel1,eventEntryType,true);break;case TimelineModel.TimelineModel.TrackType.Console:this._appendAsyncEventsGroup(track,ls`Console`,track.asyncEvents,this._headerLevel1,eventEntryType,true);break;case TimelineModel.TimelineModel.TrackType.MainThread:if(track.forMainFrame){const group=this._appendSyncEvents(track,track.events,track.url?ls`Main \u2014 ${track.url}`:ls`Main`,this._headerLevel1,eventEntryType,true);if(group)
this._timelineData.selectedGroup=group;}else{this._appendSyncEvents(track,track.events,track.url?ls`Frame \u2014 ${track.url}`:ls`Subframe`,this._headerLevel1,eventEntryType,true);}
break;case TimelineModel.TimelineModel.TrackType.Worker:this._appendSyncEvents(track,track.events,track.url?ls`Worker \u2014 ${track.url}`:ls`Dedicated Worker`,this._headerLevel1,eventEntryType,true);break;case TimelineModel.TimelineModel.TrackType.Raster:if(!rasterCount)
this._appendHeader(ls`Raster`,this._headerLevel1,false);++rasterCount;this._appendSyncEvents(track,track.events,ls`Rasterizer Thread ${rasterCount}`,this._headerLevel2,eventEntryType,true);break;case TimelineModel.TimelineModel.TrackType.GPU:this._appendSyncEvents(track,track.events,ls`GPU`,this._headerLevel1,eventEntryType,true);break;case TimelineModel.TimelineModel.TrackType.Other:this._appendSyncEvents(track,track.events,track.name||ls`Thread`,this._headerLevel1,eventEntryType,true);this._appendAsyncEventsGroup(track,track.name,track.asyncEvents,this._headerLevel1,eventEntryType,true);break;}}
if(this._timelineData.selectedGroup)
this._timelineData.selectedGroup.expanded=true;for(let extensionIndex=0;extensionIndex<this._extensionInfo.length;extensionIndex++)
this._innerAppendExtensionEvents(extensionIndex);this._markers.sort((a,b)=>a.startTime()-b.startTime());this._timelineData.markers=this._markers;this._flowEventIndexById.clear();}
minimumBoundary(){return this._minimumBoundary;}
totalTime(){return this._timeSpan;}
search(startTime,endTime,filter){const result=[];const entryTypes=Timeline.TimelineFlameChartDataProvider.EntryType;this.timelineData();for(let i=0;i<this._entryData.length;++i){if(this._entryType(i)!==entryTypes.Event)
continue;const event=(this._entryData[i]);if(event.startTime>endTime)
continue;if((event.endTime||event.startTime)<startTime)
continue;if(filter.accept(event))
result.push(i);}
result.sort((a,b)=>SDK.TracingModel.Event.compareStartTime((this._entryData[a]),(this._entryData[b])));return result;}
_appendSyncEvents(track,events,title,style,entryType,selectable){if(!events.length)
return null;const isExtension=entryType===Timeline.TimelineFlameChartDataProvider.EntryType.ExtensionEvent;const openEvents=[];const flowEventsEnabled=Runtime.experiments.isEnabled('timelineFlowEvents');const blackboxingEnabled=!isExtension&&Runtime.experiments.isEnabled('blackboxJSFramesOnTimeline');let maxStackDepth=0;let group=null;if(track&&track.type===TimelineModel.TimelineModel.TrackType.MainThread){group=this._appendHeader(title,style,selectable);group._track=track;}
const markerEventsFilter=Timeline.TimelineUIUtils.paintEventsFilter();for(let i=0;i<events.length;++i){const e=events[i];if(!isExtension&&TimelineModel.TimelineModel.isMarkerEvent(e)&&markerEventsFilter.accept(e)){this._markers.push(new Timeline.TimelineFlameChartMarker(e.startTime,e.startTime-this._model.minimumRecordTime(),Timeline.TimelineUIUtils.markerStyleForEvent(e)));}
if(!SDK.TracingModel.isFlowPhase(e.phase)){if(!e.endTime&&e.phase!==SDK.TracingModel.Phase.Instant)
continue;if(SDK.TracingModel.isAsyncPhase(e.phase))
continue;if(!isExtension&&!this._performanceModel.isVisible(e))
continue;}
while(openEvents.length&&openEvents.peekLast().endTime<=e.startTime)
openEvents.pop();e._blackboxRoot=false;if(blackboxingEnabled&&this._isBlackboxedEvent(e)){const parent=openEvents.peekLast();if(parent&&parent._blackboxRoot)
continue;e._blackboxRoot=true;}
if(!group){group=this._appendHeader(title,style,selectable);if(selectable)
group._track=track;}
const level=this._currentLevel+openEvents.length;if(flowEventsEnabled)
this._appendFlowEvent(e,level);const index=this._appendEvent(e,level);if(openEvents.length)
this._entryParent[index]=openEvents.peekLast();if(!isExtension&&TimelineModel.TimelineModel.isMarkerEvent(e))
this._timelineData.entryTotalTimes[this._entryData.length]=undefined;maxStackDepth=Math.max(maxStackDepth,openEvents.length+1);if(e.endTime)
openEvents.push(e);}
this._entryTypeByLevel.length=this._currentLevel+maxStackDepth;this._entryTypeByLevel.fill(entryType,this._currentLevel);this._currentLevel+=maxStackDepth;return group;}
_isBlackboxedEvent(event){if(event.name!==TimelineModel.TimelineModel.RecordType.JSFrame)
return false;const url=event.args['data']['url'];return url&&this._isBlackboxedURL(url);}
_isBlackboxedURL(url){return Bindings.blackboxManager.isBlackboxedURL(url);}
_appendAsyncEventsGroup(track,header,events,style,entryType,selectable){if(!events.length)
return null;const lastUsedTimeByLevel=[];let group=null;for(let i=0;i<events.length;++i){const asyncEvent=events[i];if(!this._performanceModel.isVisible(asyncEvent))
continue;if(!group){group=this._appendHeader(header,style,selectable);if(selectable)
group._track=track;}
const startTime=asyncEvent.startTime;let level;for(level=0;level<lastUsedTimeByLevel.length&&lastUsedTimeByLevel[level]>startTime;++level){}
this._appendAsyncEvent(asyncEvent,this._currentLevel+level);lastUsedTimeByLevel[level]=asyncEvent.endTime;}
this._entryTypeByLevel.length=this._currentLevel+lastUsedTimeByLevel.length;this._entryTypeByLevel.fill(entryType,this._currentLevel);this._currentLevel+=lastUsedTimeByLevel.length;return group;}
_appendInteractionRecords(){const interactionRecords=this._performanceModel.interactionRecords();if(!interactionRecords.length)
return;this._appendHeader(ls`Interactions`,this._interactionsHeaderLevel1,false);for(const segment of interactionRecords){const index=this._entryData.length;this._entryData.push((segment.data));this._entryIndexToTitle[index]=(segment.data);this._timelineData.entryLevels[index]=this._currentLevel;this._timelineData.entryTotalTimes[index]=segment.end-segment.begin;this._timelineData.entryStartTimes[index]=segment.begin;}
this._entryTypeByLevel[this._currentLevel++]=Timeline.TimelineFlameChartDataProvider.EntryType.InteractionRecord;}
_appendFrameBars(){const screenshots=this._performanceModel.filmStripModel().frames();const hasFilmStrip=!!screenshots.length;this._framesHeader.collapsible=hasFilmStrip;this._appendHeader(Common.UIString('Frames'),this._framesHeader,false);this._frameGroup=this._timelineData.groups.peekLast();const style=Timeline.TimelineUIUtils.markerStyleForFrame();this._entryTypeByLevel[this._currentLevel]=Timeline.TimelineFlameChartDataProvider.EntryType.Frame;for(const frame of this._performanceModel.frames()){this._markers.push(new Timeline.TimelineFlameChartMarker(frame.startTime,frame.startTime-this._model.minimumRecordTime(),style));this._appendFrame(frame);}
++this._currentLevel;if(!hasFilmStrip)
return;this._appendHeader('',this._screenshotsHeader,false);this._entryTypeByLevel[this._currentLevel]=Timeline.TimelineFlameChartDataProvider.EntryType.Screenshot;let prevTimestamp;for(const screenshot of screenshots){this._entryData.push(screenshot);this._timelineData.entryLevels.push(this._currentLevel);this._timelineData.entryStartTimes.push(screenshot.timestamp);if(prevTimestamp)
this._timelineData.entryTotalTimes.push(screenshot.timestamp-prevTimestamp);prevTimestamp=screenshot.timestamp;}
if(screenshots.length)
this._timelineData.entryTotalTimes.push(this._model.maximumRecordTime()-prevTimestamp);++this._currentLevel;}
_entryType(entryIndex){return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]];}
prepareHighlightedEntryInfo(entryIndex){let time='';let title;let warning;const type=this._entryType(entryIndex);if(type===Timeline.TimelineFlameChartDataProvider.EntryType.Event){const event=(this._entryData[entryIndex]);const totalTime=event.duration;const selfTime=event.selfTime;const eps=1e-6;if(typeof totalTime==='number'){time=Math.abs(totalTime-selfTime)>eps&&selfTime>eps?Common.UIString('%s (self %s)',Number.millisToString(totalTime,true),Number.millisToString(selfTime,true)):Number.millisToString(totalTime,true);}
title=this.entryTitle(entryIndex);warning=Timeline.TimelineUIUtils.eventWarning(event);}else if(type===Timeline.TimelineFlameChartDataProvider.EntryType.Frame){const frame=(this._entryData[entryIndex]);time=Common.UIString('%s ~ %.0f\xa0fps',Number.preciseMillisToString(frame.duration,1),(1000/frame.duration));title=frame.idle?Common.UIString('Idle Frame'):Common.UIString('Frame');if(frame.hasWarnings()){warning=createElement('span');warning.textContent=Common.UIString('Long frame');}}else{return null;}
const element=createElement('div');const root=UI.createShadowRootWithCoreStyles(element,'timeline/timelineFlamechartPopover.css');const contents=root.createChild('div','timeline-flamechart-popover');contents.createChild('span','timeline-info-time').textContent=time;contents.createChild('span','timeline-info-title').textContent=title;if(warning){warning.classList.add('timeline-info-warning');contents.appendChild(warning);}
return element;}
entryColor(entryIndex){function patchColorAndCache(cache,key,lookupColor){let color=cache.get(key);if(color)
return color;const parsedColor=Common.Color.parse(lookupColor(key));color=parsedColor.setAlpha(0.7).asString(Common.Color.Format.RGBA)||'';cache.set(key,color);return color;}
const entryTypes=Timeline.TimelineFlameChartDataProvider.EntryType;const type=this._entryType(entryIndex);if(type===entryTypes.Event){const event=(this._entryData[entryIndex]);if(this._model.isGenericTrace())
return this._genericTraceEventColor(event);if(!SDK.TracingModel.isAsyncPhase(event.phase))
return this._colorForEvent(event);if(event.hasCategory(TimelineModel.TimelineModel.Category.Console)||event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming))
return this._consoleColorGenerator.colorForID(event.name);if(event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)){const phase=TimelineModel.TimelineIRModel.phaseForEvent(event)||TimelineModel.TimelineIRModel.Phases.Uncategorized;return patchColorAndCache(this._asyncColorByInteractionPhase,phase,Timeline.TimelineUIUtils.interactionPhaseColor);}
const category=Timeline.TimelineUIUtils.eventStyle(event).category;return patchColorAndCache(this._asyncColorByCategory,category,()=>category.color);}
if(type===entryTypes.Frame)
return'white';if(type===entryTypes.InteractionRecord)
return'transparent';if(type===entryTypes.ExtensionEvent){const event=(this._entryData[entryIndex]);return this._extensionColorGenerator.colorForID(event.name);}
return'';}
_genericTraceEventColor(event){const key=event.categoriesString||event.name;return key?`hsl(${String.hashCode(key) % 300 + 30}, 40%, 70%)`:'#ccc';}
_drawFrame(entryIndex,context,text,barX,barY,barWidth,barHeight){const hPadding=1;const frame=(this._entryData[entryIndex]);barX+=hPadding;barWidth-=2*hPadding;context.fillStyle=frame.idle?'white':(frame.hasWarnings()?'#fad1d1':'#d7f0d1');context.fillRect(barX,barY,barWidth,barHeight);const frameDurationText=Number.preciseMillisToString(frame.duration,1);const textWidth=context.measureText(frameDurationText).width;if(textWidth<=barWidth){context.fillStyle=this.textColor(entryIndex);context.fillText(frameDurationText,barX+(barWidth-textWidth)/2,barY+barHeight-4);}}
async _drawScreenshot(entryIndex,context,barX,barY,barWidth,barHeight){const screenshot=(this._entryData[entryIndex]);if(!this._screenshotImageCache.has(screenshot)){this._screenshotImageCache.set(screenshot,null);const data=await screenshot.imageDataPromise();const image=await UI.loadImageFromData(data);this._screenshotImageCache.set(screenshot,image);this.dispatchEventToListeners(Timeline.TimelineFlameChartDataProvider.Events.DataChanged);return;}
const image=this._screenshotImageCache.get(screenshot);if(!image)
return;const imageX=barX+1;const imageY=barY+1;const imageHeight=barHeight-2;const scale=imageHeight/image.naturalHeight;const imageWidth=Math.floor(image.naturalWidth*scale);context.save();context.beginPath();context.rect(barX,barY,barWidth,barHeight);context.clip();context.drawImage(image,imageX,imageY,imageWidth,imageHeight);context.strokeStyle='#ccc';context.strokeRect(imageX-0.5,imageY-0.5,Math.min(barWidth-1,imageWidth+1),imageHeight);context.restore();}
decorateEntry(entryIndex,context,text,barX,barY,barWidth,barHeight,unclippedBarX,timeToPixels){const data=this._entryData[entryIndex];const type=this._entryType(entryIndex);const entryTypes=Timeline.TimelineFlameChartDataProvider.EntryType;if(type===entryTypes.Frame){this._drawFrame(entryIndex,context,text,barX,barY,barWidth,barHeight);return true;}
if(type===entryTypes.Screenshot){this._drawScreenshot(entryIndex,context,barX,barY,barWidth,barHeight);return true;}
if(type===entryTypes.InteractionRecord){const color=Timeline.TimelineUIUtils.interactionPhaseColor((data));context.fillStyle=color;context.fillRect(barX,barY,barWidth-1,2);context.fillRect(barX,barY-3,2,3);context.fillRect(barX+barWidth-3,barY-3,2,3);return false;}
if(type===entryTypes.Event){const event=(data);if(event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)){const timeWaitingForMainThread=TimelineModel.TimelineData.forEvent(event).timeWaitingForMainThread;if(timeWaitingForMainThread){context.fillStyle='hsla(0, 70%, 60%, 1)';const width=Math.floor(unclippedBarX-barX+timeWaitingForMainThread*timeToPixels);context.fillRect(barX,barY+barHeight-3,width,2);}}
if(TimelineModel.TimelineData.forEvent(event).warning)
paintWarningDecoration(barX,barWidth-1.5);}
function paintWarningDecoration(x,width){const triangleSize=8;context.save();context.beginPath();context.rect(x,barY,width,barHeight);context.clip();context.beginPath();context.fillStyle='red';context.moveTo(x+width-triangleSize,barY);context.lineTo(x+width,barY);context.lineTo(x+width,barY+triangleSize);context.fill();context.restore();}
return false;}
forceDecoration(entryIndex){const entryTypes=Timeline.TimelineFlameChartDataProvider.EntryType;const type=this._entryType(entryIndex);if(type===entryTypes.Frame)
return true;if(type===entryTypes.Screenshot)
return true;if(type===entryTypes.Event){const event=(this._entryData[entryIndex]);return!!TimelineModel.TimelineData.forEvent(event).warning;}
return false;}
appendExtensionEvents(entry){this._extensionInfo.push(entry);if(this._timelineData)
this._innerAppendExtensionEvents(this._extensionInfo.length-1);}
_innerAppendExtensionEvents(index){const entry=this._extensionInfo[index];const entryType=Timeline.TimelineFlameChartDataProvider.EntryType.ExtensionEvent;const allThreads=[].concat(...entry.model.sortedProcesses().map(process=>process.sortedThreads()));if(!allThreads.length)
return;const singleTrack=allThreads.length===1&&(!allThreads[0].events().length||!allThreads[0].asyncEvents().length);if(!singleTrack)
this._appendHeader(entry.title,this._headerLevel1,false);const style=singleTrack?this._headerLevel2:this._headerLevel1;let threadIndex=0;for(const thread of allThreads){const title=singleTrack?entry.title:thread.name()||ls`Thread ${++threadIndex}`;this._appendAsyncEventsGroup(null,title,thread.asyncEvents(),style,entryType,false);this._appendSyncEvents(null,thread.events(),title,style,entryType,false);}}
_appendHeader(title,style,selectable){const group={startLevel:this._currentLevel,name:title,style:style,selectable:selectable};this._timelineData.groups.push(group);return group;}
_appendEvent(event,level){const index=this._entryData.length;this._entryData.push(event);this._timelineData.entryLevels[index]=level;this._timelineData.entryTotalTimes[index]=event.duration||Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;this._timelineData.entryStartTimes[index]=event.startTime;event[Timeline.TimelineFlameChartDataProvider._indexSymbol]=index;return index;}
_appendAsyncEvent(asyncEvent,level){if(SDK.TracingModel.isNestableAsyncPhase(asyncEvent.phase)){this._appendEvent(asyncEvent,level);return;}
const steps=asyncEvent.steps;const eventOffset=steps.length>1&&steps[1].phase===SDK.TracingModel.Phase.AsyncStepPast?1:0;for(let i=0;i<steps.length-1;++i){const index=this._entryData.length;this._entryData.push(steps[i+eventOffset]);const startTime=steps[i].startTime;this._timelineData.entryLevels[index]=level;this._timelineData.entryTotalTimes[index]=steps[i+1].startTime-startTime;this._timelineData.entryStartTimes[index]=startTime;}}
_appendFlowEvent(event,level){const timelineData=this._timelineData;function pushStartFlow(event){const flowIndex=timelineData.flowStartTimes.length;timelineData.flowStartTimes.push(event.startTime);timelineData.flowStartLevels.push(level);return flowIndex;}
function pushEndFlow(event,flowIndex){timelineData.flowEndTimes[flowIndex]=event.startTime;timelineData.flowEndLevels[flowIndex]=level;}
switch(event.phase){case SDK.TracingModel.Phase.FlowBegin:this._flowEventIndexById.set(event.id,pushStartFlow(event));break;case SDK.TracingModel.Phase.FlowStep:pushEndFlow(event,this._flowEventIndexById.get(event.id));this._flowEventIndexById.set(event.id,pushStartFlow(event));break;case SDK.TracingModel.Phase.FlowEnd:pushEndFlow(event,this._flowEventIndexById.get(event.id));this._flowEventIndexById.delete(event.id);break;}}
_appendFrame(frame){const index=this._entryData.length;this._entryData.push(frame);this._entryIndexToTitle[index]=Number.millisToString(frame.duration,true);this._timelineData.entryLevels[index]=this._currentLevel;this._timelineData.entryTotalTimes[index]=frame.duration;this._timelineData.entryStartTimes[index]=frame.startTime;}
createSelection(entryIndex){const type=this._entryType(entryIndex);let timelineSelection=null;if(type===Timeline.TimelineFlameChartDataProvider.EntryType.Event){timelineSelection=Timeline.TimelineSelection.fromTraceEvent((this._entryData[entryIndex]));}else if(type===Timeline.TimelineFlameChartDataProvider.EntryType.Frame){timelineSelection=Timeline.TimelineSelection.fromFrame((this._entryData[entryIndex]));}
if(timelineSelection)
this._lastSelection=new Timeline.TimelineFlameChartView.Selection(timelineSelection,entryIndex);return timelineSelection;}
formatValue(value,precision){return Number.preciseMillisToString(value,precision);}
canJumpToEntry(entryIndex){return false;}
entryIndexForSelection(selection){if(!selection||selection.type()===Timeline.TimelineSelection.Type.Range)
return-1;if(this._lastSelection&&this._lastSelection.timelineSelection.object()===selection.object())
return this._lastSelection.entryIndex;const index=this._entryData.indexOf((selection.object()));if(index!==-1)
this._lastSelection=new Timeline.TimelineFlameChartView.Selection(selection,index);return index;}
buildFlowForInitiator(entryIndex){if(this._lastInitiatorEntry===entryIndex)
return false;this._lastInitiatorEntry=entryIndex;let event=this.eventByIndex(entryIndex);const td=this._timelineData;td.flowStartTimes=[];td.flowStartLevels=[];td.flowEndTimes=[];td.flowEndLevels=[];while(event){let initiator;for(;event;event=this._eventParent(event)){initiator=TimelineModel.TimelineData.forEvent(event).initiator();if(initiator)
break;}
if(!initiator)
break;const eventIndex=event[Timeline.TimelineFlameChartDataProvider._indexSymbol];const initiatorIndex=initiator[Timeline.TimelineFlameChartDataProvider._indexSymbol];td.flowStartTimes.push(initiator.endTime||initiator.startTime);td.flowStartLevels.push(td.entryLevels[initiatorIndex]);td.flowEndTimes.push(event.startTime);td.flowEndLevels.push(td.entryLevels[eventIndex]);event=initiator;}
return true;}
_eventParent(event){return this._entryParent[event[Timeline.TimelineFlameChartDataProvider._indexSymbol]]||null;}
eventByIndex(entryIndex){return entryIndex>=0&&this._entryType(entryIndex)===Timeline.TimelineFlameChartDataProvider.EntryType.Event?(this._entryData[entryIndex]):null;}
setEventColorMapping(colorForEvent){this._colorForEvent=colorForEvent;}};Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs=0.001;Timeline.TimelineFlameChartDataProvider._indexSymbol=Symbol('index');Timeline.TimelineFlameChartDataProvider.Events={DataChanged:Symbol('DataChanged')};Timeline.TimelineFlameChartDataProvider.EntryType={Frame:Symbol('Frame'),Event:Symbol('Event'),InteractionRecord:Symbol('InteractionRecord'),ExtensionEvent:Symbol('ExtensionEvent'),Screenshot:Symbol('Screenshot'),};;Timeline.TimelineFlameChartNetworkDataProvider=class{constructor(){this._font='11px '+Host.fontFamily();this.setModel(null);this._style={padding:4,height:17,collapsible:true,color:UI.themeSupport.patchColorText('#222',UI.ThemeSupport.ColorUsage.Foreground),font:this._font,backgroundColor:UI.themeSupport.patchColorText('white',UI.ThemeSupport.ColorUsage.Background),nestingLevel:0,useFirstLineForOverview:false,useDecoratorsForOverview:true,shareHeaderLine:false};this._group={startLevel:0,name:Common.UIString('Network'),expanded:false,style:this._style};this._minimumBoundary=0;this._maximumBoundary=0;this._timeSpan=0;}
setModel(performanceModel){this._model=performanceModel&&performanceModel.timelineModel();this._maxLevel=0;this._timelineData=null;this._requests=[];}
isEmpty(){this.timelineData();return!this._requests.length;}
maxStackDepth(){return this._maxLevel;}
timelineData(){if(this._timelineData)
return this._timelineData;this._requests=[];this._timelineData=new PerfUI.FlameChart.TimelineData([],[],[],[]);if(this._model)
this._appendTimelineData();return this._timelineData;}
minimumBoundary(){return this._minimumBoundary;}
totalTime(){return this._timeSpan;}
setWindowTimes(startTime,endTime){this._startTime=startTime;this._endTime=endTime;this._updateTimelineData();}
createSelection(index){if(index===-1)
return null;const request=this._requests[index];this._lastSelection=new Timeline.TimelineFlameChartView.Selection(Timeline.TimelineSelection.fromNetworkRequest(request),index);return this._lastSelection.timelineSelection;}
entryIndexForSelection(selection){if(!selection)
return-1;if(this._lastSelection&&this._lastSelection.timelineSelection.object()===selection.object())
return this._lastSelection.entryIndex;if(selection.type()!==Timeline.TimelineSelection.Type.NetworkRequest)
return-1;const request=(selection.object());const index=this._requests.indexOf(request);if(index!==-1){this._lastSelection=new Timeline.TimelineFlameChartView.Selection(Timeline.TimelineSelection.fromNetworkRequest(request),index);}
return index;}
entryColor(index){const request=(this._requests[index]);const category=Timeline.TimelineUIUtils.networkRequestCategory(request);return Timeline.TimelineUIUtils.networkCategoryColor(category);}
textColor(index){return Timeline.FlameChartStyle.textColor;}
entryTitle(index){const request=(this._requests[index]);const parsedURL=new Common.ParsedURL(request.url||'');return parsedURL.isValid?`${parsedURL.displayName} (${parsedURL.host})`:request.url||null;}
entryFont(index){return this._font;}
decorateEntry(index,context,text,barX,barY,barWidth,barHeight,unclippedBarX,timeToPixelRatio){const request=(this._requests[index]);if(!request.timing)
return false;function timeToPixel(time){return Math.floor(unclippedBarX+(time-beginTime)*timeToPixelRatio);}
const minBarWidthPx=2;const beginTime=request.beginTime();const startTime=request.startTime;const endTime=request.endTime;const requestTime=request.timing.requestTime*1000;const sendStart=Math.max(timeToPixel(requestTime+request.timing.sendStart),unclippedBarX);const headersEnd=Math.max(timeToPixel(requestTime+request.timing.receiveHeadersEnd),sendStart);const finish=Math.max(timeToPixel(request.finishTime||endTime),headersEnd+minBarWidthPx);const start=timeToPixel(startTime);const end=Math.max(timeToPixel(endTime),finish);context.fillStyle='hsla(0, 100%, 100%, 0.8)';context.fillRect(sendStart+0.5,barY+0.5,headersEnd-sendStart-0.5,barHeight-2);context.fillStyle=UI.themeSupport.patchColorText('white',UI.ThemeSupport.ColorUsage.Background);context.fillRect(barX,barY-0.5,sendStart-barX,barHeight);context.fillRect(finish,barY-0.5,barX+barWidth-finish,barHeight);if(request.timing.pushStart){const pushStart=timeToPixel(request.timing.pushStart*1000);const pushEnd=timeToPixel(request.timing.pushEnd*1000);const dentSize=Number.constrain(pushEnd-pushStart-2,0,4);const padding=1;context.save();context.beginPath();context.moveTo(pushStart+dentSize,barY+barHeight/2);context.lineTo(pushStart,barY+padding);context.lineTo(pushEnd-dentSize,barY+padding);context.lineTo(pushEnd,barY+barHeight/2);context.lineTo(pushEnd-dentSize,barY+barHeight-padding);context.lineTo(pushStart,barY+barHeight-padding);context.closePath();context.fillStyle=this.entryColor(index);context.globalAlpha=0.3;context.fill();context.restore();}
function drawTick(begin,end,y){const tickHeightPx=6;context.moveTo(begin,y-tickHeightPx/2);context.lineTo(begin,y+tickHeightPx/2);context.moveTo(begin,y);context.lineTo(end,y);}
context.beginPath();context.lineWidth=1;context.strokeStyle='#ccc';const lineY=Math.floor(barY+barHeight/2)+0.5;const leftTick=start+0.5;const rightTick=end-0.5;drawTick(leftTick,sendStart,lineY);drawTick(rightTick,finish,lineY);context.stroke();if(typeof request.priority==='string'){const color=this._colorForPriority(request.priority);if(color){context.fillStyle=color;context.fillRect(sendStart+0.5,barY+0.5,3.5,3.5);}}
const textStart=Math.max(sendStart,0);const textWidth=finish-textStart;const minTextWidthPx=20;if(textWidth>=minTextWidthPx){text=this.entryTitle(index)||'';if(request.fromServiceWorker)
text='⚙ '+text;if(text){const textPadding=4;const textBaseline=5;const textBaseHeight=barHeight-textBaseline;const trimmedText=UI.trimTextEnd(context,text,textWidth-2*textPadding);context.fillStyle='#333';context.fillText(trimmedText,textStart+textPadding,barY+textBaseHeight);}}
return true;}
forceDecoration(index){return true;}
prepareHighlightedEntryInfo(index){const maxURLChars=80;const request=(this._requests[index]);if(!request.url)
return null;const element=createElement('div');const root=UI.createShadowRootWithCoreStyles(element,'timeline/timelineFlamechartPopover.css');const contents=root.createChild('div','timeline-flamechart-popover');const duration=request.endTime-request.startTime;if(request.startTime&&isFinite(duration))
contents.createChild('span','timeline-info-network-time').textContent=Number.millisToString(duration);if(typeof request.priority==='string'){const div=contents.createChild('span');div.textContent=PerfUI.uiLabelForNetworkPriority((request.priority));div.style.color=this._colorForPriority(request.priority)||'black';}
contents.createChild('span').textContent=request.url.trimMiddle(maxURLChars);return element;}
_colorForPriority(priority){if(!this._priorityToValue){const priorities=Protocol.Network.ResourcePriority;this._priorityToValue=new Map([[priorities.VeryLow,1],[priorities.Low,2],[priorities.Medium,3],[priorities.High,4],[priorities.VeryHigh,5]]);}
const value=this._priorityToValue.get(priority);return value?`hsla(214, 80%, 50%, ${value / 5})`:null;}
_appendTimelineData(){this._minimumBoundary=this._model.minimumRecordTime();this._maximumBoundary=this._model.maximumRecordTime();this._timeSpan=this._model.isEmpty()?1000:this._maximumBoundary-this._minimumBoundary;this._model.networkRequests().forEach(this._appendEntry.bind(this));this._updateTimelineData();}
_updateTimelineData(){if(!this._timelineData)
return;const lastTimeByLevel=[];let maxLevel=0;for(let i=0;i<this._requests.length;++i){const r=this._requests[i];const beginTime=r.beginTime();const visible=beginTime<this._endTime&&r.endTime>this._startTime;if(!visible){this._timelineData.entryLevels[i]=-1;continue;}
while(lastTimeByLevel.length&&lastTimeByLevel.peekLast()<=beginTime)
lastTimeByLevel.pop();this._timelineData.entryLevels[i]=lastTimeByLevel.length;lastTimeByLevel.push(r.endTime);maxLevel=Math.max(maxLevel,lastTimeByLevel.length);}
for(let i=0;i<this._requests.length;++i){if(this._timelineData.entryLevels[i]===-1)
this._timelineData.entryLevels[i]=maxLevel;}
this._timelineData=new PerfUI.FlameChart.TimelineData(this._timelineData.entryLevels,this._timelineData.entryTotalTimes,this._timelineData.entryStartTimes,[this._group]);this._maxLevel=maxLevel;}
_appendEntry(request){this._requests.push(request);this._timelineData.entryStartTimes.push(request.beginTime());this._timelineData.entryTotalTimes.push(request.endTime-request.beginTime());this._timelineData.entryLevels.push(this._requests.length-1);}
preferredHeight(){return this._style.height*(this._group.expanded?Number.constrain(this._maxLevel+1,4,8.5):1);}
isExpanded(){return this._group.expanded;}
formatValue(value,precision){return Number.preciseMillisToString(value,precision);}
canJumpToEntry(entryIndex){return false;}};;Timeline.TimelineFlameChartView=class extends UI.VBox{constructor(delegate){super();this.element.classList.add('timeline-flamechart');this._delegate=delegate;this._model=null;this._searchResults;this._eventListeners=[];this._showMemoryGraphSetting=Common.settings.createSetting('timelineShowMemory',false);this._networkSplitWidget=new UI.SplitWidget(false,false,'timelineFlamechartMainView',150);const mainViewGroupExpansionSetting=Common.settings.createSetting('timelineFlamechartMainViewGroupExpansion',{});this._mainDataProvider=new Timeline.TimelineFlameChartDataProvider();this._mainDataProvider.addEventListener(Timeline.TimelineFlameChartDataProvider.Events.DataChanged,()=>this._mainFlameChart.scheduleUpdate());this._mainFlameChart=new PerfUI.FlameChart(this._mainDataProvider,this,mainViewGroupExpansionSetting);this._mainFlameChart.alwaysShowVerticalScroll();this._mainFlameChart.enableRuler(false);this._networkFlameChartGroupExpansionSetting=Common.settings.createSetting('timelineFlamechartNetworkViewGroupExpansion',{});this._networkDataProvider=new Timeline.TimelineFlameChartNetworkDataProvider();this._networkFlameChart=new PerfUI.FlameChart(this._networkDataProvider,this,this._networkFlameChartGroupExpansionSetting);this._networkFlameChart.alwaysShowVerticalScroll();this._networkFlameChart.disableRangeSelection();this._networkPane=new UI.VBox();this._networkPane.setMinimumSize(23,23);this._networkFlameChart.show(this._networkPane.element);this._splitResizer=this._networkPane.element.createChild('div','timeline-flamechart-resizer');this._networkSplitWidget.hideDefaultResizer(true);this._networkSplitWidget.installResizer(this._splitResizer);this._networkSplitWidget.setMainWidget(this._mainFlameChart);this._networkSplitWidget.setSidebarWidget(this._networkPane);this._chartSplitWidget=new UI.SplitWidget(false,true,'timelineCountersSplitViewState');this._countersView=new Timeline.CountersGraph(this._delegate);this._chartSplitWidget.setMainWidget(this._networkSplitWidget);this._chartSplitWidget.setSidebarWidget(this._countersView);this._chartSplitWidget.hideDefaultResizer();this._chartSplitWidget.installResizer((this._countersView.resizerElement()));this._updateCountersGraphToggle();this._detailsSplitWidget=new UI.SplitWidget(false,true,'timelinePanelDetailsSplitViewState');this._detailsSplitWidget.element.classList.add('timeline-details-split');this._detailsView=new Timeline.TimelineDetailsView(delegate);this._detailsSplitWidget.installResizer(this._detailsView.headerElement());this._detailsSplitWidget.setMainWidget(this._chartSplitWidget);this._detailsSplitWidget.setSidebarWidget(this._detailsView);this._detailsSplitWidget.show(this.element);this._onMainEntrySelected=this._onEntrySelected.bind(this,this._mainDataProvider);this._onNetworkEntrySelected=this._onEntrySelected.bind(this,this._networkDataProvider);this._mainFlameChart.addEventListener(PerfUI.FlameChart.Events.EntrySelected,this._onMainEntrySelected,this);this._networkFlameChart.addEventListener(PerfUI.FlameChart.Events.EntrySelected,this._onNetworkEntrySelected,this);this._mainFlameChart.addEventListener(PerfUI.FlameChart.Events.EntryHighlighted,this._onEntryHighlighted,this);this._nextExtensionIndex=0;this._boundRefresh=this._refresh.bind(this);this._selectedTrack=null;this._mainDataProvider.setEventColorMapping(Timeline.TimelineUIUtils.eventColor);this._groupBySetting=Common.settings.createSetting('timelineTreeGroupBy',Timeline.AggregatedTimelineTreeView.GroupBy.None);this._groupBySetting.addChangeListener(this._updateColorMapper,this);this._updateColorMapper();ProductRegistry.instance().then(registry=>this._productRegistry=registry);}
_updateColorMapper(){this._urlToColorCache=new Map();if(!this._model)
return;const colorByProduct=this._groupBySetting.get()===Timeline.AggregatedTimelineTreeView.GroupBy.Product;this._mainDataProvider.setEventColorMapping(colorByProduct?this._colorByProductForEvent.bind(this):Timeline.TimelineUIUtils.eventColor);this._mainFlameChart.update();}
_colorByProductForEvent(event){return Timeline.TimelineUIUtils.eventColorByProduct(this._productRegistry,this._model.timelineModel(),this._urlToColorCache,event);}
_onWindowChanged(event){const window=(event.data.window);const animate=!!event.data.animate;this._mainFlameChart.setWindowTimes(window.left,window.right,animate);this._networkFlameChart.setWindowTimes(window.left,window.right,animate);this._networkDataProvider.setWindowTimes(window.left,window.right);this._updateSearchResults(false,false);}
windowChanged(windowStartTime,windowEndTime,animate){this._model.setWindow({left:windowStartTime,right:windowEndTime},animate);}
updateRangeSelection(startTime,endTime){this._delegate.select(Timeline.TimelineSelection.fromRange(startTime,endTime));}
updateSelectedGroup(flameChart,group){if(flameChart!==this._mainFlameChart)
return;const track=group?this._mainDataProvider.groupTrack(group):null;this._selectedTrack=track;this._updateTrack();}
setModel(model){if(model===this._model)
return;Common.EventTarget.removeEventListeners(this._eventListeners);this._model=model;this._selectedTrack=null;this._mainDataProvider.setModel(this._model);this._networkDataProvider.setModel(this._model);if(this._model){this._eventListeners=[this._model.addEventListener(Timeline.PerformanceModel.Events.WindowChanged,this._onWindowChanged,this),this._model.addEventListener(Timeline.PerformanceModel.Events.ExtensionDataAdded,this._appendExtensionData,this)];const window=model.window();this._mainFlameChart.setWindowTimes(window.left,window.right);this._networkFlameChart.setWindowTimes(window.left,window.right);this._networkDataProvider.setWindowTimes(window.left,window.right);this._updateSearchResults(false,false);}
this._updateColorMapper();this._updateTrack();this._nextExtensionIndex=0;this._appendExtensionData();this._refresh();}
_updateTrack(){this._countersView.setModel(this._model,this._selectedTrack);this._detailsView.setModel(this._model,this._selectedTrack);}
_refresh(){if(this._networkDataProvider.isEmpty()){this._mainFlameChart.enableRuler(true);this._networkSplitWidget.hideSidebar();}else{this._mainFlameChart.enableRuler(false);this._networkSplitWidget.showBoth();this.resizeToPreferredHeights();}
this._mainFlameChart.reset();this._networkFlameChart.reset();this._updateSearchResults(false,false);}
_appendExtensionData(){if(!this._model)
return;const extensions=this._model.extensionInfo();while(this._nextExtensionIndex<extensions.length)
this._mainDataProvider.appendExtensionEvents(extensions[this._nextExtensionIndex++]);this._mainFlameChart.scheduleUpdate();}
_onEntryHighlighted(commonEvent){SDK.OverlayModel.hideDOMNodeHighlight();const entryIndex=(commonEvent.data);const event=this._mainDataProvider.eventByIndex(entryIndex);if(!event)
return;const target=this._model&&this._model.timelineModel().targetByEvent(event);if(!target)
return;const timelineData=TimelineModel.TimelineData.forEvent(event);const backendNodeId=timelineData.backendNodeId;if(!backendNodeId)
return;new SDK.DeferredDOMNode(target,backendNodeId).highlight();}
highlightEvent(event){const entryIndex=event?this._mainDataProvider.entryIndexForSelection(Timeline.TimelineSelection.fromTraceEvent(event)):-1;if(entryIndex>=0)
this._mainFlameChart.highlightEntry(entryIndex);else
this._mainFlameChart.hideHighlight();}
willHide(){this._networkFlameChartGroupExpansionSetting.removeChangeListener(this.resizeToPreferredHeights,this);this._showMemoryGraphSetting.removeChangeListener(this._updateCountersGraphToggle,this);Bindings.blackboxManager.removeChangeListener(this._boundRefresh);}
wasShown(){this._networkFlameChartGroupExpansionSetting.addChangeListener(this.resizeToPreferredHeights,this);this._showMemoryGraphSetting.addChangeListener(this._updateCountersGraphToggle,this);Bindings.blackboxManager.addChangeListener(this._boundRefresh);if(this._needsResizeToPreferredHeights)
this.resizeToPreferredHeights();this._mainFlameChart.scheduleUpdate();this._networkFlameChart.scheduleUpdate();}
_updateCountersGraphToggle(){if(this._showMemoryGraphSetting.get())
this._chartSplitWidget.showBoth();else
this._chartSplitWidget.hideSidebar();}
setSelection(selection){let index=this._mainDataProvider.entryIndexForSelection(selection);this._mainFlameChart.setSelectedEntry(index);index=this._networkDataProvider.entryIndexForSelection(selection);this._networkFlameChart.setSelectedEntry(index);if(this._detailsView)
this._detailsView.setSelection(selection);}
_onEntrySelected(dataProvider,event){const entryIndex=(event.data);if(Runtime.experiments.isEnabled('timelineEventInitiators')&&dataProvider===this._mainDataProvider){if(this._mainDataProvider.buildFlowForInitiator(entryIndex))
this._mainFlameChart.scheduleUpdate();}
this._delegate.select(dataProvider.createSelection(entryIndex));}
resizeToPreferredHeights(){if(!this.isShowing()){this._needsResizeToPreferredHeights=true;return;}
this._needsResizeToPreferredHeights=false;this._networkPane.element.classList.toggle('timeline-network-resizer-disabled',!this._networkDataProvider.isExpanded());this._networkSplitWidget.setSidebarSize(this._networkDataProvider.preferredHeight()+this._splitResizer.clientHeight+PerfUI.FlameChart.HeaderHeight+
2);}
setSearchableView(searchableView){this._searchableView=searchableView;}
jumpToNextSearchResult(){if(!this._searchResults||!this._searchResults.length)
return;const index=typeof this._selectedSearchResult!=='undefined'?this._searchResults.indexOf(this._selectedSearchResult):-1;this._selectSearchResult(mod(index+1,this._searchResults.length));}
jumpToPreviousSearchResult(){if(!this._searchResults||!this._searchResults.length)
return;const index=typeof this._selectedSearchResult!=='undefined'?this._searchResults.indexOf(this._selectedSearchResult):0;this._selectSearchResult(mod(index-1,this._searchResults.length));}
supportsCaseSensitiveSearch(){return true;}
supportsRegexSearch(){return true;}
_selectSearchResult(index){this._searchableView.updateCurrentMatchIndex(index);this._selectedSearchResult=this._searchResults[index];this._delegate.select(this._mainDataProvider.createSelection(this._selectedSearchResult));}
_updateSearchResults(shouldJump,jumpBackwards){const oldSelectedSearchResult=this._selectedSearchResult;delete this._selectedSearchResult;this._searchResults=[];if(!this._searchRegex||!this._model)
return;const regExpFilter=new Timeline.TimelineFilters.RegExp(this._searchRegex);const window=this._model.window();this._searchResults=this._mainDataProvider.search(window.left,window.right,regExpFilter);this._searchableView.updateSearchMatchesCount(this._searchResults.length);if(!shouldJump||!this._searchResults.length)
return;let selectedIndex=this._searchResults.indexOf(oldSelectedSearchResult);if(selectedIndex===-1)
selectedIndex=jumpBackwards?this._searchResults.length-1:0;this._selectSearchResult(selectedIndex);}
searchCanceled(){if(typeof this._selectedSearchResult!=='undefined')
this._delegate.select(null);delete this._searchResults;delete this._selectedSearchResult;delete this._searchRegex;}
performSearch(searchConfig,shouldJump,jumpBackwards){this._searchRegex=searchConfig.toSearchRegex();this._updateSearchResults(shouldJump,jumpBackwards);}};Timeline.TimelineFlameChartView.Selection=class{constructor(selection,entryIndex){this.timelineSelection=selection;this.entryIndex=entryIndex;}};Timeline.FlameChartStyle={textColor:'#333'};Timeline.TimelineFlameChartMarker=class{constructor(startTime,startOffset,style){this._startTime=startTime;this._startOffset=startOffset;this._style=style;}
startTime(){return this._startTime;}
color(){return this._style.color;}
title(){const startTime=Number.millisToString(this._startOffset);return Common.UIString('%s at %s',this._style.title,startTime);}
draw(context,x,height,pixelsPerMillisecond){const lowPriorityVisibilityThresholdInPixelsPerMs=4;if(this._style.lowPriority&&pixelsPerMillisecond<lowPriorityVisibilityThresholdInPixelsPerMs)
return;context.save();if(!this._style.lowPriority){context.strokeStyle=this._style.color;context.lineWidth=2;context.beginPath();context.moveTo(x,0);context.lineTo(x,height);context.stroke();}
if(this._style.tall){context.strokeStyle=this._style.color;context.lineWidth=this._style.lineWidth;context.translate(this._style.lineWidth<1||(this._style.lineWidth&1)?0.5:0,0.5);context.beginPath();context.moveTo(x,height);context.setLineDash(this._style.dashStyle);context.lineTo(x,context.canvas.height);context.stroke();}
context.restore();}};Timeline.TimelineFlameChartView._ColorBy={URL:'URL',Product:'Product'};;Timeline.TimelineHistoryManager=class{constructor(){this._recordings=[];this._action=(UI.actionRegistry.action('timeline.show-history'));this._nextNumberByDomain=new Map();this._button=new Timeline.TimelineHistoryManager.ToolbarButton(this._action);this.clear();this._allOverviews=[{constructor:Timeline.TimelineEventOverviewResponsiveness,height:3},{constructor:Timeline.TimelineEventOverviewFrames,height:16},{constructor:Timeline.TimelineEventOverviewCPUActivity,height:20},{constructor:Timeline.TimelineEventOverviewNetwork,height:8}];this._totalHeight=this._allOverviews.reduce((acc,entry)=>acc+entry.height,0);this._enabled=true;this._lastActiveModel=null;}
addRecording(performanceModel){this._lastActiveModel=performanceModel;this._recordings.unshift(performanceModel);this._buildPreview(performanceModel);this._button.setText(this._title(performanceModel));this._updateState();if(this._recordings.length<=Timeline.TimelineHistoryManager._maxRecordings)
return;const lruModel=this._recordings.reduce((a,b)=>lastUsedTime(a)<lastUsedTime(b)?a:b);this._recordings.splice(this._recordings.indexOf(lruModel),1);lruModel.dispose();function lastUsedTime(model){return Timeline.TimelineHistoryManager._dataForModel(model).lastUsed;}}
setEnabled(enabled){this._enabled=enabled;this._updateState();}
button(){return this._button;}
clear(){this._recordings.forEach(model=>model.dispose());this._recordings=[];this._lastActiveModel=null;this._updateState();this._button.setText(Common.UIString('(no recordings)'));this._nextNumberByDomain.clear();}
async showHistoryDropDown(){if(this._recordings.length<2||!this._enabled)
return null;const model=await Timeline.TimelineHistoryManager.DropDown.show(this._recordings,(this._lastActiveModel),this._button.element);if(!model)
return null;const index=this._recordings.indexOf(model);if(index<0){console.assert(false,`selected recording not found`);return null;}
this._setCurrentModel(model);return model;}
cancelIfShowing(){Timeline.TimelineHistoryManager.DropDown.cancelIfShowing();}
navigate(direction){if(!this._enabled||!this._lastActiveModel)
return null;const index=this._recordings.indexOf(this._lastActiveModel);if(index<0)
return null;const newIndex=Number.constrain(index+direction,0,this._recordings.length-1);const model=this._recordings[newIndex];this._setCurrentModel(model);return model;}
_setCurrentModel(model){Timeline.TimelineHistoryManager._dataForModel(model).lastUsed=Date.now();this._lastActiveModel=model;this._button.setText(this._title(model));}
_updateState(){this._action.setEnabled(this._recordings.length>1&&this._enabled);}
static _previewElement(performanceModel){const data=Timeline.TimelineHistoryManager._dataForModel(performanceModel);const startedAt=performanceModel.recordStartTime();data.time.textContent=startedAt?Common.UIString('(%s ago)',Timeline.TimelineHistoryManager._coarseAge(startedAt)):'';return data.preview;}
static _coarseAge(time){const seconds=Math.round((Date.now()-time)/1000);if(seconds<50)
return Common.UIString('moments');const minutes=Math.round(seconds/60);if(minutes<50)
return Common.UIString('%s m',minutes);const hours=Math.round(minutes/60);return Common.UIString('%s h',hours);}
_title(performanceModel){return Timeline.TimelineHistoryManager._dataForModel(performanceModel).title;}
_buildPreview(performanceModel){const parsedURL=performanceModel.timelineModel().pageURL().asParsedURL();const domain=parsedURL?parsedURL.host:'';const sequenceNumber=this._nextNumberByDomain.get(domain)||1;const title=Common.UIString('%s #%d',domain,sequenceNumber);this._nextNumberByDomain.set(domain,sequenceNumber+1);const timeElement=createElement('span');const preview=createElementWithClass('div','preview-item vbox');const data={preview:preview,title:title,time:timeElement,lastUsed:Date.now()};performanceModel[Timeline.TimelineHistoryManager._previewDataSymbol]=data;preview.appendChild(this._buildTextDetails(performanceModel,title,timeElement));const screenshotAndOverview=preview.createChild('div','hbox');screenshotAndOverview.appendChild(this._buildScreenshotThumbnail(performanceModel));screenshotAndOverview.appendChild(this._buildOverview(performanceModel));return data.preview;}
_buildTextDetails(performanceModel,title,timeElement){const container=createElementWithClass('div','text-details hbox');container.createChild('span','name').textContent=title;const tracingModel=performanceModel.tracingModel();const duration=Number.millisToString(tracingModel.maximumRecordTime()-tracingModel.minimumRecordTime(),false);const timeContainer=container.createChild('span','time');timeContainer.appendChild(createTextNode(duration));timeContainer.appendChild(timeElement);return container;}
_buildScreenshotThumbnail(performanceModel){const container=createElementWithClass('div','screenshot-thumb');const thumbnailAspectRatio=3/2;container.style.width=this._totalHeight*thumbnailAspectRatio+'px';container.style.height=this._totalHeight+'px';const filmStripModel=performanceModel.filmStripModel();const lastFrame=filmStripModel.frames().peekLast();if(!lastFrame)
return container;lastFrame.imageDataPromise().then(data=>UI.loadImageFromData(data)).then(image=>image&&container.appendChild(image));return container;}
_buildOverview(performanceModel){const container=createElement('div');container.style.width=Timeline.TimelineHistoryManager._previewWidth+'px';container.style.height=this._totalHeight+'px';const canvas=container.createChild('canvas');canvas.width=window.devicePixelRatio*Timeline.TimelineHistoryManager._previewWidth;canvas.height=window.devicePixelRatio*this._totalHeight;const ctx=canvas.getContext('2d');let yOffset=0;for(const overview of this._allOverviews){const timelineOverview=new overview.constructor();timelineOverview.setCanvasSize(Timeline.TimelineHistoryManager._previewWidth,overview.height);timelineOverview.setModel(performanceModel);timelineOverview.update();const sourceContext=timelineOverview.context();const imageData=sourceContext.getImageData(0,0,sourceContext.canvas.width,sourceContext.canvas.height);ctx.putImageData(imageData,0,yOffset);yOffset+=overview.height*window.devicePixelRatio;}
return container;}
static _dataForModel(model){return model[Timeline.TimelineHistoryManager._previewDataSymbol]||null;}};Timeline.TimelineHistoryManager.PreviewData;Timeline.TimelineHistoryManager._maxRecordings=5;Timeline.TimelineHistoryManager._previewWidth=450;Timeline.TimelineHistoryManager._previewDataSymbol=Symbol('previewData');Timeline.TimelineHistoryManager.DropDown=class{constructor(models){this._glassPane=new UI.GlassPane();this._glassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);this._glassPane.setOutsideClickCallback(()=>this._close(null));this._glassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);this._glassPane.setAnchorBehavior(UI.GlassPane.AnchorBehavior.PreferBottom);const shadowRoot=UI.createShadowRootWithCoreStyles(this._glassPane.contentElement,'timeline/timelineHistoryManager.css');const contentElement=shadowRoot.createChild('div','drop-down');const listModel=new UI.ListModel();this._listControl=new UI.ListControl(listModel,this,UI.ListMode.NonViewport);this._listControl.element.addEventListener('mousemove',this._onMouseMove.bind(this),false);listModel.replaceAll(models);contentElement.appendChild(this._listControl.element);contentElement.addEventListener('keydown',this._onKeyDown.bind(this),false);contentElement.addEventListener('click',this._onClick.bind(this),false);this._selectionDone=null;}
static show(models,currentModel,anchor){if(Timeline.TimelineHistoryManager.DropDown._instance)
return Promise.resolve((null));const instance=new Timeline.TimelineHistoryManager.DropDown(models);return instance._show(anchor,currentModel);}
static cancelIfShowing(){if(!Timeline.TimelineHistoryManager.DropDown._instance)
return;Timeline.TimelineHistoryManager.DropDown._instance._close(null);}
_show(anchor,currentModel){Timeline.TimelineHistoryManager.DropDown._instance=this;this._glassPane.setContentAnchorBox(anchor.boxInWindow());this._glassPane.show((this._glassPane.contentElement.ownerDocument));this._listControl.element.focus();this._listControl.selectItem(currentModel);return new Promise(fulfill=>this._selectionDone=fulfill);}
_onMouseMove(event){const node=event.target.enclosingNodeOrSelfWithClass('preview-item');const listItem=node&&this._listControl.itemForNode(node);if(!listItem)
return;this._listControl.selectItem(listItem);}
_onClick(event){if(!event.target.enclosingNodeOrSelfWithClass('preview-item'))
return;this._close(this._listControl.selectedItem());}
_onKeyDown(event){switch(event.key){case'Escape':this._close(null);break;case'Enter':this._close(this._listControl.selectedItem());break;default:return;}
event.consume(true);}
_close(model){this._selectionDone(model);this._glassPane.hide();Timeline.TimelineHistoryManager.DropDown._instance=null;}
createElementForItem(item){const element=Timeline.TimelineHistoryManager._previewElement(item);element.classList.remove('selected');return element;}
heightForItem(item){console.assert(false,'Should not be called');return 0;}
isItemSelectable(item){return true;}
selectedItemChanged(from,to,fromElement,toElement){if(fromElement)
fromElement.classList.remove('selected');if(toElement)
toElement.classList.add('selected');}};Timeline.TimelineHistoryManager.DropDown._instance=null;Timeline.TimelineHistoryManager.ToolbarButton=class extends UI.ToolbarItem{constructor(action){super(createElementWithClass('button','dropdown-button'));const shadowRoot=UI.createShadowRootWithCoreStyles(this.element,'timeline/historyToolbarButton.css');this._contentElement=shadowRoot.createChild('span','content');const dropdownArrowIcon=UI.Icon.create('smallicon-triangle-down');shadowRoot.appendChild(dropdownArrowIcon);this.element.addEventListener('click',()=>void action.execute(),false);this.setEnabled(action.enabled());action.addEventListener(UI.Action.Events.Enabled,event=>this.setEnabled((event.data)));}
setText(text){this._contentElement.textContent=text;}};;Timeline.TimelineTreeView=class extends UI.VBox{constructor(){super();this._model=null;this._track=null;this._tree=null;this.element.classList.add('timeline-tree-view');}
static eventNameForSorting(event){if(event.name===TimelineModel.TimelineModel.RecordType.JSFrame){const data=event.args['data'];return data['functionName']+'@'+(data['scriptId']||data['url']||'');}
return event.name+':@'+TimelineModel.TimelineProfileTree.eventURL(event);}
setSearchableView(searchableView){this._searchableView=searchableView;}
setModel(model,track){this._model=model;this._track=track;this.refreshTree();}
model(){return this._model;}
init(){this._linkifier=new Components.Linkifier();this._textFilter=new Timeline.TimelineFilters.RegExp();this._currentThreadSetting=Common.settings.createSetting('timelineTreeCurrentThread',0);this._currentThreadSetting.addChangeListener(this.refreshTree,this);const columns=([]);this.populateColumns(columns);this._splitWidget=new UI.SplitWidget(true,true,'timelineTreeViewDetailsSplitWidget');const mainView=new UI.VBox();const toolbar=new UI.Toolbar('',mainView.element);this.populateToolbar(toolbar);this._dataGrid=new DataGrid.SortableDataGrid(columns);this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged,this._sortingChanged,this);this._dataGrid.element.addEventListener('mousemove',this._onMouseMove.bind(this),true);this._dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.Last);this._dataGrid.setRowContextMenuCallback(this._onContextMenu.bind(this));this._dataGrid.asWidget().show(mainView.element);this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode,this._updateDetailsForSelection,this);this._detailsView=new UI.VBox();this._detailsView.element.classList.add('timeline-details-view','timeline-details-view-body');this._splitWidget.setMainWidget(mainView);this._splitWidget.setSidebarWidget(this._detailsView);this._splitWidget.hideSidebar();this._splitWidget.show(this.element);this._splitWidget.addEventListener(UI.SplitWidget.Events.ShowModeChanged,this._onShowModeChanged,this);this._lastSelectedNode;}
lastSelectedNode(){return this._lastSelectedNode;}
updateContents(selection){this.setRange(selection.startTime(),selection.endTime());}
setRange(startTime,endTime){this._startTime=startTime;this._endTime=endTime;this.refreshTree();}
filters(){return[this._textFilter,...this._model.filters()];}
_exposePercentages(){return false;}
populateToolbar(toolbar){this._textFilterUI=new UI.ToolbarInput(Common.UIString('Filter'));this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged,textFilterChanged,this);toolbar.appendToolbarItem(this._textFilterUI);function textFilterChanged(){const searchQuery=this._textFilterUI.value();this._textFilter.setRegExp(searchQuery?createPlainTextSearchRegex(searchQuery,'i'):null);this.refreshTree();}}
_modelEvents(){return this._track?this._track.syncEvents():[];}
_onHover(node){}
_appendContextMenuItems(contextMenu,node){}
_linkifyLocation(event){const target=this._model.timelineModel().targetByEvent(event);if(!target)
return null;const frame=TimelineModel.TimelineProfileTree.eventStackFrame(event);if(!frame)
return null;return this._linkifier.maybeLinkifyConsoleCallFrame(target,frame);}
selectProfileNode(treeNode,suppressSelectedEvent){const pathToRoot=[];for(let node=treeNode;node;node=node.parent)
pathToRoot.push(node);for(let i=pathToRoot.length-1;i>0;--i){const gridNode=this.dataGridNodeForTreeNode(pathToRoot[i]);if(gridNode&&gridNode.dataGrid)
gridNode.expand();}
const gridNode=this.dataGridNodeForTreeNode(treeNode);if(gridNode.dataGrid){gridNode.reveal();gridNode.select(suppressSelectedEvent);}}
refreshTree(){this._linkifier.reset();this._dataGrid.rootNode().removeChildren();if(!this._model){this._updateDetailsForSelection();return;}
this._root=this._buildTree();const children=this._root.children();let maxSelfTime=0;let maxTotalTime=0;const totalUsedTime=this._root.totalTime-this._root.selfTime;for(const child of children.values()){maxSelfTime=Math.max(maxSelfTime,child.selfTime);maxTotalTime=Math.max(maxTotalTime,child.totalTime);}
for(const child of children.values()){const gridNode=new Timeline.TimelineTreeView.TreeGridNode(child,totalUsedTime,maxSelfTime,maxTotalTime,this);this._dataGrid.insertChild(gridNode);}
this._sortingChanged();this._updateDetailsForSelection();if(this._searchableView)
this._searchableView.refreshSearch();}
_buildTree(){throw new Error('Not Implemented');}
buildTopDownTree(doNotAggregate,groupIdCallback){return new TimelineModel.TimelineProfileTree.TopDownRootNode(this._modelEvents(),this.filters(),this._startTime,this._endTime,doNotAggregate,groupIdCallback);}
populateColumns(columns){columns.push({id:'self',title:Common.UIString('Self Time'),width:'120px',fixedWidth:true,sortable:true});columns.push({id:'total',title:Common.UIString('Total Time'),width:'120px',fixedWidth:true,sortable:true});columns.push({id:'activity',title:Common.UIString('Activity'),disclosure:true,sortable:true});}
_sortingChanged(){const columnId=this._dataGrid.sortColumnId();if(!columnId)
return;let sortFunction;switch(columnId){case'startTime':sortFunction=compareStartTime;break;case'self':sortFunction=compareNumericField.bind(null,'selfTime');break;case'total':sortFunction=compareNumericField.bind(null,'totalTime');break;case'activity':sortFunction=compareName;break;default:console.assert(false,'Unknown sort field: '+columnId);return;}
this._dataGrid.sortNodes(sortFunction,!this._dataGrid.isSortOrderAscending());function compareNumericField(field,a,b){const nodeA=(a);const nodeB=(b);return nodeA._profileNode[field]-nodeB._profileNode[field];}
function compareStartTime(a,b){const nodeA=(a);const nodeB=(b);return nodeA._profileNode.event.startTime-nodeB._profileNode.event.startTime;}
function compareName(a,b){const nodeA=(a);const nodeB=(b);const nameA=Timeline.TimelineTreeView.eventNameForSorting(nodeA._profileNode.event);const nameB=Timeline.TimelineTreeView.eventNameForSorting(nodeB._profileNode.event);return nameA.localeCompare(nameB);}}
_onShowModeChanged(){if(this._splitWidget.showMode()===UI.SplitWidget.ShowMode.OnlyMain)
return;this._lastSelectedNode=undefined;this._updateDetailsForSelection();}
_updateDetailsForSelection(){const selectedNode=this._dataGrid.selectedNode?(this._dataGrid.selectedNode)._profileNode:null;if(selectedNode===this._lastSelectedNode)
return;this._lastSelectedNode=selectedNode;if(this._splitWidget.showMode()===UI.SplitWidget.ShowMode.OnlyMain)
return;this._detailsView.detachChildWidgets();this._detailsView.element.removeChildren();if(selectedNode&&this._showDetailsForNode(selectedNode))
return;const banner=this._detailsView.element.createChild('div','full-widget-dimmed-banner');banner.createTextChild(Common.UIString('Select item for details.'));}
_showDetailsForNode(node){return false;}
_onMouseMove(event){const gridNode=event.target&&(event.target instanceof Node)?(this._dataGrid.dataGridNodeFromNode((event.target))):null;const profileNode=gridNode&&gridNode._profileNode;if(profileNode===this._lastHoveredProfileNode)
return;this._lastHoveredProfileNode=profileNode;this._onHover(profileNode);}
_onContextMenu(contextMenu,gridNode){const profileNode=gridNode._profileNode;if(!profileNode)
return;this._appendContextMenuItems(contextMenu,profileNode);}
dataGridNodeForTreeNode(treeNode){return treeNode[Timeline.TimelineTreeView.TreeGridNode._gridNodeSymbol]||null;}
searchCanceled(){this._searchResults=[];this._currentResult=0;}
performSearch(searchConfig,shouldJump,jumpBackwards){this._searchResults=[];this._currentResult=0;if(!this._root)
return;const searchRegex=searchConfig.toSearchRegex();this._searchResults=this._root.searchTree(event=>Timeline.TimelineUIUtils.testContentMatching(event,searchRegex));this._searchableView.updateSearchMatchesCount(this._searchResults.length);}
jumpToNextSearchResult(){if(!this._searchResults.length)
return;this.selectProfileNode(this._searchResults[this._currentResult],false);this._currentResult=mod(this._currentResult+1,this._searchResults.length);}
jumpToPreviousSearchResult(){if(!this._searchResults.length)
return;this.selectProfileNode(this._searchResults[this._currentResult],false);this._currentResult=mod(this._currentResult-1,this._searchResults.length);}
supportsCaseSensitiveSearch(){return true;}
supportsRegexSearch(){return true;}};Timeline.TimelineTreeView.GridNode=class extends DataGrid.SortableDataGridNode{constructor(profileNode,grandTotalTime,maxSelfTime,maxTotalTime,treeView){super(null,false);this._populated=false;this._profileNode=profileNode;this._treeView=treeView;this._grandTotalTime=grandTotalTime;this._maxSelfTime=maxSelfTime;this._maxTotalTime=maxTotalTime;}
createCell(columnId){if(columnId==='activity')
return this._createNameCell(columnId);return this._createValueCell(columnId)||super.createCell(columnId);}
_createNameCell(columnId){const cell=this.createTD(columnId);const container=cell.createChild('div','name-container');const iconContainer=container.createChild('div','activity-icon-container');const icon=iconContainer.createChild('div','activity-icon');const name=container.createChild('div','activity-name');const event=this._profileNode.event;if(this._profileNode.isGroupNode()){const treeView=(this._treeView);const info=treeView._displayInfoForGroupNode(this._profileNode);name.textContent=info.name;icon.style.backgroundColor=info.color;if(info.icon)
iconContainer.insertBefore(info.icon,icon);}else if(event){const data=event.args['data'];const deoptReason=data&&data['deoptReason'];if(deoptReason)
container.createChild('div','activity-warning').title=Common.UIString('Not optimized: %s',deoptReason);name.textContent=Timeline.TimelineUIUtils.eventTitle(event);const link=this._treeView._linkifyLocation(event);if(link)
container.createChild('div','activity-link').appendChild(link);icon.style.backgroundColor=Timeline.TimelineUIUtils.eventColor(event);}
return cell;}
_createValueCell(columnId){if(columnId!=='self'&&columnId!=='total'&&columnId!=='startTime')
return null;let showPercents=false;let value;let maxTime;switch(columnId){case'startTime':value=this._profileNode.event.startTime-this._treeView._model.timelineModel().minimumRecordTime();break;case'self':value=this._profileNode.selfTime;maxTime=this._maxSelfTime;showPercents=true;break;case'total':value=this._profileNode.totalTime;maxTime=this._maxTotalTime;showPercents=true;break;default:return null;}
const cell=this.createTD(columnId);cell.className='numeric-column';const textDiv=cell.createChild('div');textDiv.createChild('span').textContent=Common.UIString('%.1f\xa0ms',value);if(showPercents&&this._treeView._exposePercentages()){textDiv.createChild('span','percent-column').textContent=Common.UIString('%.1f\xa0%%',value/this._grandTotalTime*100);}
if(maxTime){textDiv.classList.add('background-percent-bar');cell.createChild('div','background-bar-container').createChild('div','background-bar').style.width=(value*100/maxTime).toFixed(1)+'%';}
return cell;}};Timeline.TimelineTreeView.TreeGridNode=class extends Timeline.TimelineTreeView.GridNode{constructor(profileNode,grandTotalTime,maxSelfTime,maxTotalTime,treeView){super(profileNode,grandTotalTime,maxSelfTime,maxTotalTime,treeView);this.setHasChildren(this._profileNode.hasChildren());profileNode[Timeline.TimelineTreeView.TreeGridNode._gridNodeSymbol]=this;}
populate(){if(this._populated)
return;this._populated=true;if(!this._profileNode.children)
return;for(const node of this._profileNode.children().values()){const gridNode=new Timeline.TimelineTreeView.TreeGridNode(node,this._grandTotalTime,this._maxSelfTime,this._maxTotalTime,this._treeView);this.insertChildOrdered(gridNode);}}};Timeline.TimelineTreeView.TreeGridNode._gridNodeSymbol=Symbol('treeGridNode');Timeline.AggregatedTimelineTreeView=class extends Timeline.TimelineTreeView{constructor(){super();this._groupBySetting=Common.settings.createSetting('timelineTreeGroupBy',Timeline.AggregatedTimelineTreeView.GroupBy.None);this._groupBySetting.addChangeListener(this.refreshTree.bind(this));this.init();this._stackView=new Timeline.TimelineStackView(this);this._stackView.addEventListener(Timeline.TimelineStackView.Events.SelectionChanged,this._onStackViewSelectionChanged,this);this._badgePool=new ProductRegistry.BadgePool(true);this._productByURLCache=new Map();this._colorByURLCache=new Map();ProductRegistry.instance().then(registry=>{this._productRegistry=registry;this.refreshTree();});}
setModel(model,track){this._badgePool.reset();super.setModel(model,track);}
updateContents(selection){this._updateExtensionResolver();super.updateContents(selection);const rootNode=this._dataGrid.rootNode();if(rootNode.children.length)
rootNode.children[0].revealAndSelect();}
_updateExtensionResolver(){this._executionContextNamesByOrigin=new Map();for(const runtimeModel of SDK.targetManager.models(SDK.RuntimeModel)){for(const context of runtimeModel.executionContexts())
this._executionContextNamesByOrigin.set(context.origin,context.name);}}
_beautifyDomainName(name){if(Timeline.AggregatedTimelineTreeView._isExtensionInternalURL(name))
name=Common.UIString('[Chrome extensions overhead]');else if(Timeline.AggregatedTimelineTreeView._isV8NativeURL(name))
name=Common.UIString('[V8 Runtime]');else if(name.startsWith('chrome-extension'))
name=this._executionContextNamesByOrigin.get(name)||name;return name;}
_displayInfoForGroupNode(node){const categories=Timeline.TimelineUIUtils.categories();let color=node.id?Timeline.TimelineUIUtils.eventColor((node.event)):categories['other'].color;const unattributed=Common.UIString('[unattributed]');switch(this._groupBySetting.get()){case Timeline.AggregatedTimelineTreeView.GroupBy.Category:{const category=categories[node.id]||categories['other'];return{name:category.title,color:category.color};}
case Timeline.AggregatedTimelineTreeView.GroupBy.Domain:case Timeline.AggregatedTimelineTreeView.GroupBy.Subdomain:{let domainName=this._beautifyDomainName(node.id);if(domainName){const productName=this._productByEvent((node.event));if(productName)
domainName+=' \u2014 '+productName;}
return{name:domainName||unattributed,color:color};}
case Timeline.AggregatedTimelineTreeView.GroupBy.EventName:{const name=node.event.name===TimelineModel.TimelineModel.RecordType.JSFrame?Common.UIString('JavaScript'):Timeline.TimelineUIUtils.eventTitle(node.event);return{name:name,color:node.event.name===TimelineModel.TimelineModel.RecordType.JSFrame?Timeline.TimelineUIUtils.eventStyle(node.event).category.color:color};}
case Timeline.AggregatedTimelineTreeView.GroupBy.Product:{const event=(node.event);const info=this._productAndBadgeByEvent(event);const name=info&&info.name||unattributed;color=Timeline.TimelineUIUtils.eventColorByProduct(this._productRegistry,this._model.timelineModel(),this._colorByURLCache,event);return{name:name,color:color,icon:info&&info.badge||undefined};}
case Timeline.AggregatedTimelineTreeView.GroupBy.URL:break;case Timeline.AggregatedTimelineTreeView.GroupBy.Frame:{const frame=this._model.timelineModel().pageFrameById(node.id);const frameName=frame?Timeline.TimelineUIUtils.displayNameForFrame(frame,80):Common.UIString('Page');return{name:frameName,color:color};}
default:console.assert(false,'Unexpected grouping type');}
return{name:node.id||unattributed,color:color};}
populateToolbar(toolbar){super.populateToolbar(toolbar);const groupBy=Timeline.AggregatedTimelineTreeView.GroupBy;const options=[{label:Common.UIString('No Grouping'),value:groupBy.None},{label:Common.UIString('Group by Activity'),value:groupBy.EventName},{label:Common.UIString('Group by Category'),value:groupBy.Category},{label:Common.UIString('Group by Domain'),value:groupBy.Domain},{label:Common.UIString('Group by Frame'),value:groupBy.Frame},{label:Common.UIString('Group by Product'),value:groupBy.Product},{label:Common.UIString('Group by Subdomain'),value:groupBy.Subdomain},{label:Common.UIString('Group by URL'),value:groupBy.URL},];toolbar.appendToolbarItem(new UI.ToolbarSettingComboBox(options,this._groupBySetting));toolbar.appendSpacer();toolbar.appendToolbarItem(this._splitWidget.createShowHideSidebarButton(Common.UIString('heaviest stack')));}
_buildHeaviestStack(treeNode){console.assert(!!treeNode.parent,'Attempt to build stack for tree root');let result=[];for(let node=treeNode;node&&node.parent;node=node.parent)
result.push(node);result=result.reverse();for(let node=treeNode;node&&node.children()&&node.children().size;){const children=Array.from(node.children().values());node=children.reduce((a,b)=>a.totalTime>b.totalTime?a:b);result.push(node);}
return result;}
_exposePercentages(){return true;}
_onStackViewSelectionChanged(){const treeNode=this._stackView.selectedTreeNode();if(treeNode)
this.selectProfileNode(treeNode,true);}
_showDetailsForNode(node){const stack=this._buildHeaviestStack(node);this._stackView.setStack(stack,node);this._stackView.show(this._detailsView.element);return true;}
_groupingFunction(groupBy){const GroupBy=Timeline.AggregatedTimelineTreeView.GroupBy;switch(groupBy){case GroupBy.None:return null;case GroupBy.EventName:return event=>Timeline.TimelineUIUtils.eventStyle(event).title;case GroupBy.Category:return event=>Timeline.TimelineUIUtils.eventStyle(event).category.name;case GroupBy.Subdomain:return this._domainByEvent.bind(this,false);case GroupBy.Domain:return this._domainByEvent.bind(this,true);case GroupBy.Product:return event=>this._productByEvent(event)||this._domainByEvent(true,event)||'';case GroupBy.URL:return event=>TimelineModel.TimelineProfileTree.eventURL(event)||'';case GroupBy.Frame:return event=>TimelineModel.TimelineData.forEvent(event).frameId;default:console.assert(false,`Unexpected aggregation setting: ${groupBy}`);return null;}}
_domainByEvent(groupSubdomains,event){const url=TimelineModel.TimelineProfileTree.eventURL(event);if(!url)
return'';if(Timeline.AggregatedTimelineTreeView._isExtensionInternalURL(url))
return Timeline.AggregatedTimelineTreeView._extensionInternalPrefix;if(Timeline.AggregatedTimelineTreeView._isV8NativeURL(url))
return Timeline.AggregatedTimelineTreeView._v8NativePrefix;const parsedURL=url.asParsedURL();if(!parsedURL)
return'';if(parsedURL.scheme==='chrome-extension')
return parsedURL.scheme+'://'+parsedURL.host;if(!groupSubdomains)
return parsedURL.host;if(/^[.0-9]+$/.test(parsedURL.host))
return parsedURL.host;const domainMatch=/([^.]*\.)?[^.]*$/.exec(parsedURL.host);return domainMatch&&domainMatch[0]||'';}
_productByEvent(event){const url=TimelineModel.TimelineProfileTree.eventURL(event);if(!url)
return'';if(this._productByURLCache.has(url))
return this._productByURLCache.get(url);if(!this._productRegistry)
return'';const parsedURL=url.asParsedURL();const name=parsedURL&&this._productRegistry.nameForUrl(parsedURL)||'';this._productByURLCache.set(url,name);return name;}
_productAndBadgeByEvent(event){const url=TimelineModel.TimelineProfileTree.eventURL(event);if(!url||!this._productRegistry)
return null;const parsedURL=url.asParsedURL();const name=parsedURL&&this._productRegistry.nameForUrl(parsedURL)||this._domainByEvent(true,event);if(!name)
return null;const icon=parsedURL&&this._badgePool.badgeForURL(parsedURL);return{name:this._beautifyDomainName(name),badge:icon};}
_appendContextMenuItems(contextMenu,node){if(this._groupBySetting.get()!==Timeline.AggregatedTimelineTreeView.GroupBy.Frame)
return;if(!node.isGroupNode())
return;const frame=this._model.timelineModel().pageFrameById(node.id);if(!frame||!frame.ownerNode)
return;contextMenu.appendApplicableItems(frame.ownerNode);}
static _isExtensionInternalURL(url){return url.startsWith(Timeline.AggregatedTimelineTreeView._extensionInternalPrefix);}
static _isV8NativeURL(url){return url.startsWith(Timeline.AggregatedTimelineTreeView._v8NativePrefix);}};Timeline.AggregatedTimelineTreeView._extensionInternalPrefix='extensions::';Timeline.AggregatedTimelineTreeView._v8NativePrefix='native ';Timeline.AggregatedTimelineTreeView.GroupBy={None:'None',EventName:'EventName',Category:'Category',Domain:'Domain',Subdomain:'Subdomain',Product:'Product',URL:'URL',Frame:'Frame'};Timeline.CallTreeTimelineTreeView=class extends Timeline.AggregatedTimelineTreeView{constructor(){super();this._dataGrid.markColumnAsSortedBy('total',DataGrid.DataGrid.Order.Descending);}
_buildTree(){const grouping=this._groupBySetting.get();return this.buildTopDownTree(false,this._groupingFunction(grouping));}};Timeline.BottomUpTimelineTreeView=class extends Timeline.AggregatedTimelineTreeView{constructor(){super();this._dataGrid.markColumnAsSortedBy('self',DataGrid.DataGrid.Order.Descending);}
_buildTree(){return new TimelineModel.TimelineProfileTree.BottomUpRootNode(this._modelEvents(),this.filters(),this._startTime,this._endTime,this._groupingFunction(this._groupBySetting.get()));}};Timeline.TimelineStackView=class extends UI.VBox{constructor(treeView){super();const header=this.element.createChild('div','timeline-stack-view-header');header.textContent=Common.UIString('Heaviest stack');this._treeView=treeView;const columns=([{id:'total',title:Common.UIString('Total Time'),fixedWidth:true,width:'110px'},{id:'activity',title:Common.UIString('Activity')}]);this._dataGrid=new DataGrid.ViewportDataGrid(columns);this._dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.Last);this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode,this._onSelectionChanged,this);this._dataGrid.asWidget().show(this.element);}
setStack(stack,selectedNode){const rootNode=this._dataGrid.rootNode();rootNode.removeChildren();let nodeToReveal=null;const totalTime=Math.max.apply(Math,stack.map(node=>node.totalTime));for(const node of stack){const gridNode=new Timeline.TimelineTreeView.GridNode(node,totalTime,totalTime,totalTime,this._treeView);rootNode.appendChild(gridNode);if(node===selectedNode)
nodeToReveal=gridNode;}
nodeToReveal.revealAndSelect();}
selectedTreeNode(){const selectedNode=this._dataGrid.selectedNode;return selectedNode&&(selectedNode)._profileNode;}
_onSelectionChanged(){this.dispatchEventToListeners(Timeline.TimelineStackView.Events.SelectionChanged);}};Timeline.TimelineStackView.Events={SelectionChanged:Symbol('SelectionChanged')};;Timeline.EventsTimelineTreeView=class extends Timeline.TimelineTreeView{constructor(delegate){super();this._filtersControl=new Timeline.EventsTimelineTreeView.Filters();this._filtersControl.addEventListener(Timeline.EventsTimelineTreeView.Filters.Events.FilterChanged,this._onFilterChanged,this);this.init();this._delegate=delegate;this._badgePool=new ProductRegistry.BadgePool(true);this._dataGrid.markColumnAsSortedBy('startTime',DataGrid.DataGrid.Order.Ascending);this._splitWidget.showBoth();}
filters(){return[...super.filters(),...this._filtersControl.filters()];}
updateContents(selection){this._badgePool.reset();super.updateContents(selection);if(selection.type()===Timeline.TimelineSelection.Type.TraceEvent){const event=(selection.object());this._selectEvent(event,true);}}
_buildTree(){this._currentTree=this.buildTopDownTree(true,null);return this._currentTree;}
_onFilterChanged(){const selectedEvent=this.lastSelectedNode()&&this.lastSelectedNode().event;this.refreshTree();if(selectedEvent)
this._selectEvent(selectedEvent,false);}
_findNodeWithEvent(event){const iterators=[this._currentTree.children().values()];while(iterators.length){const iterator=iterators.peekLast().next();if(iterator.done){iterators.pop();continue;}
const child=(iterator.value);if(child.event===event)
return child;iterators.push(child.children().values());}
return null;}
_selectEvent(event,expand){const node=this._findNodeWithEvent(event);if(!node)
return;this.selectProfileNode(node,false);if(expand)
this.dataGridNodeForTreeNode(node).expand();}
populateColumns(columns){columns.push({id:'startTime',title:Common.UIString('Start Time'),width:'80px',fixedWidth:true,sortable:true});super.populateColumns(columns);columns.filter(c=>c.fixedWidth).forEach(c=>c.width='80px');}
populateToolbar(toolbar){super.populateToolbar(toolbar);this._filtersControl.populateToolbar(toolbar);}
_showDetailsForNode(node){const traceEvent=node.event;if(!traceEvent)
return false;Timeline.TimelineUIUtils.buildTraceEventDetails(traceEvent,this.model().timelineModel(),this._linkifier,this._badgePool,false).then(fragment=>this._detailsView.element.appendChild(fragment));return true;}
_onHover(node){this._delegate.highlightEvent(node&&node.event);}};Timeline.EventsTimelineTreeView.Filters=class extends Common.Object{constructor(){super();this._categoryFilter=new Timeline.TimelineFilters.Category();this._durationFilter=new Timeline.TimelineFilters.IsLong();this._filters=[this._categoryFilter,this._durationFilter];}
filters(){return this._filters;}
populateToolbar(toolbar){const durationFilterUI=new UI.ToolbarComboBox(durationFilterChanged.bind(this));for(const durationMs of Timeline.EventsTimelineTreeView.Filters._durationFilterPresetsMs){durationFilterUI.addOption(durationFilterUI.createOption(durationMs?Common.UIString('\u2265 %d\xa0ms',durationMs):Common.UIString('All'),durationMs?Common.UIString('Hide records shorter than %d\xa0ms',durationMs):Common.UIString('Show all records'),String(durationMs)));}
toolbar.appendToolbarItem(durationFilterUI);const categoryFiltersUI={};const categories=Timeline.TimelineUIUtils.categories();for(const categoryName in categories){const category=categories[categoryName];if(!category.visible)
continue;const checkbox=new UI.ToolbarCheckbox(category.title,undefined,categoriesFilterChanged.bind(this,categoryName));checkbox.setChecked(true);checkbox.inputElement.style.backgroundColor=category.color;categoryFiltersUI[category.name]=checkbox;toolbar.appendToolbarItem(checkbox);}
function durationFilterChanged(){const duration=durationFilterUI.selectedOption().value;const minimumRecordDuration=parseInt(duration,10);this._durationFilter.setMinimumRecordDuration(minimumRecordDuration);this._notifyFiltersChanged();}
function categoriesFilterChanged(name){const categories=Timeline.TimelineUIUtils.categories();categories[name].hidden=!categoryFiltersUI[name].checked();this._notifyFiltersChanged();}}
_notifyFiltersChanged(){this.dispatchEventToListeners(Timeline.EventsTimelineTreeView.Filters.Events.FilterChanged);}};Timeline.EventsTimelineTreeView.Filters._durationFilterPresetsMs=[0,1,15];Timeline.EventsTimelineTreeView.Filters.Events={FilterChanged:Symbol('FilterChanged')};;Timeline.TimelineUIUtils=class{static _initEventStyles(){if(Timeline.TimelineUIUtils._eventStylesMap)
return Timeline.TimelineUIUtils._eventStylesMap;const recordTypes=TimelineModel.TimelineModel.RecordType;const categories=Timeline.TimelineUIUtils.categories();const eventStyles={};eventStyles[recordTypes.Task]=new Timeline.TimelineRecordStyle(Common.UIString('Task'),categories['other']);eventStyles[recordTypes.Program]=new Timeline.TimelineRecordStyle(Common.UIString('Other'),categories['other']);eventStyles[recordTypes.Animation]=new Timeline.TimelineRecordStyle(Common.UIString('Animation'),categories['rendering']);eventStyles[recordTypes.EventDispatch]=new Timeline.TimelineRecordStyle(Common.UIString('Event'),categories['scripting']);eventStyles[recordTypes.RequestMainThreadFrame]=new Timeline.TimelineRecordStyle(Common.UIString('Request Main Thread Frame'),categories['rendering'],true);eventStyles[recordTypes.BeginFrame]=new Timeline.TimelineRecordStyle(Common.UIString('Frame Start'),categories['rendering'],true);eventStyles[recordTypes.BeginMainThreadFrame]=new Timeline.TimelineRecordStyle(Common.UIString('Frame Start (main thread)'),categories['rendering'],true);eventStyles[recordTypes.DrawFrame]=new Timeline.TimelineRecordStyle(Common.UIString('Draw Frame'),categories['rendering'],true);eventStyles[recordTypes.HitTest]=new Timeline.TimelineRecordStyle(Common.UIString('Hit Test'),categories['rendering']);eventStyles[recordTypes.ScheduleStyleRecalculation]=new Timeline.TimelineRecordStyle(Common.UIString('Schedule Style Recalculation'),categories['rendering'],true);eventStyles[recordTypes.RecalculateStyles]=new Timeline.TimelineRecordStyle(Common.UIString('Recalculate Style'),categories['rendering']);eventStyles[recordTypes.UpdateLayoutTree]=new Timeline.TimelineRecordStyle(Common.UIString('Recalculate Style'),categories['rendering']);eventStyles[recordTypes.InvalidateLayout]=new Timeline.TimelineRecordStyle(Common.UIString('Invalidate Layout'),categories['rendering'],true);eventStyles[recordTypes.Layout]=new Timeline.TimelineRecordStyle(Common.UIString('Layout'),categories['rendering']);eventStyles[recordTypes.PaintSetup]=new Timeline.TimelineRecordStyle(Common.UIString('Paint Setup'),categories['painting']);eventStyles[recordTypes.PaintImage]=new Timeline.TimelineRecordStyle(Common.UIString('Paint Image'),categories['painting'],true);eventStyles[recordTypes.UpdateLayer]=new Timeline.TimelineRecordStyle(Common.UIString('Update Layer'),categories['painting'],true);eventStyles[recordTypes.UpdateLayerTree]=new Timeline.TimelineRecordStyle(Common.UIString('Update Layer Tree'),categories['rendering']);eventStyles[recordTypes.Paint]=new Timeline.TimelineRecordStyle(Common.UIString('Paint'),categories['painting']);eventStyles[recordTypes.RasterTask]=new Timeline.TimelineRecordStyle(Common.UIString('Rasterize Paint'),categories['painting']);eventStyles[recordTypes.ScrollLayer]=new Timeline.TimelineRecordStyle(Common.UIString('Scroll'),categories['rendering']);eventStyles[recordTypes.CompositeLayers]=new Timeline.TimelineRecordStyle(Common.UIString('Composite Layers'),categories['painting']);eventStyles[recordTypes.ParseHTML]=new Timeline.TimelineRecordStyle(Common.UIString('Parse HTML'),categories['loading']);eventStyles[recordTypes.ParseAuthorStyleSheet]=new Timeline.TimelineRecordStyle(Common.UIString('Parse Stylesheet'),categories['loading']);eventStyles[recordTypes.TimerInstall]=new Timeline.TimelineRecordStyle(Common.UIString('Install Timer'),categories['scripting']);eventStyles[recordTypes.TimerRemove]=new Timeline.TimelineRecordStyle(Common.UIString('Remove Timer'),categories['scripting']);eventStyles[recordTypes.TimerFire]=new Timeline.TimelineRecordStyle(Common.UIString('Timer Fired'),categories['scripting']);eventStyles[recordTypes.XHRReadyStateChange]=new Timeline.TimelineRecordStyle(Common.UIString('XHR Ready State Change'),categories['scripting']);eventStyles[recordTypes.XHRLoad]=new Timeline.TimelineRecordStyle(Common.UIString('XHR Load'),categories['scripting']);eventStyles[recordTypes.CompileScript]=new Timeline.TimelineRecordStyle(Common.UIString('Compile Script'),categories['scripting']);eventStyles[recordTypes.EvaluateScript]=new Timeline.TimelineRecordStyle(Common.UIString('Evaluate Script'),categories['scripting']);eventStyles[recordTypes.CompileModule]=new Timeline.TimelineRecordStyle(Common.UIString('Compile Module'),categories['scripting']);eventStyles[recordTypes.EvaluateModule]=new Timeline.TimelineRecordStyle(Common.UIString('Evaluate Module'),categories['scripting']);eventStyles[recordTypes.ParseScriptOnBackground]=new Timeline.TimelineRecordStyle(Common.UIString('Parse Script'),categories['scripting']);eventStyles[recordTypes.FrameStartedLoading]=new Timeline.TimelineRecordStyle(Common.UIString('Frame Started Loading'),categories['loading'],true);eventStyles[recordTypes.MarkLoad]=new Timeline.TimelineRecordStyle(Common.UIString('Load event'),categories['scripting'],true);eventStyles[recordTypes.MarkDOMContent]=new Timeline.TimelineRecordStyle(Common.UIString('DOMContentLoaded event'),categories['scripting'],true);eventStyles[recordTypes.MarkFirstPaint]=new Timeline.TimelineRecordStyle(Common.UIString('First paint'),categories['painting'],true);eventStyles[recordTypes.MarkFCP]=new Timeline.TimelineRecordStyle(Common.UIString('First contentful paint'),categories['rendering'],true);eventStyles[recordTypes.MarkFMP]=new Timeline.TimelineRecordStyle(Common.UIString('First meaningful paint'),categories['rendering'],true);eventStyles[recordTypes.MarkFMPCandidate]=new Timeline.TimelineRecordStyle(Common.UIString('Meaningful paint candidate'),categories['rendering'],true);eventStyles[recordTypes.TimeStamp]=new Timeline.TimelineRecordStyle(Common.UIString('Timestamp'),categories['scripting']);eventStyles[recordTypes.ConsoleTime]=new Timeline.TimelineRecordStyle(Common.UIString('Console Time'),categories['scripting']);eventStyles[recordTypes.UserTiming]=new Timeline.TimelineRecordStyle(Common.UIString('User Timing'),categories['scripting']);eventStyles[recordTypes.ResourceSendRequest]=new Timeline.TimelineRecordStyle(Common.UIString('Send Request'),categories['loading']);eventStyles[recordTypes.ResourceReceiveResponse]=new Timeline.TimelineRecordStyle(Common.UIString('Receive Response'),categories['loading']);eventStyles[recordTypes.ResourceFinish]=new Timeline.TimelineRecordStyle(Common.UIString('Finish Loading'),categories['loading']);eventStyles[recordTypes.ResourceReceivedData]=new Timeline.TimelineRecordStyle(Common.UIString('Receive Data'),categories['loading']);eventStyles[recordTypes.RunMicrotasks]=new Timeline.TimelineRecordStyle(Common.UIString('Run Microtasks'),categories['scripting']);eventStyles[recordTypes.FunctionCall]=new Timeline.TimelineRecordStyle(Common.UIString('Function Call'),categories['scripting']);eventStyles[recordTypes.GCEvent]=new Timeline.TimelineRecordStyle(Common.UIString('GC Event'),categories['scripting']);eventStyles[recordTypes.MajorGC]=new Timeline.TimelineRecordStyle(Common.UIString('Major GC'),categories['scripting']);eventStyles[recordTypes.MinorGC]=new Timeline.TimelineRecordStyle(Common.UIString('Minor GC'),categories['scripting']);eventStyles[recordTypes.JSFrame]=new Timeline.TimelineRecordStyle(Common.UIString('JS Frame'),categories['scripting']);eventStyles[recordTypes.RequestAnimationFrame]=new Timeline.TimelineRecordStyle(Common.UIString('Request Animation Frame'),categories['scripting']);eventStyles[recordTypes.CancelAnimationFrame]=new Timeline.TimelineRecordStyle(Common.UIString('Cancel Animation Frame'),categories['scripting']);eventStyles[recordTypes.FireAnimationFrame]=new Timeline.TimelineRecordStyle(Common.UIString('Animation Frame Fired'),categories['scripting']);eventStyles[recordTypes.RequestIdleCallback]=new Timeline.TimelineRecordStyle(Common.UIString('Request Idle Callback'),categories['scripting']);eventStyles[recordTypes.CancelIdleCallback]=new Timeline.TimelineRecordStyle(Common.UIString('Cancel Idle Callback'),categories['scripting']);eventStyles[recordTypes.FireIdleCallback]=new Timeline.TimelineRecordStyle(Common.UIString('Fire Idle Callback'),categories['scripting']);eventStyles[recordTypes.WebSocketCreate]=new Timeline.TimelineRecordStyle(Common.UIString('Create WebSocket'),categories['scripting']);eventStyles[recordTypes.WebSocketSendHandshakeRequest]=new Timeline.TimelineRecordStyle(Common.UIString('Send WebSocket Handshake'),categories['scripting']);eventStyles[recordTypes.WebSocketReceiveHandshakeResponse]=new Timeline.TimelineRecordStyle(Common.UIString('Receive WebSocket Handshake'),categories['scripting']);eventStyles[recordTypes.WebSocketDestroy]=new Timeline.TimelineRecordStyle(Common.UIString('Destroy WebSocket'),categories['scripting']);eventStyles[recordTypes.EmbedderCallback]=new Timeline.TimelineRecordStyle(Common.UIString('Embedder Callback'),categories['scripting']);eventStyles[recordTypes.DecodeImage]=new Timeline.TimelineRecordStyle(Common.UIString('Image Decode'),categories['painting']);eventStyles[recordTypes.ResizeImage]=new Timeline.TimelineRecordStyle(Common.UIString('Image Resize'),categories['painting']);eventStyles[recordTypes.GPUTask]=new Timeline.TimelineRecordStyle(Common.UIString('GPU'),categories['gpu']);eventStyles[recordTypes.LatencyInfo]=new Timeline.TimelineRecordStyle(Common.UIString('Input Latency'),categories['scripting']);eventStyles[recordTypes.GCIdleLazySweep]=new Timeline.TimelineRecordStyle(Common.UIString('DOM GC'),categories['scripting']);eventStyles[recordTypes.GCCompleteSweep]=new Timeline.TimelineRecordStyle(Common.UIString('DOM GC'),categories['scripting']);eventStyles[recordTypes.GCCollectGarbage]=new Timeline.TimelineRecordStyle(Common.UIString('DOM GC'),categories['scripting']);eventStyles[recordTypes.CryptoDoEncrypt]=new Timeline.TimelineRecordStyle(Common.UIString('Encrypt'),categories['scripting']);eventStyles[recordTypes.CryptoDoEncryptReply]=new Timeline.TimelineRecordStyle(Common.UIString('Encrypt Reply'),categories['scripting']);eventStyles[recordTypes.CryptoDoDecrypt]=new Timeline.TimelineRecordStyle(Common.UIString('Decrypt'),categories['scripting']);eventStyles[recordTypes.CryptoDoDecryptReply]=new Timeline.TimelineRecordStyle(Common.UIString('Decrypt Reply'),categories['scripting']);eventStyles[recordTypes.CryptoDoDigest]=new Timeline.TimelineRecordStyle(Common.UIString('Digest'),categories['scripting']);eventStyles[recordTypes.CryptoDoDigestReply]=new Timeline.TimelineRecordStyle(Common.UIString('Digest Reply'),categories['scripting']);eventStyles[recordTypes.CryptoDoSign]=new Timeline.TimelineRecordStyle(Common.UIString('Sign'),categories['scripting']);eventStyles[recordTypes.CryptoDoSignReply]=new Timeline.TimelineRecordStyle(Common.UIString('Sign Reply'),categories['scripting']);eventStyles[recordTypes.CryptoDoVerify]=new Timeline.TimelineRecordStyle(Common.UIString('Verify'),categories['scripting']);eventStyles[recordTypes.CryptoDoVerifyReply]=new Timeline.TimelineRecordStyle(Common.UIString('Verify Reply'),categories['scripting']);eventStyles[recordTypes.AsyncTask]=new Timeline.TimelineRecordStyle(Common.UIString('Async Task'),categories['async']);Timeline.TimelineUIUtils._eventStylesMap=eventStyles;return eventStyles;}
static inputEventDisplayName(inputEventType){if(!Timeline.TimelineUIUtils._inputEventToDisplayName){const inputEvent=TimelineModel.TimelineIRModel.InputEvents;Timeline.TimelineUIUtils._inputEventToDisplayName=new Map([[inputEvent.Char,Common.UIString('Key Character')],[inputEvent.KeyDown,Common.UIString('Key Down')],[inputEvent.KeyDownRaw,Common.UIString('Key Down')],[inputEvent.KeyUp,Common.UIString('Key Up')],[inputEvent.Click,Common.UIString('Click')],[inputEvent.ContextMenu,Common.UIString('Context Menu')],[inputEvent.MouseDown,Common.UIString('Mouse Down')],[inputEvent.MouseMove,Common.UIString('Mouse Move')],[inputEvent.MouseUp,Common.UIString('Mouse Up')],[inputEvent.MouseWheel,Common.UIString('Mouse Wheel')],[inputEvent.ScrollBegin,Common.UIString('Scroll Begin')],[inputEvent.ScrollEnd,Common.UIString('Scroll End')],[inputEvent.ScrollUpdate,Common.UIString('Scroll Update')],[inputEvent.FlingStart,Common.UIString('Fling Start')],[inputEvent.FlingCancel,Common.UIString('Fling Halt')],[inputEvent.Tap,Common.UIString('Tap')],[inputEvent.TapCancel,Common.UIString('Tap Halt')],[inputEvent.ShowPress,Common.UIString('Tap Begin')],[inputEvent.TapDown,Common.UIString('Tap Down')],[inputEvent.TouchCancel,Common.UIString('Touch Cancel')],[inputEvent.TouchEnd,Common.UIString('Touch End')],[inputEvent.TouchMove,Common.UIString('Touch Move')],[inputEvent.TouchStart,Common.UIString('Touch Start')],[inputEvent.PinchBegin,Common.UIString('Pinch Begin')],[inputEvent.PinchEnd,Common.UIString('Pinch End')],[inputEvent.PinchUpdate,Common.UIString('Pinch Update')]]);}
return Timeline.TimelineUIUtils._inputEventToDisplayName.get(inputEventType)||null;}
static frameDisplayName(frame){if(!TimelineModel.TimelineJSProfileProcessor.isNativeRuntimeFrame(frame))
return UI.beautifyFunctionName(frame.functionName);const nativeGroup=TimelineModel.TimelineJSProfileProcessor.nativeGroup(frame.functionName);const groups=TimelineModel.TimelineJSProfileProcessor.NativeGroups;switch(nativeGroup){case groups.Compile:return Common.UIString('Compile');case groups.Parse:return Common.UIString('Parse');}
return frame.functionName;}
static testContentMatching(traceEvent,regExp){const title=Timeline.TimelineUIUtils.eventStyle(traceEvent).title;const tokens=[title];const url=TimelineModel.TimelineData.forEvent(traceEvent).url;if(url)
tokens.push(url);appendObjectProperties(traceEvent.args,2);return regExp.test(tokens.join('|'));function appendObjectProperties(object,depth){if(!depth)
return;for(const key in object){const value=object[key];const type=typeof value;if(type==='string')
tokens.push(value);else if(type==='number')
tokens.push(String(value));else if(type==='object')
appendObjectProperties(value,depth-1);}}}
static eventURL(event){const data=event.args['data']||event.args['beginData'];const url=data&&data.url;if(url)
return url;const stackTrace=data&&data['stackTrace'];const frame=stackTrace&&stackTrace.length&&stackTrace[0]||TimelineModel.TimelineData.forEvent(event).topFrame();return frame&&frame.url||null;}
static eventStyle(event){const eventStyles=Timeline.TimelineUIUtils._initEventStyles();if(event.hasCategory(TimelineModel.TimelineModel.Category.Console)||event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming))
return{title:event.name,category:Timeline.TimelineUIUtils.categories()['scripting']};if(event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)){const prefix='InputLatency::';const inputEventType=event.name.startsWith(prefix)?event.name.substr(prefix.length):event.name;const displayName=Timeline.TimelineUIUtils.inputEventDisplayName((inputEventType));return{title:displayName||inputEventType,category:Timeline.TimelineUIUtils.categories()['scripting']};}
let result=eventStyles[event.name];if(!result){result=new Timeline.TimelineRecordStyle(event.name,Timeline.TimelineUIUtils.categories()['other'],true);eventStyles[event.name]=result;}
return result;}
static eventColor(event){if(event.name===TimelineModel.TimelineModel.RecordType.JSFrame){const frame=event.args['data'];if(Timeline.TimelineUIUtils.isUserFrame(frame))
return Timeline.TimelineUIUtils.colorForId(frame.url);}
return Timeline.TimelineUIUtils.eventStyle(event).category.color;}
static eventColorByProduct(productRegistry,model,urlToColorCache,event){const url=Timeline.TimelineUIUtils.eventURL(event)||'';let color=urlToColorCache.get(url);if(color)
return color;const defaultColor='#f2ecdc';const parsedURL=url.asParsedURL();if(!parsedURL)
return defaultColor;let name=productRegistry&&productRegistry.nameForUrl(parsedURL);if(!name){name=parsedURL.host;const rootFrames=model.rootFrames();if(rootFrames.some(pageFrame=>new Common.ParsedURL(pageFrame.url).host===name))
color=defaultColor;}
if(!color)
color=name?ProductRegistry.BadgePool.colorForEntryName(name):defaultColor;urlToColorCache.set(url,color);return color;}
static eventTitle(event){const recordType=TimelineModel.TimelineModel.RecordType;const eventData=event.args['data'];if(event.name===recordType.JSFrame)
return Timeline.TimelineUIUtils.frameDisplayName(eventData);const title=Timeline.TimelineUIUtils.eventStyle(event).title;if(event.hasCategory(TimelineModel.TimelineModel.Category.Console))
return title;if(event.name===recordType.TimeStamp)
return Common.UIString('%s: %s',title,eventData['message']);if(event.name===recordType.Animation&&eventData&&eventData['name'])
return Common.UIString('%s: %s',title,eventData['name']);return title;}
static _interactionPhaseStyles(){let map=Timeline.TimelineUIUtils._interactionPhaseStylesMap;if(!map){map=new Map([[TimelineModel.TimelineIRModel.Phases.Idle,{color:'white',label:'Idle'}],[TimelineModel.TimelineIRModel.Phases.Response,{color:'hsl(43, 83%, 64%)',label:Common.UIString('Response')}],[TimelineModel.TimelineIRModel.Phases.Scroll,{color:'hsl(256, 67%, 70%)',label:Common.UIString('Scroll')}],[TimelineModel.TimelineIRModel.Phases.Fling,{color:'hsl(256, 67%, 70%)',label:Common.UIString('Fling')}],[TimelineModel.TimelineIRModel.Phases.Drag,{color:'hsl(256, 67%, 70%)',label:Common.UIString('Drag')}],[TimelineModel.TimelineIRModel.Phases.Animation,{color:'hsl(256, 67%, 70%)',label:Common.UIString('Animation')}],[TimelineModel.TimelineIRModel.Phases.Uncategorized,{color:'hsl(0, 0%, 87%)',label:Common.UIString('Uncategorized')}]]);Timeline.TimelineUIUtils._interactionPhaseStylesMap=map;}
return map;}
static interactionPhaseColor(phase){return Timeline.TimelineUIUtils._interactionPhaseStyles().get(phase).color;}
static interactionPhaseLabel(phase){return Timeline.TimelineUIUtils._interactionPhaseStyles().get(phase).label;}
static isUserFrame(frame){return frame.scriptId!=='0'&&!(frame.url&&frame.url.startsWith('native '));}
static networkRequestCategory(request){const categories=Timeline.TimelineUIUtils.NetworkCategory;switch(request.mimeType){case'text/html':return categories.HTML;case'application/javascript':case'application/x-javascript':case'text/javascript':return categories.Script;case'text/css':return categories.Style;case'audio/ogg':case'image/gif':case'image/jpeg':case'image/png':case'image/svg+xml':case'image/webp':case'image/x-icon':case'font/opentype':case'font/woff2':case'application/font-woff':return categories.Media;default:return categories.Other;}}
static networkCategoryColor(category){const categories=Timeline.TimelineUIUtils.NetworkCategory;switch(category){case categories.HTML:return'hsl(214, 67%, 66%)';case categories.Script:return'hsl(43, 83%, 64%)';case categories.Style:return'hsl(256, 67%, 70%)';case categories.Media:return'hsl(109, 33%, 55%)';default:return'hsl(0, 0%, 70%)';}}
static buildDetailsTextForTraceEvent(event,target){const recordType=TimelineModel.TimelineModel.RecordType;let detailsText;const eventData=event.args['data'];switch(event.name){case recordType.GCEvent:case recordType.MajorGC:case recordType.MinorGC:{const delta=event.args['usedHeapSizeBefore']-event.args['usedHeapSizeAfter'];detailsText=Common.UIString('%s collected',Number.bytesToString(delta));break;}
case recordType.FunctionCall:if(eventData){detailsText=linkifyLocationAsText(eventData['scriptId'],eventData['lineNumber'],eventData['columnNumber']);}
break;case recordType.JSFrame:detailsText=Timeline.TimelineUIUtils.frameDisplayName(eventData);break;case recordType.EventDispatch:detailsText=eventData?eventData['type']:null;break;case recordType.Paint:{const width=Timeline.TimelineUIUtils.quadWidth(eventData.clip);const height=Timeline.TimelineUIUtils.quadHeight(eventData.clip);if(width&&height)
detailsText=Common.UIString('%d\xa0\u00d7\xa0%d',width,height);break;}
case recordType.ParseHTML:{const endLine=event.args['endData']&&event.args['endData']['endLine'];const url=Bindings.displayNameForURL(event.args['beginData']['url']);detailsText=Common.UIString('%s [%s\u2026%s]',url,event.args['beginData']['startLine']+1,endLine>=0?endLine+1:'');break;}
case recordType.CompileModule:detailsText=Bindings.displayNameForURL(event.args['fileName']);break;case recordType.CompileScript:case recordType.EvaluateScript:{const url=eventData&&eventData['url'];if(url)
detailsText=Bindings.displayNameForURL(url)+':'+(eventData['lineNumber']+1);break;}
case recordType.ParseScriptOnBackground:case recordType.XHRReadyStateChange:case recordType.XHRLoad:{const url=eventData['url'];if(url)
detailsText=Bindings.displayNameForURL(url);break;}
case recordType.TimeStamp:detailsText=eventData['message'];break;case recordType.WebSocketCreate:case recordType.WebSocketSendHandshakeRequest:case recordType.WebSocketReceiveHandshakeResponse:case recordType.WebSocketDestroy:case recordType.ResourceSendRequest:case recordType.ResourceReceivedData:case recordType.ResourceReceiveResponse:case recordType.ResourceFinish:case recordType.PaintImage:case recordType.DecodeImage:case recordType.ResizeImage:case recordType.DecodeLazyPixelRef:{const url=TimelineModel.TimelineData.forEvent(event).url;if(url)
detailsText=Bindings.displayNameForURL(url);break;}
case recordType.EmbedderCallback:detailsText=eventData['callbackName'];break;case recordType.Animation:detailsText=eventData&&eventData['name'];break;case recordType.GCIdleLazySweep:detailsText=Common.UIString('idle sweep');break;case recordType.GCCompleteSweep:detailsText=Common.UIString('complete sweep');break;case recordType.GCCollectGarbage:detailsText=Common.UIString('collect');break;case recordType.AsyncTask:detailsText=eventData?eventData['name']:null;break;default:if(event.hasCategory(TimelineModel.TimelineModel.Category.Console))
detailsText=null;else
detailsText=linkifyTopCallFrameAsText();break;}
return detailsText;function linkifyLocationAsText(scriptId,lineNumber,columnNumber){const debuggerModel=target?target.model(SDK.DebuggerModel):null;if(!target||target.isDisposed()||!scriptId||!debuggerModel)
return null;const rawLocation=debuggerModel.createRawLocationByScriptId(scriptId,lineNumber,columnNumber);if(!rawLocation)
return null;const uiLocation=Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(rawLocation);return uiLocation?uiLocation.linkText():null;}
function linkifyTopCallFrameAsText(){const frame=TimelineModel.TimelineData.forEvent(event).topFrame();if(!frame)
return null;let text=linkifyLocationAsText(frame.scriptId,frame.lineNumber,frame.columnNumber);if(!text){text=frame.url;if(typeof frame.lineNumber==='number')
text+=':'+(frame.lineNumber+1);}
return text;}}
static buildDetailsNodeForTraceEvent(event,target,linkifier){const recordType=TimelineModel.TimelineModel.RecordType;let details=null;let detailsText;const eventData=event.args['data'];switch(event.name){case recordType.GCEvent:case recordType.MajorGC:case recordType.MinorGC:case recordType.EventDispatch:case recordType.Paint:case recordType.Animation:case recordType.EmbedderCallback:case recordType.ParseHTML:case recordType.WebSocketCreate:case recordType.WebSocketSendHandshakeRequest:case recordType.WebSocketReceiveHandshakeResponse:case recordType.WebSocketDestroy:case recordType.GCIdleLazySweep:case recordType.GCCompleteSweep:case recordType.GCCollectGarbage:detailsText=Timeline.TimelineUIUtils.buildDetailsTextForTraceEvent(event,target);break;case recordType.PaintImage:case recordType.DecodeImage:case recordType.ResizeImage:case recordType.DecodeLazyPixelRef:case recordType.XHRReadyStateChange:case recordType.XHRLoad:case recordType.ResourceSendRequest:case recordType.ResourceReceivedData:case recordType.ResourceReceiveResponse:case recordType.ResourceFinish:{const url=TimelineModel.TimelineData.forEvent(event).url;if(url)
details=Components.Linkifier.linkifyURL(url);break;}
case recordType.FunctionCall:case recordType.JSFrame:details=createElement('span');details.createTextChild(Timeline.TimelineUIUtils.frameDisplayName(eventData));const location=linkifyLocation(eventData['scriptId'],eventData['url'],eventData['lineNumber'],eventData['columnNumber']);if(location){details.createTextChild(' @ ');details.appendChild(location);}
break;case recordType.CompileModule:details=linkifyLocation('',event.args['fileName'],0,0);break;case recordType.CompileScript:case recordType.EvaluateScript:{const url=eventData['url'];if(url)
details=linkifyLocation('',url,eventData['lineNumber'],0);break;}
case recordType.ParseScriptOnBackground:{const url=eventData['url'];if(url)
details=linkifyLocation('',url,0,0);break;}
default:if(event.hasCategory(TimelineModel.TimelineModel.Category.Console))
detailsText=null;else
details=linkifyTopCallFrame();break;}
if(!details&&detailsText)
details=createTextNode(detailsText);return details;function linkifyLocation(scriptId,url,lineNumber,columnNumber){return linkifier.linkifyScriptLocation(target,scriptId,url,lineNumber,columnNumber,'timeline-details');}
function linkifyTopCallFrame(){const frame=TimelineModel.TimelineData.forEvent(event).topFrame();return frame?linkifier.maybeLinkifyConsoleCallFrame(target,frame,'timeline-details'):null;}}
static async buildTraceEventDetails(event,model,linkifier,badgePool,detailed){const maybeTarget=model.targetByEvent(event);let relatedNodesMap=null;if(maybeTarget){const target=(maybeTarget);if(typeof event[Timeline.TimelineUIUtils._previewElementSymbol]==='undefined'){let previewElement=null;const url=TimelineModel.TimelineData.forEvent(event).url;if(url)
previewElement=await BrowserComponents.ImagePreview.build(target,url,false);else if(TimelineModel.TimelineData.forEvent(event).picture)
previewElement=await Timeline.TimelineUIUtils.buildPicturePreviewContent(event,target);event[Timeline.TimelineUIUtils._previewElementSymbol]=previewElement;}
const nodeIdsToResolve=new Set();const timelineData=TimelineModel.TimelineData.forEvent(event);if(timelineData.backendNodeId)
nodeIdsToResolve.add(timelineData.backendNodeId);const invalidationTrackingEvents=TimelineModel.InvalidationTracker.invalidationEventsFor(event);if(invalidationTrackingEvents)
Timeline.TimelineUIUtils._collectInvalidationNodeIds(nodeIdsToResolve,invalidationTrackingEvents);if(nodeIdsToResolve.size){const domModel=target.model(SDK.DOMModel);if(domModel)
relatedNodesMap=await domModel.pushNodesByBackendIdsToFrontend(nodeIdsToResolve);}}
const recordTypes=TimelineModel.TimelineModel.RecordType;let relatedNodeLabel;const contentHelper=new Timeline.TimelineDetailsContentHelper(model.targetByEvent(event),linkifier);contentHelper.addSection(Timeline.TimelineUIUtils.eventTitle(event),Timeline.TimelineUIUtils.eventStyle(event).category.color);const eventData=event.args['data'];const timelineData=TimelineModel.TimelineData.forEvent(event);const initiator=timelineData.initiator();let url=null;if(timelineData.warning)
contentHelper.appendWarningRow(event);if(event.name===recordTypes.JSFrame&&eventData['deoptReason'])
contentHelper.appendWarningRow(event,TimelineModel.TimelineModel.WarningType.V8Deopt);if(detailed){contentHelper.appendTextRow(Common.UIString('Total Time'),Number.millisToString(event.duration||0,true));contentHelper.appendTextRow(Common.UIString('Self Time'),Number.millisToString(event.selfTime,true));}
if(model.isGenericTrace()){for(const key in event.args){try{contentHelper.appendTextRow(key,JSON.stringify(event.args[key]));}catch(e){contentHelper.appendTextRow(key,`<${typeof event.args[key]}>`);}}
return contentHelper.fragment;}
switch(event.name){case recordTypes.GCEvent:case recordTypes.MajorGC:case recordTypes.MinorGC:const delta=event.args['usedHeapSizeBefore']-event.args['usedHeapSizeAfter'];contentHelper.appendTextRow(Common.UIString('Collected'),Number.bytesToString(delta));break;case recordTypes.JSFrame:case recordTypes.FunctionCall:const detailsNode=Timeline.TimelineUIUtils.buildDetailsNodeForTraceEvent(event,model.targetByEvent(event),linkifier);if(detailsNode)
contentHelper.appendElementRow(Common.UIString('Function'),detailsNode);break;case recordTypes.TimerFire:case recordTypes.TimerInstall:case recordTypes.TimerRemove:contentHelper.appendTextRow(Common.UIString('Timer ID'),eventData['timerId']);if(event.name===recordTypes.TimerInstall){contentHelper.appendTextRow(Common.UIString('Timeout'),Number.millisToString(eventData['timeout']));contentHelper.appendTextRow(Common.UIString('Repeats'),!eventData['singleShot']);}
break;case recordTypes.FireAnimationFrame:contentHelper.appendTextRow(Common.UIString('Callback ID'),eventData['id']);break;case recordTypes.ResourceSendRequest:case recordTypes.ResourceReceiveResponse:case recordTypes.ResourceReceivedData:case recordTypes.ResourceFinish:url=timelineData.url;if(url)
contentHelper.appendElementRow(Common.UIString('Resource'),Components.Linkifier.linkifyURL(url));if(eventData['requestMethod'])
contentHelper.appendTextRow(Common.UIString('Request Method'),eventData['requestMethod']);if(typeof eventData['statusCode']==='number')
contentHelper.appendTextRow(Common.UIString('Status Code'),eventData['statusCode']);if(eventData['mimeType'])
contentHelper.appendTextRow(Common.UIString('MIME Type'),eventData['mimeType']);if('priority'in eventData){const priority=PerfUI.uiLabelForNetworkPriority(eventData['priority']);contentHelper.appendTextRow(Common.UIString('Priority'),priority);}
if(eventData['encodedDataLength']){contentHelper.appendTextRow(Common.UIString('Encoded Data'),Common.UIString('%d Bytes',eventData['encodedDataLength']));}
if(eventData['decodedBodyLength']){contentHelper.appendTextRow(Common.UIString('Decoded Body'),Common.UIString('%d Bytes',eventData['decodedBodyLength']));}
break;case recordTypes.CompileModule:contentHelper.appendLocationRow(Common.UIString('Module'),event.args['fileName'],0);break;case recordTypes.CompileScript:url=eventData&&eventData['url'];if(url){contentHelper.appendLocationRow(Common.UIString('Script'),url,eventData['lineNumber'],eventData['columnNumber']);}
contentHelper.appendTextRow(Common.UIString('Streamed'),Common.UIString('%s',eventData['streamed']));const cacheProduceOptions=eventData&&eventData['cacheProduceOptions'];if(cacheProduceOptions){contentHelper.appendTextRow(Common.UIString('Cache Produce Options'),Common.UIString('%s',cacheProduceOptions));contentHelper.appendTextRow(Common.UIString('Produced Cache Size'),Common.UIString('%d',eventData['producedCacheSize']));}
const cacheConsumeOptions=eventData&&eventData['cacheConsumeOptions'];if(cacheConsumeOptions){contentHelper.appendTextRow(Common.UIString('Cache Consume Options'),Common.UIString('%s',cacheConsumeOptions));contentHelper.appendTextRow(Common.UIString('Consumed Cache Size'),Common.UIString('%d',eventData['consumedCacheSize']));contentHelper.appendTextRow(Common.UIString('Cache Rejected'),Common.UIString('%s',eventData['cacheRejected']));}
break;case recordTypes.EvaluateScript:url=eventData&&eventData['url'];if(url){contentHelper.appendLocationRow(Common.UIString('Script'),url,eventData['lineNumber'],eventData['columnNumber']);}
break;case recordTypes.Paint:const clip=eventData['clip'];contentHelper.appendTextRow(Common.UIString('Location'),Common.UIString('(%d, %d)',clip[0],clip[1]));const clipWidth=Timeline.TimelineUIUtils.quadWidth(clip);const clipHeight=Timeline.TimelineUIUtils.quadHeight(clip);contentHelper.appendTextRow(Common.UIString('Dimensions'),Common.UIString('%d × %d',clipWidth,clipHeight));case recordTypes.PaintSetup:case recordTypes.Rasterize:case recordTypes.ScrollLayer:relatedNodeLabel=Common.UIString('Layer Root');break;case recordTypes.PaintImage:case recordTypes.DecodeLazyPixelRef:case recordTypes.DecodeImage:case recordTypes.ResizeImage:case recordTypes.DrawLazyPixelRef:relatedNodeLabel=Common.UIString('Owner Element');url=timelineData.url;if(url)
contentHelper.appendElementRow(Common.UIString('Image URL'),Components.Linkifier.linkifyURL(url));break;case recordTypes.ParseAuthorStyleSheet:url=eventData['styleSheetUrl'];if(url)
contentHelper.appendElementRow(Common.UIString('Stylesheet URL'),Components.Linkifier.linkifyURL(url));break;case recordTypes.UpdateLayoutTree:case recordTypes.RecalculateStyles:contentHelper.appendTextRow(Common.UIString('Elements Affected'),event.args['elementCount']);break;case recordTypes.Layout:const beginData=event.args['beginData'];contentHelper.appendTextRow(Common.UIString('Nodes That Need Layout'),Common.UIString('%s of %s',beginData['dirtyObjects'],beginData['totalObjects']));relatedNodeLabel=Common.UIString('Layout root');break;case recordTypes.ConsoleTime:contentHelper.appendTextRow(Common.UIString('Message'),event.name);break;case recordTypes.WebSocketCreate:case recordTypes.WebSocketSendHandshakeRequest:case recordTypes.WebSocketReceiveHandshakeResponse:case recordTypes.WebSocketDestroy:const initiatorData=initiator?initiator.args['data']:eventData;if(typeof initiatorData['webSocketURL']!=='undefined')
contentHelper.appendTextRow(Common.UIString('URL'),initiatorData['webSocketURL']);if(typeof initiatorData['webSocketProtocol']!=='undefined')
contentHelper.appendTextRow(Common.UIString('WebSocket Protocol'),initiatorData['webSocketProtocol']);if(typeof eventData['message']!=='undefined')
contentHelper.appendTextRow(Common.UIString('Message'),eventData['message']);break;case recordTypes.EmbedderCallback:contentHelper.appendTextRow(Common.UIString('Callback Function'),eventData['callbackName']);break;case recordTypes.Animation:if(event.phase===SDK.TracingModel.Phase.NestableAsyncInstant)
contentHelper.appendTextRow(Common.UIString('State'),eventData['state']);break;case recordTypes.ParseHTML:{const beginData=event.args['beginData'];const startLine=beginData['startLine']-1;const endLine=event.args['endData']?event.args['endData']['endLine']-1:undefined;url=beginData['url'];if(url)
contentHelper.appendLocationRange(Common.UIString('Range'),url,startLine,endLine);break;}
case recordTypes.FireIdleCallback:contentHelper.appendTextRow(Common.UIString('Allotted Time'),Number.millisToString(eventData['allottedMilliseconds']));contentHelper.appendTextRow(Common.UIString('Invoked by Timeout'),eventData['timedOut']);case recordTypes.RequestIdleCallback:case recordTypes.CancelIdleCallback:contentHelper.appendTextRow(Common.UIString('Callback ID'),eventData['id']);break;case recordTypes.EventDispatch:contentHelper.appendTextRow(Common.UIString('Type'),eventData['type']);break;default:{const detailsNode=Timeline.TimelineUIUtils.buildDetailsNodeForTraceEvent(event,model.targetByEvent(event),linkifier);if(detailsNode)
contentHelper.appendElementRow(Common.UIString('Details'),detailsNode);break;}}
Timeline.TimelineUIUtils._maybeAppendProductToDetails(contentHelper,badgePool,url||eventData&&eventData['url']);if(timelineData.timeWaitingForMainThread){contentHelper.appendTextRow(Common.UIString('Time Waiting for Main Thread'),Number.millisToString(timelineData.timeWaitingForMainThread,true));}
const relatedNode=relatedNodesMap&&relatedNodesMap.get(timelineData.backendNodeId);if(relatedNode){const nodeSpan=await Common.Linkifier.linkify(relatedNode);contentHelper.appendElementRow(relatedNodeLabel||Common.UIString('Related Node'),nodeSpan);}
if(event[Timeline.TimelineUIUtils._previewElementSymbol]){contentHelper.addSection(Common.UIString('Preview'));contentHelper.appendElementRow('',event[Timeline.TimelineUIUtils._previewElementSymbol]);}
if(initiator||timelineData.stackTraceForSelfOrInitiator()||TimelineModel.InvalidationTracker.invalidationEventsFor(event))
Timeline.TimelineUIUtils._generateCauses(event,model.targetByEvent(event),relatedNodesMap,contentHelper);const stats={};const showPieChart=detailed&&Timeline.TimelineUIUtils._aggregatedStatsForTraceEvent(stats,model,event);if(showPieChart){contentHelper.addSection(Common.UIString('Aggregated Time'));const pieChart=Timeline.TimelineUIUtils.generatePieChart(stats,Timeline.TimelineUIUtils.eventStyle(event).category,event.selfTime);contentHelper.appendElementRow('',pieChart);}
return contentHelper.fragment;}
static _maybeAppendProductToDetails(contentHelper,badgePool,url){const parsedURL=url?url.asParsedURL():null;if(parsedURL)
contentHelper.appendElementRow('',badgePool.badgeForURL(parsedURL));}
static statsForTimeRange(events,startTime,endTime){if(!events.length)
return{'idle':endTime-startTime};const symbol=Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol;Timeline.TimelineUIUtils._buildRangeStatsCacheIfNeeded(events);const before=findCachedStatsAfterTime(startTime);const statsBefore=subtractStats(before.stats,Timeline.TimelineUIUtils._slowStatsForTimeRange(events,startTime,before.time));const after=findCachedStatsAfterTime(endTime);const statsAfter=subtractStats(after.stats,Timeline.TimelineUIUtils._slowStatsForTimeRange(events,endTime,after.time));const aggregatedStats=subtractStats(statsAfter,statsBefore);const aggregatedTotal=Object.values(aggregatedStats).reduce((a,b)=>a+b,0);aggregatedStats['idle']=Math.max(0,endTime-startTime-aggregatedTotal);return aggregatedStats;function findCachedStatsAfterTime(atTime){let index=events.lowerBound(atTime,(time,event)=>time-(event.endTime||event.startTime));while(index<events.length&&!events[index][symbol])
index++;if(index===events.length){const lastEvent=events.peekLast();return{time:lastEvent.endTime||lastEvent.startTime,stats:events[symbol]};}
const event=events[index];return{time:event.endTime||event.startTime,stats:event[symbol]};}
function subtractStats(a,b){const result=Object.assign({},a);for(const key in b)
result[key]-=b[key];return result;}}
static _slowStatsForTimeRange(events,startTime,endTime){const stats={};const ownTimes=[];TimelineModel.TimelineModel.forEachEvent(events,onStartEvent,onEndEvent,undefined,startTime,endTime,Timeline.TimelineUIUtils._filterForStats());function onStartEvent(e){const duration=Math.min(e.endTime,endTime)-Math.max(e.startTime,startTime);if(ownTimes.length)
ownTimes[ownTimes.length-1]-=duration;ownTimes.push(duration);}
function onEndEvent(e){const category=Timeline.TimelineUIUtils.eventStyle(e).category.name;stats[category]=(stats[category]||0)+ownTimes.pop();}
return stats;}
static _filterForStats(){const visibleEventsFilter=Timeline.TimelineUIUtils.visibleEventsFilter();return event=>visibleEventsFilter.accept(event)||SDK.TracingModel.isTopLevelEvent(event);}
static _buildRangeStatsCacheIfNeeded(events){if(events[Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol])
return;const aggregatedStats={};const ownTimes=[];TimelineModel.TimelineModel.forEachEvent(events,onStartEvent,onEndEvent,undefined,undefined,undefined,Timeline.TimelineUIUtils._filterForStats());function onStartEvent(e){if(ownTimes.length)
ownTimes[ownTimes.length-1]-=e.duration;ownTimes.push(e.duration);}
function onEndEvent(e){const category=Timeline.TimelineUIUtils.eventStyle(e).category.name;aggregatedStats[category]=(aggregatedStats[category]||0)+ownTimes.pop();if(!ownTimes.length)
e[Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol]=Object.assign({},aggregatedStats);}
const obj=(events);obj[Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol]=Object.assign({},aggregatedStats);}
static async buildNetworkRequestDetails(request,model,linkifier,badgePool){const target=model.targetByEvent(request.children[0]);const contentHelper=new Timeline.TimelineDetailsContentHelper(target,linkifier);const category=Timeline.TimelineUIUtils.networkRequestCategory(request);const color=Timeline.TimelineUIUtils.networkCategoryColor(category);contentHelper.addSection(Common.UIString('Network request'),color);const duration=request.endTime-(request.startTime||-Infinity);if(request.url)
contentHelper.appendElementRow(Common.UIString('URL'),Components.Linkifier.linkifyURL(request.url));Timeline.TimelineUIUtils._maybeAppendProductToDetails(contentHelper,badgePool,request.url);if(isFinite(duration))
contentHelper.appendTextRow(Common.UIString('Duration'),Number.millisToString(duration,true));if(request.requestMethod)
contentHelper.appendTextRow(Common.UIString('Request Method'),request.requestMethod);if(typeof request.priority==='string'){const priority=PerfUI.uiLabelForNetworkPriority((request.priority));contentHelper.appendTextRow(Common.UIString('Priority'),priority);}
if(request.mimeType)
contentHelper.appendTextRow(Common.UIString('Mime Type'),request.mimeType);let lengthText='';if(request.fromCache)
lengthText+=Common.UIString(' (from cache)');if(request.fromServiceWorker)
lengthText+=Common.UIString(' (from service worker)');if(request.encodedDataLength||!lengthText)
lengthText=`${Number.bytesToString(request.encodedDataLength)}${lengthText}`;contentHelper.appendTextRow(Common.UIString('Encoded Data'),lengthText);if(request.decodedBodyLength)
contentHelper.appendTextRow(Common.UIString('Decoded Body'),Number.bytesToString(request.decodedBodyLength));const title=Common.UIString('Initiator');const sendRequest=request.children[0];const topFrame=TimelineModel.TimelineData.forEvent(sendRequest).topFrame();if(topFrame){const link=linkifier.maybeLinkifyConsoleCallFrame(target,topFrame);if(link)
contentHelper.appendElementRow(title,link);}else{const initiator=TimelineModel.TimelineData.forEvent(sendRequest).initiator();if(initiator){const initiatorURL=TimelineModel.TimelineData.forEvent(initiator).url;if(initiatorURL){const link=linkifier.maybeLinkifyScriptLocation(target,null,initiatorURL,0);if(link)
contentHelper.appendElementRow(title,link);}}}
if(!request.previewElement&&request.url&&target)
request.previewElement=await BrowserComponents.ImagePreview.build(target,request.url,false);if(request.previewElement)
contentHelper.appendElementRow(Common.UIString('Preview'),request.previewElement);return contentHelper.fragment;}
static _stackTraceFromCallFrames(callFrames){return({callFrames:callFrames});}
static _generateCauses(event,target,relatedNodesMap,contentHelper){const recordTypes=TimelineModel.TimelineModel.RecordType;let callSiteStackLabel;let stackLabel;switch(event.name){case recordTypes.TimerFire:callSiteStackLabel=Common.UIString('Timer Installed');break;case recordTypes.FireAnimationFrame:callSiteStackLabel=Common.UIString('Animation Frame Requested');break;case recordTypes.FireIdleCallback:callSiteStackLabel=Common.UIString('Idle Callback Requested');break;case recordTypes.UpdateLayoutTree:case recordTypes.RecalculateStyles:stackLabel=Common.UIString('Recalculation Forced');break;case recordTypes.Layout:callSiteStackLabel=Common.UIString('First Layout Invalidation');stackLabel=Common.UIString('Layout Forced');break;}
const timelineData=TimelineModel.TimelineData.forEvent(event);if(timelineData.stackTrace&&timelineData.stackTrace.length){contentHelper.addSection(Common.UIString('Call Stacks'));contentHelper.appendStackTrace(stackLabel||Common.UIString('Stack Trace'),Timeline.TimelineUIUtils._stackTraceFromCallFrames(timelineData.stackTrace));}
const initiator=TimelineModel.TimelineData.forEvent(event).initiator();if(TimelineModel.InvalidationTracker.invalidationEventsFor(event)&&target){contentHelper.addSection(Common.UIString('Invalidations'));Timeline.TimelineUIUtils._generateInvalidations(event,target,relatedNodesMap,contentHelper);}else if(initiator){const delay=event.startTime-initiator.startTime;contentHelper.appendTextRow(Common.UIString('Pending for'),Number.preciseMillisToString(delay,1));const link=createElementWithClass('span','devtools-link');link.textContent=Common.UIString('reveal');link.addEventListener('click',()=>{Timeline.TimelinePanel.instance().select(Timeline.TimelineSelection.fromTraceEvent((initiator)));});contentHelper.appendElementRow(Common.UIString('Initiator'),link);const initiatorStackTrace=TimelineModel.TimelineData.forEvent(initiator).stackTrace;if(initiatorStackTrace){contentHelper.appendStackTrace(callSiteStackLabel||Common.UIString('First Invalidated'),Timeline.TimelineUIUtils._stackTraceFromCallFrames(initiatorStackTrace));}}}
static _generateInvalidations(event,target,relatedNodesMap,contentHelper){const invalidationTrackingEvents=TimelineModel.InvalidationTracker.invalidationEventsFor(event);const invalidations={};invalidationTrackingEvents.forEach(function(invalidation){if(!invalidations[invalidation.type])
invalidations[invalidation.type]=[invalidation];else
invalidations[invalidation.type].push(invalidation);});Object.keys(invalidations).forEach(function(type){Timeline.TimelineUIUtils._generateInvalidationsForType(type,target,invalidations[type],relatedNodesMap,contentHelper);});}
static _generateInvalidationsForType(type,target,invalidations,relatedNodesMap,contentHelper){let title;switch(type){case TimelineModel.TimelineModel.RecordType.StyleRecalcInvalidationTracking:title=Common.UIString('Style Invalidations');break;case TimelineModel.TimelineModel.RecordType.LayoutInvalidationTracking:title=Common.UIString('Layout Invalidations');break;default:title=Common.UIString('Other Invalidations');break;}
const invalidationsTreeOutline=new UI.TreeOutlineInShadow();invalidationsTreeOutline.registerRequiredCSS('timeline/invalidationsTree.css');invalidationsTreeOutline.element.classList.add('invalidations-tree');const invalidationGroups=groupInvalidationsByCause(invalidations);invalidationGroups.forEach(function(group){const groupElement=new Timeline.TimelineUIUtils.InvalidationsGroupElement(target,relatedNodesMap,contentHelper,group);invalidationsTreeOutline.appendChild(groupElement);});contentHelper.appendElementRow(title,invalidationsTreeOutline.element,false,true);function groupInvalidationsByCause(invalidations){const causeToInvalidationMap=new Map();for(let index=0;index<invalidations.length;index++){const invalidation=invalidations[index];let causeKey='';if(invalidation.cause.reason)
causeKey+=invalidation.cause.reason+'.';if(invalidation.cause.stackTrace){invalidation.cause.stackTrace.forEach(function(stackFrame){causeKey+=stackFrame['functionName']+'.';causeKey+=stackFrame['scriptId']+'.';causeKey+=stackFrame['url']+'.';causeKey+=stackFrame['lineNumber']+'.';causeKey+=stackFrame['columnNumber']+'.';});}
if(causeToInvalidationMap.has(causeKey))
causeToInvalidationMap.get(causeKey).push(invalidation);else
causeToInvalidationMap.set(causeKey,[invalidation]);}
return causeToInvalidationMap.valuesArray();}}
static _collectInvalidationNodeIds(nodeIds,invalidations){nodeIds.addAll(invalidations.map(invalidation=>invalidation.nodeId).filter(id=>id));}
static _aggregatedStatsForTraceEvent(total,model,event){const events=model.inspectedTargetEvents();function eventComparator(startTime,e){return startTime-e.startTime;}
const index=events.binaryIndexOf(event.startTime,eventComparator);if(index<0)
return false;let hasChildren=false;const endTime=event.endTime;if(endTime){for(let i=index;i<events.length;i++){const nextEvent=events[i];if(nextEvent.startTime>=endTime)
break;if(!nextEvent.selfTime)
continue;if(nextEvent.thread!==event.thread)
continue;if(i>index)
hasChildren=true;const categoryName=Timeline.TimelineUIUtils.eventStyle(nextEvent).category.name;total[categoryName]=(total[categoryName]||0)+nextEvent.selfTime;}}
if(SDK.TracingModel.isAsyncPhase(event.phase)){if(event.endTime){let aggregatedTotal=0;for(const categoryName in total)
aggregatedTotal+=total[categoryName];total['idle']=Math.max(0,event.endTime-event.startTime-aggregatedTotal);}
return false;}
return hasChildren;}
static async buildPicturePreviewContent(event,target){const snapshotWithRect=await new TimelineModel.LayerPaintEvent(event,target).snapshotPromise();if(!snapshotWithRect)
return null;const imageURLPromise=snapshotWithRect.snapshot.replay();snapshotWithRect.snapshot.release();const imageURL=await imageURLPromise;if(!imageURL)
return null;const container=createElement('div');UI.appendStyle(container,'browser_components/imagePreview.css');container.classList.add('image-preview-container','vbox','link');const img=container.createChild('img');img.src=imageURL;const paintProfilerButton=container.createChild('a');paintProfilerButton.textContent=Common.UIString('Paint Profiler');container.addEventListener('click',()=>Timeline.TimelinePanel.instance().select(Timeline.TimelineSelection.fromTraceEvent(event)),false);return container;}
static createEventDivider(event,zeroTime){const eventDivider=createElementWithClass('div','resources-event-divider');const startTime=Number.millisToString(event.startTime-zeroTime);eventDivider.title=Common.UIString('%s at %s',Timeline.TimelineUIUtils.eventTitle(event),startTime);const style=Timeline.TimelineUIUtils.markerStyleForEvent(event);if(style.tall)
eventDivider.style.backgroundColor=style.color;return eventDivider;}
static _visibleTypes(){const eventStyles=Timeline.TimelineUIUtils._initEventStyles();const result=[];for(const name in eventStyles){if(!eventStyles[name].hidden)
result.push(name);}
return result;}
static visibleEventsFilter(){return new TimelineModel.TimelineVisibleEventsFilter(Timeline.TimelineUIUtils._visibleTypes());}
static paintEventsFilter(){const recordTypes=TimelineModel.TimelineModel.RecordType;return new TimelineModel.TimelineInvisibleEventsFilter(!Runtime.experiments.isEnabled('timelinePaintTimingMarkers')?[recordTypes.MarkFCP,recordTypes.MarkFMP,recordTypes.MarkFMPCandidate]:[]);}
static categories(){if(Timeline.TimelineUIUtils._categories)
return Timeline.TimelineUIUtils._categories;Timeline.TimelineUIUtils._categories={loading:new Timeline.TimelineCategory('loading',Common.UIString('Loading'),true,'hsl(214, 67%, 74%)','hsl(214, 67%, 66%)'),scripting:new Timeline.TimelineCategory('scripting',Common.UIString('Scripting'),true,'hsl(43, 83%, 72%)','hsl(43, 83%, 64%) '),rendering:new Timeline.TimelineCategory('rendering',Common.UIString('Rendering'),true,'hsl(256, 67%, 76%)','hsl(256, 67%, 70%)'),painting:new Timeline.TimelineCategory('painting',Common.UIString('Painting'),true,'hsl(109, 33%, 64%)','hsl(109, 33%, 55%)'),gpu:new Timeline.TimelineCategory('gpu',Common.UIString('GPU'),false,'hsl(109, 33%, 64%)','hsl(109, 33%, 55%)'),async:new Timeline.TimelineCategory('async',Common.UIString('Async'),false,'hsl(0, 100%, 50%)','hsl(0, 100%, 40%)'),other:new Timeline.TimelineCategory('other',Common.UIString('Other'),false,'hsl(0, 0%, 87%)','hsl(0, 0%, 79%)'),idle:new Timeline.TimelineCategory('idle',Common.UIString('Idle'),false,'hsl(0, 0%, 98%)','hsl(0, 0%, 98%)')};return Timeline.TimelineUIUtils._categories;}
static generatePieChart(aggregatedStats,selfCategory,selfTime){let total=0;for(const categoryName in aggregatedStats)
total+=aggregatedStats[categoryName];const element=createElementWithClass('div','timeline-details-view-pie-chart-wrapper hbox');const pieChart=new PerfUI.PieChart(110,value=>Number.preciseMillisToString(value),true);pieChart.element.classList.add('timeline-details-view-pie-chart');pieChart.setTotal(total);const pieChartContainer=element.createChild('div','vbox');pieChartContainer.appendChild(pieChart.element);const footerElement=element.createChild('div','timeline-aggregated-info-legend');function appendLegendRow(name,title,value,color){if(!value)
return;pieChart.addSlice(value,color);const rowElement=footerElement.createChild('div');rowElement.createChild('span','timeline-aggregated-legend-value').textContent=Number.preciseMillisToString(value,1);rowElement.createChild('span','timeline-aggregated-legend-swatch').style.backgroundColor=color;rowElement.createChild('span','timeline-aggregated-legend-title').textContent=title;}
if(selfCategory){if(selfTime){appendLegendRow(selfCategory.name,Common.UIString('%s (self)',selfCategory.title),selfTime,selfCategory.color);}
const categoryTime=aggregatedStats[selfCategory.name];const value=categoryTime-selfTime;if(value>0){appendLegendRow(selfCategory.name,Common.UIString('%s (children)',selfCategory.title),value,selfCategory.childColor);}}
for(const categoryName in Timeline.TimelineUIUtils.categories()){const category=Timeline.TimelineUIUtils.categories()[categoryName];if(category===selfCategory)
continue;appendLegendRow(category.name,category.title,aggregatedStats[category.name],category.childColor);}
return element;}
static generateDetailsContentForFrame(frame,filmStripFrame){const contentHelper=new Timeline.TimelineDetailsContentHelper(null,null);contentHelper.addSection(Common.UIString('Frame'));const duration=Timeline.TimelineUIUtils.frameDuration(frame);contentHelper.appendElementRow(Common.UIString('Duration'),duration,frame.hasWarnings());const durationInMillis=frame.endTime-frame.startTime;contentHelper.appendTextRow(Common.UIString('FPS'),Math.floor(1000/durationInMillis));contentHelper.appendTextRow(Common.UIString('CPU time'),Number.millisToString(frame.cpuTime,true));if(filmStripFrame){const filmStripPreview=createElementWithClass('div','timeline-filmstrip-preview');filmStripFrame.imageDataPromise().then(data=>UI.loadImageFromData(data)).then(image=>image&&filmStripPreview.appendChild(image));contentHelper.appendElementRow('',filmStripPreview);filmStripPreview.addEventListener('click',frameClicked.bind(null,filmStripFrame),false);}
if(frame.layerTree){contentHelper.appendElementRow(Common.UIString('Layer tree'),Components.Linkifier.linkifyRevealable(frame.layerTree,Common.UIString('show')));}
function frameClicked(filmStripFrame){new PerfUI.FilmStripView.Dialog(filmStripFrame,0);}
return contentHelper.fragment;}
static frameDuration(frame){const durationText=Common.UIString('%s (at %s)',Number.millisToString(frame.endTime-frame.startTime,true),Number.millisToString(frame.startTimeOffset,true));const element=createElement('span');element.createTextChild(durationText);if(!frame.hasWarnings())
return element;element.createTextChild(Common.UIString('. Long frame times are an indication of '));element.appendChild(UI.XLink.create('https://developers.google.com/web/fundamentals/performance/rendering/',Common.UIString('jank')));element.createTextChild('.');return element;}
static createFillStyle(context,width,height,color0,color1,color2){const gradient=context.createLinearGradient(0,0,width,height);gradient.addColorStop(0,color0);gradient.addColorStop(0.25,color1);gradient.addColorStop(0.75,color1);gradient.addColorStop(1,color2);return gradient;}
static quadWidth(quad){return Math.round(Math.sqrt(Math.pow(quad[0]-quad[2],2)+Math.pow(quad[1]-quad[3],2)));}
static quadHeight(quad){return Math.round(Math.sqrt(Math.pow(quad[0]-quad[6],2)+Math.pow(quad[1]-quad[7],2)));}
static eventDispatchDesciptors(){if(Timeline.TimelineUIUtils._eventDispatchDesciptors)
return Timeline.TimelineUIUtils._eventDispatchDesciptors;const lightOrange='hsl(40,100%,80%)';const orange='hsl(40,100%,50%)';const green='hsl(90,100%,40%)';const purple='hsl(256,100%,75%)';Timeline.TimelineUIUtils._eventDispatchDesciptors=[new Timeline.TimelineUIUtils.EventDispatchTypeDescriptor(1,lightOrange,['mousemove','mouseenter','mouseleave','mouseout','mouseover']),new Timeline.TimelineUIUtils.EventDispatchTypeDescriptor(1,lightOrange,['pointerover','pointerout','pointerenter','pointerleave','pointermove']),new Timeline.TimelineUIUtils.EventDispatchTypeDescriptor(2,green,['wheel']),new Timeline.TimelineUIUtils.EventDispatchTypeDescriptor(3,orange,['click','mousedown','mouseup']),new Timeline.TimelineUIUtils.EventDispatchTypeDescriptor(3,orange,['touchstart','touchend','touchmove','touchcancel']),new Timeline.TimelineUIUtils.EventDispatchTypeDescriptor(3,orange,['pointerdown','pointerup','pointercancel','gotpointercapture','lostpointercapture']),new Timeline.TimelineUIUtils.EventDispatchTypeDescriptor(3,purple,['keydown','keyup','keypress'])];return Timeline.TimelineUIUtils._eventDispatchDesciptors;}
static markerStyleForEvent(event){const tallMarkerDashStyle=[10,5];const title=Timeline.TimelineUIUtils.eventTitle(event);if(event.hasCategory(TimelineModel.TimelineModel.Category.Console)||event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming)){return{title:title,dashStyle:tallMarkerDashStyle,lineWidth:0.5,color:event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming)?'purple':'orange',tall:false,lowPriority:false,};}
const recordTypes=TimelineModel.TimelineModel.RecordType;let tall=false;let color='grey';switch(event.name){case recordTypes.FrameStartedLoading:color='green';tall=true;break;case recordTypes.MarkDOMContent:color='blue';tall=true;break;case recordTypes.MarkLoad:color='red';tall=true;break;case recordTypes.MarkFirstPaint:color='hsl(180, 45%, 79%)';tall=true;break;case recordTypes.MarkFCP:color='hsl(160, 43%, 58%)';tall=true;break;case recordTypes.MarkFMPCandidate:color='hsl(146, 57%, 40%)';tall=true;break;case recordTypes.MarkFMP:color='hsl(144, 100%, 21%)';tall=true;break;case recordTypes.TimeStamp:color='orange';break;}
return{title:title,dashStyle:tallMarkerDashStyle,lineWidth:0.5,color:color,tall:tall,lowPriority:false,};}
static markerStyleForFrame(){return{title:Common.UIString('Frame'),color:'rgba(100, 100, 100, 0.4)',lineWidth:3,dashStyle:[3],tall:true,lowPriority:true};}
static colorForId(id){if(!Timeline.TimelineUIUtils.colorForId._colorGenerator){Timeline.TimelineUIUtils.colorForId._colorGenerator=new Common.Color.Generator({min:30,max:330},{min:50,max:80,count:3},85);Timeline.TimelineUIUtils.colorForId._colorGenerator.setColorForID('','#f2ecdc');}
return Timeline.TimelineUIUtils.colorForId._colorGenerator.colorForID(id);}
static eventWarning(event,warningType){const timelineData=TimelineModel.TimelineData.forEvent(event);const warning=warningType||timelineData.warning;if(!warning)
return null;const warnings=TimelineModel.TimelineModel.WarningType;const span=createElement('span');const eventData=event.args['data'];switch(warning){case warnings.ForcedStyle:case warnings.ForcedLayout:span.appendChild(UI.createDocumentationLink('../../fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts',Common.UIString('Forced reflow')));span.createTextChild(Common.UIString(' is a likely performance bottleneck.'));break;case warnings.IdleDeadlineExceeded:span.textContent=Common.UIString('Idle callback execution extended beyond deadline by '+
Number.millisToString(event.duration-eventData['allottedMilliseconds'],true));break;case warnings.LongHandler:span.textContent=Common.UIString('Handler took %s',Number.millisToString(event.duration,true));break;case warnings.LongRecurringHandler:span.textContent=Common.UIString('Recurring handler took %s',Number.millisToString(event.duration,true));break;case warnings.V8Deopt:span.appendChild(UI.XLink.create('https://github.com/GoogleChrome/devtools-docs/issues/53',Common.UIString('Not optimized')));span.createTextChild(Common.UIString(': %s',eventData['deoptReason']));break;default:console.assert(false,'Unhandled TimelineModel.WarningType');}
return span;}
static displayNameForFrame(frame,trimAt){const url=frame.url;if(!trimAt)
trimAt=30;return url.startsWith('about:')?`"${frame.name.trimMiddle(trimAt)}"`:frame.url.trimEnd(trimAt);}};Timeline.TimelineRecordStyle=class{constructor(title,category,hidden){this.title=title;this.category=category;this.hidden=!!hidden;}};Timeline.TimelineUIUtils.NetworkCategory={HTML:Symbol('HTML'),Script:Symbol('Script'),Style:Symbol('Style'),Media:Symbol('Media'),Other:Symbol('Other')};Timeline.TimelineUIUtils._aggregatedStatsKey=Symbol('aggregatedStats');Timeline.TimelineUIUtils.InvalidationsGroupElement=class extends UI.TreeElement{constructor(target,relatedNodesMap,contentHelper,invalidations){super('',true);this.listItemElement.classList.add('header');this.selectable=false;this.toggleOnClick=true;this._relatedNodesMap=relatedNodesMap;this._contentHelper=contentHelper;this._invalidations=invalidations;this.title=this._createTitle(target);}
_createTitle(target){const first=this._invalidations[0];const reason=first.cause.reason;const topFrame=first.cause.stackTrace&&first.cause.stackTrace[0];const title=createElement('span');if(reason)
title.createTextChild(Common.UIString('%s for ',reason));else
title.createTextChild(Common.UIString('Unknown cause for '));this._appendTruncatedNodeList(title,this._invalidations);if(topFrame&&this._contentHelper.linkifier()){title.createTextChild(Common.UIString('. '));const stack=title.createChild('span','monospace');stack.createChild('span').textContent=Timeline.TimelineUIUtils.frameDisplayName(topFrame);const link=this._contentHelper.linkifier().maybeLinkifyConsoleCallFrame(target,topFrame);if(link){stack.createChild('span').textContent=' @ ';stack.createChild('span').appendChild(link);}}
return title;}
onpopulate(){const content=createElementWithClass('div','content');const first=this._invalidations[0];if(first.cause.stackTrace){const stack=content.createChild('div');stack.createTextChild(Common.UIString('Stack trace:'));this._contentHelper.createChildStackTraceElement(stack,Timeline.TimelineUIUtils._stackTraceFromCallFrames(first.cause.stackTrace));}
content.createTextChild(this._invalidations.length>1?Common.UIString('Nodes:'):Common.UIString('Node:'));const nodeList=content.createChild('div','node-list');let firstNode=true;for(let i=0;i<this._invalidations.length;i++){const invalidation=this._invalidations[i];const invalidationNode=this._createInvalidationNode(invalidation,true);if(invalidationNode){if(!firstNode)
nodeList.createTextChild(Common.UIString(', '));firstNode=false;nodeList.appendChild(invalidationNode);const extraData=invalidation.extraData?', '+invalidation.extraData:'';if(invalidation.changedId){nodeList.createTextChild(Common.UIString('(changed id to "%s"%s)',invalidation.changedId,extraData));}else if(invalidation.changedClass){nodeList.createTextChild(Common.UIString('(changed class to "%s"%s)',invalidation.changedClass,extraData));}else if(invalidation.changedAttribute){nodeList.createTextChild(Common.UIString('(changed attribute to "%s"%s)',invalidation.changedAttribute,extraData));}else if(invalidation.changedPseudo){nodeList.createTextChild(Common.UIString('(changed pesudo to "%s"%s)',invalidation.changedPseudo,extraData));}else if(invalidation.selectorPart){nodeList.createTextChild(Common.UIString('(changed "%s"%s)',invalidation.selectorPart,extraData));}}}
const contentTreeElement=new UI.TreeElement(content,false);contentTreeElement.selectable=false;this.appendChild(contentTreeElement);}
_appendTruncatedNodeList(parentElement,invalidations){const invalidationNodes=[];const invalidationNodeIdMap={};for(let i=0;i<invalidations.length;i++){const invalidation=invalidations[i];const invalidationNode=this._createInvalidationNode(invalidation,false);invalidationNode.addEventListener('click',e=>e.consume(),false);if(invalidationNode&&!invalidationNodeIdMap[invalidation.nodeId]){invalidationNodes.push(invalidationNode);invalidationNodeIdMap[invalidation.nodeId]=true;}}
if(invalidationNodes.length===1){parentElement.appendChild(invalidationNodes[0]);}else if(invalidationNodes.length===2){parentElement.appendChild(invalidationNodes[0]);parentElement.createTextChild(Common.UIString(' and '));parentElement.appendChild(invalidationNodes[1]);}else if(invalidationNodes.length>=3){parentElement.appendChild(invalidationNodes[0]);parentElement.createTextChild(Common.UIString(', '));parentElement.appendChild(invalidationNodes[1]);parentElement.createTextChild(Common.UIString(', and %s others',invalidationNodes.length-2));}}
_createInvalidationNode(invalidation,showUnknownNodes){const node=(invalidation.nodeId&&this._relatedNodesMap)?this._relatedNodesMap.get(invalidation.nodeId):null;if(node){const nodeSpan=createElement('span');Common.Linkifier.linkify(node).then(link=>nodeSpan.appendChild(link));return nodeSpan;}
if(invalidation.nodeName){const nodeSpan=createElement('span');nodeSpan.textContent=Common.UIString('[ %s ]',invalidation.nodeName);return nodeSpan;}
if(showUnknownNodes){const nodeSpan=createElement('span');return nodeSpan.createTextChild(Common.UIString('[ unknown node ]'));}}};Timeline.TimelineUIUtils._previewElementSymbol=Symbol('previewElement');Timeline.TimelineUIUtils.EventDispatchTypeDescriptor=class{constructor(priority,color,eventTypes){this.priority=priority;this.color=color;this.eventTypes=eventTypes;}};Timeline.TimelineCategory=class extends Common.Object{constructor(name,title,visible,childColor,color){super();this.name=name;this.title=title;this.visible=visible;this.childColor=childColor;this.color=color;this.hidden=false;}
get hidden(){return this._hidden;}
set hidden(hidden){this._hidden=hidden;this.dispatchEventToListeners(Timeline.TimelineCategory.Events.VisibilityChanged,this);}};Timeline.TimelineCategory.Events={VisibilityChanged:Symbol('VisibilityChanged')};Timeline.TimelineMarkerStyle;Timeline.TimelinePopupContentHelper=class{constructor(title){this._contentTable=createElement('table');const titleCell=this._createCell(Common.UIString('%s - Details',title),'timeline-details-title');titleCell.colSpan=2;const titleRow=createElement('tr');titleRow.appendChild(titleCell);this._contentTable.appendChild(titleRow);}
contentTable(){return this._contentTable;}
_createCell(content,styleName){const text=createElement('label');text.createTextChild(String(content));const cell=createElement('td');cell.className='timeline-details';if(styleName)
cell.className+=' '+styleName;cell.textContent=content;return cell;}
appendTextRow(title,content){const row=createElement('tr');row.appendChild(this._createCell(title,'timeline-details-row-title'));row.appendChild(this._createCell(content,'timeline-details-row-data'));this._contentTable.appendChild(row);}
appendElementRow(title,content){const row=createElement('tr');const titleCell=this._createCell(title,'timeline-details-row-title');row.appendChild(titleCell);const cell=createElement('td');cell.className='details';if(content instanceof Node)
cell.appendChild(content);else
cell.createTextChild(content||'');row.appendChild(cell);this._contentTable.appendChild(row);}};Timeline.TimelineDetailsContentHelper=class{constructor(target,linkifier){this.fragment=createDocumentFragment();this._linkifier=linkifier;this._target=target;this.element=createElementWithClass('div','timeline-details-view-block');this._tableElement=this.element.createChild('div','vbox timeline-details-chip-body');this.fragment.appendChild(this.element);}
addSection(title,swatchColor){if(!this._tableElement.hasChildNodes()){this.element.removeChildren();}else{this.element=createElementWithClass('div','timeline-details-view-block');this.fragment.appendChild(this.element);}
if(title){const titleElement=this.element.createChild('div','timeline-details-chip-title');if(swatchColor)
titleElement.createChild('div').style.backgroundColor=swatchColor;titleElement.createTextChild(title);}
this._tableElement=this.element.createChild('div','vbox timeline-details-chip-body');this.fragment.appendChild(this.element);}
linkifier(){return this._linkifier;}
appendTextRow(title,value){const rowElement=this._tableElement.createChild('div','timeline-details-view-row');rowElement.createChild('div','timeline-details-view-row-title').textContent=title;rowElement.createChild('div','timeline-details-view-row-value').textContent=value;}
appendElementRow(title,content,isWarning,isStacked){const rowElement=this._tableElement.createChild('div','timeline-details-view-row');if(isWarning)
rowElement.classList.add('timeline-details-warning');if(isStacked)
rowElement.classList.add('timeline-details-stack-values');const titleElement=rowElement.createChild('div','timeline-details-view-row-title');titleElement.textContent=title;const valueElement=rowElement.createChild('div','timeline-details-view-row-value');if(content instanceof Node)
valueElement.appendChild(content);else
valueElement.createTextChild(content||'');}
appendLocationRow(title,url,startLine,startColumn){if(!this._linkifier||!this._target)
return;const link=this._linkifier.maybeLinkifyScriptLocation(this._target,null,url,startLine,startColumn);if(!link)
return;this.appendElementRow(title,link);}
appendLocationRange(title,url,startLine,endLine){if(!this._linkifier||!this._target)
return;const locationContent=createElement('span');const link=this._linkifier.maybeLinkifyScriptLocation(this._target,null,url,startLine);if(!link)
return;locationContent.appendChild(link);locationContent.createTextChild(String.sprintf(' [%s\u2026%s]',startLine+1,endLine+1||''));this.appendElementRow(title,locationContent);}
appendStackTrace(title,stackTrace){if(!this._linkifier||!this._target)
return;const rowElement=this._tableElement.createChild('div','timeline-details-view-row');rowElement.createChild('div','timeline-details-view-row-title').textContent=title;this.createChildStackTraceElement(rowElement,stackTrace);}
createChildStackTraceElement(parentElement,stackTrace){if(!this._linkifier||!this._target)
return;parentElement.classList.add('timeline-details-stack-values');const stackTraceElement=parentElement.createChild('div','timeline-details-view-row-value timeline-details-view-row-stack-trace');const callFrameElem=Components.JSPresentationUtils.buildStackTracePreviewContents(this._target,this._linkifier,stackTrace);stackTraceElement.appendChild(callFrameElem);}
appendWarningRow(event,warningType){const warning=Timeline.TimelineUIUtils.eventWarning(event,warningType);if(warning)
this.appendElementRow(Common.UIString('Warning'),warning,true);}};Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol=Symbol('categoryBreakdownCache');;Timeline.TimelineLayersView=class extends UI.SplitWidget{constructor(model,showPaintProfilerCallback){super(true,false,'timelineLayersView');this._model=model;this._showPaintProfilerCallback=showPaintProfilerCallback;this.element.classList.add('timeline-layers-view');this._rightSplitWidget=new UI.SplitWidget(true,true,'timelineLayersViewDetails');this._rightSplitWidget.element.classList.add('timeline-layers-view-properties');this.setMainWidget(this._rightSplitWidget);const vbox=new UI.VBox();this.setSidebarWidget(vbox);this._layerViewHost=new LayerViewer.LayerViewHost();const layerTreeOutline=new LayerViewer.LayerTreeOutline(this._layerViewHost);vbox.element.appendChild(layerTreeOutline.element);this._layers3DView=new LayerViewer.Layers3DView(this._layerViewHost);this._layers3DView.addEventListener(LayerViewer.Layers3DView.Events.PaintProfilerRequested,this._onPaintProfilerRequested,this);this._rightSplitWidget.setMainWidget(this._layers3DView);const layerDetailsView=new LayerViewer.LayerDetailsView(this._layerViewHost);this._rightSplitWidget.setSidebarWidget(layerDetailsView);layerDetailsView.addEventListener(LayerViewer.LayerDetailsView.Events.PaintProfilerRequested,this._onPaintProfilerRequested,this);}
showLayerTree(frameLayerTree){this._frameLayerTree=frameLayerTree;if(this.isShowing())
this._update();else
this._updateWhenVisible=true;}
wasShown(){if(this._updateWhenVisible){this._updateWhenVisible=false;this._update();}}
_onPaintProfilerRequested(event){const selection=(event.data);this._layers3DView.snapshotForSelection(selection).then(snapshotWithRect=>{if(snapshotWithRect)
this._showPaintProfilerCallback(snapshotWithRect.snapshot);});}
_update(){this._frameLayerTree.layerTreePromise().then(layerTree=>this._layerViewHost.setLayerTree(layerTree));}};;Timeline.TimelinePaintProfilerView=class extends UI.SplitWidget{constructor(frameModel){super(false,false);this.element.classList.add('timeline-paint-profiler-view');this.setSidebarSize(60);this.setResizable(false);this._frameModel=frameModel;this._logAndImageSplitWidget=new UI.SplitWidget(true,false);this._logAndImageSplitWidget.element.classList.add('timeline-paint-profiler-log-split');this.setMainWidget(this._logAndImageSplitWidget);this._imageView=new Timeline.TimelinePaintImageView();this._logAndImageSplitWidget.setMainWidget(this._imageView);this._paintProfilerView=new LayerViewer.PaintProfilerView(this._imageView.showImage.bind(this._imageView));this._paintProfilerView.addEventListener(LayerViewer.PaintProfilerView.Events.WindowChanged,this._onWindowChanged,this);this.setSidebarWidget(this._paintProfilerView);this._logTreeView=new LayerViewer.PaintProfilerCommandLogView();this._logAndImageSplitWidget.setSidebarWidget(this._logTreeView);this._needsUpdateWhenVisible=false;this._pendingSnapshot=null;this._event=null;this._paintProfilerModel=null;this._lastLoadedSnapshot=null;}
wasShown(){if(this._needsUpdateWhenVisible){this._needsUpdateWhenVisible=false;this._update();}}
setSnapshot(snapshot){this._releaseSnapshot();this._pendingSnapshot=snapshot;this._event=null;this._updateWhenVisible();}
setEvent(paintProfilerModel,event){this._releaseSnapshot();this._paintProfilerModel=paintProfilerModel;this._pendingSnapshot=null;this._event=event;this._updateWhenVisible();if(this._event.name===TimelineModel.TimelineModel.RecordType.Paint)
return!!TimelineModel.TimelineData.forEvent(event).picture;if(this._event.name===TimelineModel.TimelineModel.RecordType.RasterTask)
return this._frameModel.hasRasterTile(this._event);return false;}
_updateWhenVisible(){if(this.isShowing())
this._update();else
this._needsUpdateWhenVisible=true;}
_update(){this._logTreeView.setCommandLog([]);this._paintProfilerView.setSnapshotAndLog(null,[],null);let snapshotPromise;if(this._pendingSnapshot){snapshotPromise=Promise.resolve({rect:null,snapshot:this._pendingSnapshot});}else if(this._event.name===TimelineModel.TimelineModel.RecordType.Paint){const picture=TimelineModel.TimelineData.forEvent(this._event).picture;snapshotPromise=picture.objectPromise().then(data=>this._paintProfilerModel.loadSnapshot(data['skp64'])).then(snapshot=>snapshot&&{rect:null,snapshot:snapshot});}else if(this._event.name===TimelineModel.TimelineModel.RecordType.RasterTask){snapshotPromise=this._frameModel.rasterTilePromise(this._event);}else{console.assert(false,'Unexpected event type or no snapshot');return;}
snapshotPromise.then(snapshotWithRect=>{this._releaseSnapshot();if(!snapshotWithRect){this._imageView.showImage();return;}
const snapshot=snapshotWithRect.snapshot;this._lastLoadedSnapshot=snapshot;this._imageView.setMask(snapshotWithRect.rect);snapshot.commandLog().then(log=>onCommandLogDone.call(this,snapshot,snapshotWithRect.rect,log));});function onCommandLogDone(snapshot,clipRect,log){this._logTreeView.setCommandLog(log||[]);this._paintProfilerView.setSnapshotAndLog(snapshot,log||[],clipRect);}}
_releaseSnapshot(){if(!this._lastLoadedSnapshot)
return;this._lastLoadedSnapshot.release();this._lastLoadedSnapshot=null;}
_onWindowChanged(){this._logTreeView.updateWindow(this._paintProfilerView.selectionWindow());}};Timeline.TimelinePaintImageView=class extends UI.Widget{constructor(){super(true);this.registerRequiredCSS('timeline/timelinePaintProfiler.css');this.contentElement.classList.add('fill','paint-profiler-image-view');this._imageContainer=this.contentElement.createChild('div','paint-profiler-image-container');this._imageElement=this._imageContainer.createChild('img');this._maskElement=this._imageContainer.createChild('div');this._imageElement.addEventListener('load',this._updateImagePosition.bind(this),false);this._transformController=new LayerViewer.TransformController(this.contentElement,true);this._transformController.addEventListener(LayerViewer.TransformController.Events.TransformChanged,this._updateImagePosition,this);}
onResize(){if(this._imageElement.src)
this._updateImagePosition();}
_updateImagePosition(){const width=this._imageElement.naturalWidth;const height=this._imageElement.naturalHeight;const clientWidth=this.contentElement.clientWidth;const clientHeight=this.contentElement.clientHeight;const paddingFraction=0.1;const paddingX=clientWidth*paddingFraction;const paddingY=clientHeight*paddingFraction;const scaleX=(clientWidth-paddingX)/width;const scaleY=(clientHeight-paddingY)/height;const scale=Math.min(scaleX,scaleY);if(this._maskRectangle){const style=this._maskElement.style;style.width=width+'px';style.height=height+'px';style.borderLeftWidth=this._maskRectangle.x+'px';style.borderTopWidth=this._maskRectangle.y+'px';style.borderRightWidth=(width-this._maskRectangle.x-this._maskRectangle.width)+'px';style.borderBottomWidth=(height-this._maskRectangle.y-this._maskRectangle.height)+'px';}
this._transformController.setScaleConstraints(0.5,10/scale);let matrix=new WebKitCSSMatrix().scale(this._transformController.scale(),this._transformController.scale()).translate(clientWidth/2,clientHeight/2).scale(scale,scale).translate(-width/2,-height/2);const bounds=UI.Geometry.boundsForTransformedPoints(matrix,[0,0,0,width,height,0]);this._transformController.clampOffsets(paddingX-bounds.maxX,clientWidth-paddingX-bounds.minX,paddingY-bounds.maxY,clientHeight-paddingY-bounds.minY);matrix=new WebKitCSSMatrix().translate(this._transformController.offsetX(),this._transformController.offsetY()).multiply(matrix);this._imageContainer.style.webkitTransform=matrix.toString();}
showImage(imageURL){this._imageContainer.classList.toggle('hidden',!imageURL);if(imageURL)
this._imageElement.src=imageURL;}
setMask(maskRectangle){this._maskRectangle=maskRectangle;this._maskElement.classList.toggle('hidden',!maskRectangle);}};;Timeline.TimelinePanel=class extends UI.Panel{constructor(){super('timeline');this.registerRequiredCSS('timeline/timelinePanel.css');this.element.addEventListener('contextmenu',this._contextMenu.bind(this),false);this._dropTarget=new UI.DropTarget(this.element,[UI.DropTarget.Type.File,UI.DropTarget.Type.URI],Common.UIString('Drop timeline file or URL here'),this._handleDrop.bind(this));this._recordingOptionUIControls=[];this._state=Timeline.TimelinePanel.State.Idle;this._recordingPageReload=false;this._millisecondsToRecordAfterLoadEvent=3000;this._toggleRecordAction=(UI.actionRegistry.action('timeline.toggle-recording'));this._recordReloadAction=(UI.actionRegistry.action('timeline.record-reload'));this._historyManager=new Timeline.TimelineHistoryManager();this._performanceModel=null;this._viewModeSetting=Common.settings.createSetting('timelineViewMode',Timeline.TimelinePanel.ViewMode.FlameChart);this._disableCaptureJSProfileSetting=Common.settings.createSetting('timelineDisableJSSampling',false);this._disableCaptureJSProfileSetting.setTitle(Common.UIString('Disable JavaScript samples'));this._captureLayersAndPicturesSetting=Common.settings.createSetting('timelineCaptureLayersAndPictures',false);this._captureLayersAndPicturesSetting.setTitle(Common.UIString('Enable advanced paint instrumentation (slow)'));this._showScreenshotsSetting=Common.settings.createSetting('timelineShowScreenshots',true);this._showScreenshotsSetting.setTitle(Common.UIString('Screenshots'));this._showScreenshotsSetting.addChangeListener(this._updateOverviewControls,this);this._showMemorySetting=Common.settings.createSetting('timelineShowMemory',false);this._showMemorySetting.setTitle(Common.UIString('Memory'));this._showMemorySetting.addChangeListener(this._onModeChanged,this);this._panelToolbar=new UI.Toolbar('',this.element);this._createSettingsPane();this._updateShowSettingsToolbarButton();this._timelinePane=new UI.VBox();this._timelinePane.show(this.element);const topPaneElement=this._timelinePane.element.createChild('div','hbox');topPaneElement.id='timeline-overview-panel';this._overviewPane=new PerfUI.TimelineOverviewPane('timeline');this._overviewPane.addEventListener(PerfUI.TimelineOverviewPane.Events.WindowChanged,this._onOverviewWindowChanged.bind(this));this._overviewPane.show(topPaneElement);this._overviewControls=[];this._statusPaneContainer=this._timelinePane.element.createChild('div','status-pane-container fill');this._createFileSelector();SDK.targetManager.addModelListener(SDK.ResourceTreeModel,SDK.ResourceTreeModel.Events.Load,this._loadEventFired,this);this._flameChart=new Timeline.TimelineFlameChartView(this);this._searchableView=new UI.SearchableView(this._flameChart);this._searchableView.setMinimumSize(0,100);this._searchableView.element.classList.add('searchable-view');this._searchableView.show(this._timelinePane.element);this._flameChart.show(this._searchableView.element);this._flameChart.setSearchableView(this._searchableView);this._onModeChanged();this._populateToolbar();this._showLandingPage();this._updateTimelineControls();Extensions.extensionServer.addEventListener(Extensions.ExtensionServer.Events.TraceProviderAdded,this._appendExtensionsToToolbar,this);SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged,this._onSuspendStateChanged,this);}
static instance(){return(self.runtime.sharedInstance(Timeline.TimelinePanel));}
searchableView(){return this._searchableView;}
wasShown(){UI.context.setFlavor(Timeline.TimelinePanel,this);}
willHide(){UI.context.setFlavor(Timeline.TimelinePanel,null);this._historyManager.cancelIfShowing();}
loadFromEvents(events){if(this._state!==Timeline.TimelinePanel.State.Idle)
return;this._prepareToLoadTimeline();this._loader=Timeline.TimelineLoader.loadFromEvents(events,this);}
_onOverviewWindowChanged(event){const left=event.data.startTime;const right=event.data.endTime;this._performanceModel.setWindow({left,right},true);}
_onModelWindowChanged(event){const window=(event.data.window);this._overviewPane.setWindowTimes(window.left,window.right);}
_setState(state){this._state=state;this._updateTimelineControls();}
_createSettingCheckbox(setting,tooltip){const checkboxItem=new UI.ToolbarSettingCheckbox(setting,tooltip);this._recordingOptionUIControls.push(checkboxItem);return checkboxItem;}
_populateToolbar(){this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._toggleRecordAction));this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._recordReloadAction));this._clearButton=new UI.ToolbarButton(Common.UIString('Clear'),'largeicon-clear');this._clearButton.addEventListener(UI.ToolbarButton.Events.Click,()=>this._onClearButton());this._panelToolbar.appendToolbarItem(this._clearButton);this._loadButton=new UI.ToolbarButton(Common.UIString('Load profile...'),'largeicon-load');this._loadButton.addEventListener(UI.ToolbarButton.Events.Click,()=>this._selectFileToLoad());this._saveButton=new UI.ToolbarButton(Common.UIString('Save profile...'),'largeicon-download');this._saveButton.addEventListener(UI.ToolbarButton.Events.Click,()=>this._saveToFile());this._panelToolbar.appendSeparator();this._panelToolbar.appendToolbarItem(this._loadButton);this._panelToolbar.appendToolbarItem(this._saveButton);this._panelToolbar.appendSeparator();this._panelToolbar.appendToolbarItem(this._historyManager.button());this._panelToolbar.appendSeparator();this._panelToolbar.appendSeparator();this._showScreenshotsToolbarCheckbox=this._createSettingCheckbox(this._showScreenshotsSetting,Common.UIString('Capture screenshots'));this._panelToolbar.appendToolbarItem(this._showScreenshotsToolbarCheckbox);this._showMemoryToolbarCheckbox=this._createSettingCheckbox(this._showMemorySetting,Common.UIString('Show memory timeline'));this._panelToolbar.appendToolbarItem(this._showMemoryToolbarCheckbox);this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButtonForId('components.collect-garbage'));this._panelToolbar.appendSpacer();this._panelToolbar.appendText('');this._panelToolbar.appendSeparator();this._panelToolbar.appendToolbarItem(this._showSettingsPaneButton);}
_createSettingsPane(){this._showSettingsPaneSetting=Common.settings.createSetting('timelineShowSettingsToolbar',false);this._showSettingsPaneButton=new UI.ToolbarSettingToggle(this._showSettingsPaneSetting,'largeicon-settings-gear',Common.UIString('Capture settings'));SDK.multitargetNetworkManager.addEventListener(SDK.MultitargetNetworkManager.Events.ConditionsChanged,this._updateShowSettingsToolbarButton,this);MobileThrottling.throttlingManager().addEventListener(MobileThrottling.ThrottlingManager.Events.RateChanged,this._updateShowSettingsToolbarButton,this);this._disableCaptureJSProfileSetting.addChangeListener(this._updateShowSettingsToolbarButton,this);this._captureLayersAndPicturesSetting.addChangeListener(this._updateShowSettingsToolbarButton,this);this._settingsPane=new UI.HBox();this._settingsPane.element.classList.add('timeline-settings-pane');this._settingsPane.show(this.element);const captureToolbar=new UI.Toolbar('',this._settingsPane.element);captureToolbar.element.classList.add('flex-auto');captureToolbar.makeVertical();captureToolbar.appendToolbarItem(this._createSettingCheckbox(this._disableCaptureJSProfileSetting,Common.UIString('Disables JavaScript sampling, reduces overhead when running against mobile devices')));captureToolbar.appendToolbarItem(this._createSettingCheckbox(this._captureLayersAndPicturesSetting,Common.UIString('Captures advanced paint instrumentation, introduces significant performance overhead')));const throttlingPane=new UI.VBox();throttlingPane.element.classList.add('flex-auto');throttlingPane.show(this._settingsPane.element);const networkThrottlingToolbar=new UI.Toolbar('',throttlingPane.element);networkThrottlingToolbar.appendText(Common.UIString('Network:'));this._networkThrottlingSelect=this._createNetworkConditionsSelect();networkThrottlingToolbar.appendToolbarItem(this._networkThrottlingSelect);const cpuThrottlingToolbar=new UI.Toolbar('',throttlingPane.element);cpuThrottlingToolbar.appendText(Common.UIString('CPU:'));this._cpuThrottlingSelect=MobileThrottling.throttlingManager().createCPUThrottlingSelector();cpuThrottlingToolbar.appendToolbarItem(this._cpuThrottlingSelect);this._showSettingsPaneSetting.addChangeListener(this._updateSettingsPaneVisibility.bind(this));this._updateSettingsPaneVisibility();}
_appendExtensionsToToolbar(event){const provider=(event.data);const setting=Timeline.TimelinePanel._settingForTraceProvider(provider);const checkbox=this._createSettingCheckbox(setting,provider.longDisplayName());this._panelToolbar.appendToolbarItem(checkbox);}
static _settingForTraceProvider(traceProvider){let setting=traceProvider[Timeline.TimelinePanel._traceProviderSettingSymbol];if(!setting){const providerId=traceProvider.persistentIdentifier();setting=Common.settings.createSetting(providerId,false);setting.setTitle(traceProvider.shortDisplayName());traceProvider[Timeline.TimelinePanel._traceProviderSettingSymbol]=setting;}
return setting;}
_createNetworkConditionsSelect(){const toolbarItem=new UI.ToolbarComboBox(null);toolbarItem.setMaxWidth(140);MobileThrottling.throttlingManager().decorateSelectWithNetworkThrottling(toolbarItem.selectElement());return toolbarItem;}
_prepareToLoadTimeline(){console.assert(this._state===Timeline.TimelinePanel.State.Idle);this._setState(Timeline.TimelinePanel.State.Loading);if(this._performanceModel){this._performanceModel.dispose();this._performanceModel=null;}}
_createFileSelector(){if(this._fileSelectorElement)
this._fileSelectorElement.remove();this._fileSelectorElement=UI.createFileSelectorElement(this._loadFromFile.bind(this));this._timelinePane.element.appendChild(this._fileSelectorElement);}
_contextMenu(event){const contextMenu=new UI.ContextMenu(event);contextMenu.appendItemsAtLocation('timelineMenu');contextMenu.show();}
async _saveToFile(){if(this._state!==Timeline.TimelinePanel.State.Idle)
return;const performanceModel=this._performanceModel;if(!performanceModel)
return;const now=new Date();const fileName='Profile-'+now.toISO8601Compact()+'.json';const stream=new Bindings.FileOutputStream();const accepted=await stream.open(fileName);if(!accepted)
return;const error=await performanceModel.save(stream);if(!error)
return;Common.console.error(Common.UIString('Failed to save timeline: %s (%s, %s)',error.message,error.name,error.code));}
async _showHistory(){const model=await this._historyManager.showHistoryDropDown();if(model&&model!==this._performanceModel)
this._setModel(model);}
_navigateHistory(direction){const model=this._historyManager.navigate(direction);if(model&&model!==this._performanceModel)
this._setModel(model);return true;}
_selectFileToLoad(){this._fileSelectorElement.click();}
_loadFromFile(file){if(this._state!==Timeline.TimelinePanel.State.Idle)
return;this._prepareToLoadTimeline();this._loader=Timeline.TimelineLoader.loadFromFile(file,this);this._createFileSelector();}
_loadFromURL(url){if(this._state!==Timeline.TimelinePanel.State.Idle)
return;this._prepareToLoadTimeline();this._loader=Timeline.TimelineLoader.loadFromURL(url,this);}
_updateOverviewControls(){this._overviewControls=[];this._overviewControls.push(new Timeline.TimelineEventOverviewResponsiveness());if(Runtime.experiments.isEnabled('inputEventsOnTimelineOverview'))
this._overviewControls.push(new Timeline.TimelineEventOverviewInput());this._overviewControls.push(new Timeline.TimelineEventOverviewFrames());this._overviewControls.push(new Timeline.TimelineEventOverviewCPUActivity());this._overviewControls.push(new Timeline.TimelineEventOverviewNetwork());if(this._showScreenshotsSetting.get()&&this._performanceModel&&this._performanceModel.frameModel().frames().length)
this._overviewControls.push(new Timeline.TimelineFilmStripOverview());if(this._showMemorySetting.get())
this._overviewControls.push(new Timeline.TimelineEventOverviewMemory());for(const control of this._overviewControls)
control.setModel(this._performanceModel);this._overviewPane.setOverviewControls(this._overviewControls);}
_onModeChanged(){this._updateOverviewControls();this.doResize();this.select(null);}
_updateSettingsPaneVisibility(){if(this._showSettingsPaneSetting.get())
this._settingsPane.showWidget();else
this._settingsPane.hideWidget();}
_updateShowSettingsToolbarButton(){const messages=[];if(MobileThrottling.throttlingManager().cpuThrottlingRate()!==1)
messages.push(Common.UIString('- CPU throttling is enabled'));if(SDK.multitargetNetworkManager.isThrottling())
messages.push(Common.UIString('- Network throttling is enabled'));if(this._captureLayersAndPicturesSetting.get())
messages.push(Common.UIString('- Significant overhead due to paint instrumentation'));if(this._disableCaptureJSProfileSetting.get())
messages.push(Common.UIString('- JavaScript sampling is disabled'));this._showSettingsPaneButton.setDefaultWithRedColor(messages.length);this._showSettingsPaneButton.setToggleWithRedColor(messages.length);if(messages.length){const tooltipElement=createElement('div');messages.forEach(message=>{tooltipElement.createChild('div').textContent=message;});this._showSettingsPaneButton.setTitle(tooltipElement);}else{this._showSettingsPaneButton.setTitle(Common.UIString('Capture settings'));}}
_setUIControlsEnabled(enabled){this._recordingOptionUIControls.forEach(control=>control.setEnabled(enabled));}
async _startRecording(){console.assert(!this._statusPane,'Status pane is already opened.');this._setState(Timeline.TimelinePanel.State.StartPending);this._showRecordingStarted();const enabledTraceProviders=Extensions.extensionServer.traceProviders().filter(provider=>Timeline.TimelinePanel._settingForTraceProvider(provider).get());const recordingOptions={enableJSSampling:!this._disableCaptureJSProfileSetting.get(),capturePictures:this._captureLayersAndPicturesSetting.get(),captureFilmStrip:this._showScreenshotsSetting.get()};const mainTarget=(SDK.targetManager.mainTarget());this._controller=new Timeline.TimelineController(mainTarget,this);this._setUIControlsEnabled(false);this._hideLandingPage();await this._controller.startRecording(recordingOptions,enabledTraceProviders);this._recordingStarted();}
async _stopRecording(){if(this._statusPane){this._statusPane.finish();this._statusPane.updateStatus(Common.UIString('Stopping timeline\u2026'));this._statusPane.updateProgressBar(Common.UIString('Received'),0);}
this._setState(Timeline.TimelinePanel.State.StopPending);this._performanceModel=await this._controller.stopRecording();this._setUIControlsEnabled(true);this._controller=null;}
_onSuspendStateChanged(){this._updateTimelineControls();}
_updateTimelineControls(){const state=Timeline.TimelinePanel.State;this._toggleRecordAction.setToggled(this._state===state.Recording);this._toggleRecordAction.setEnabled(this._state===state.Recording||this._state===state.Idle);this._recordReloadAction.setEnabled(this._state===state.Idle);this._historyManager.setEnabled(this._state===state.Idle);this._clearButton.setEnabled(this._state===state.Idle);this._panelToolbar.setEnabled(this._state!==state.Loading);this._dropTarget.setEnabled(this._state===state.Idle);this._loadButton.setEnabled(this._state===state.Idle);this._saveButton.setEnabled(this._state===state.Idle&&!!this._performanceModel);}
_toggleRecording(){if(this._state===Timeline.TimelinePanel.State.Idle){this._recordingPageReload=false;this._startRecording();Host.userMetrics.actionTaken(Host.UserMetrics.Action.TimelineStarted);}else if(this._state===Timeline.TimelinePanel.State.Recording){this._stopRecording();}}
_recordReload(){if(this._state!==Timeline.TimelinePanel.State.Idle)
return;this._recordingPageReload=true;this._startRecording();Host.userMetrics.actionTaken(Host.UserMetrics.Action.TimelinePageReloadStarted);}
_onClearButton(){this._historyManager.clear();this._clear();}
_clear(){this._showLandingPage();this._reset();}
_reset(){PerfUI.LineLevelProfile.instance().reset();this._setModel(null);}
_applyFilters(model){if(model.timelineModel().isGenericTrace()||Runtime.experiments.isEnabled('timelineShowAllEvents'))
return;model.setFilters([Timeline.TimelineUIUtils.visibleEventsFilter(),new TimelineModel.ExcludeTopLevelFilter()]);}
_setModel(model){if(this._performanceModel){this._performanceModel.removeEventListener(Timeline.PerformanceModel.Events.WindowChanged,this._onModelWindowChanged,this);}
this._performanceModel=model;if(model)
this._applyFilters(model);this._flameChart.setModel(model);this._updateOverviewControls();this._overviewPane.reset();if(model){this._performanceModel.addEventListener(Timeline.PerformanceModel.Events.WindowChanged,this._onModelWindowChanged,this);this._overviewPane.setBounds(model.timelineModel().minimumRecordTime(),model.timelineModel().maximumRecordTime());for(const profile of model.timelineModel().cpuProfiles())
PerfUI.LineLevelProfile.instance().appendCPUProfile(profile);this._setMarkers(model.timelineModel());this._flameChart.setSelection(null);this._overviewPane.setWindowTimes(model.window().left,model.window().right);}
for(const control of this._overviewControls)
control.setModel(model);if(this._flameChart)
this._flameChart.resizeToPreferredHeights();this._updateTimelineControls();}
_recordingStarted(){if(this._recordingPageReload){const target=this._controller.mainTarget();const resourceModel=target.model(SDK.ResourceTreeModel);if(resourceModel)
resourceModel.reloadPage();}
this._reset();this._setState(Timeline.TimelinePanel.State.Recording);this._showRecordingStarted();this._statusPane.updateStatus(Common.UIString('Profiling\u2026'));this._statusPane.updateProgressBar(Common.UIString('Buffer usage'),0);this._statusPane.startTimer();this._hideLandingPage();}
recordingProgress(usage){this._statusPane.updateProgressBar(Common.UIString('Buffer usage'),usage*100);}
_showLandingPage(){if(this._landingPage){this._landingPage.show(this._statusPaneContainer);return;}
function encloseWithTag(tagName,contents){const e=createElement(tagName);e.textContent=contents;return e;}
const learnMoreNode=UI.XLink.create('https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/',Common.UIString('Learn\xa0more'));const recordKey=encloseWithTag('b',UI.shortcutRegistry.shortcutDescriptorsForAction('timeline.toggle-recording')[0].name);const reloadKey=encloseWithTag('b',UI.shortcutRegistry.shortcutDescriptorsForAction('timeline.record-reload')[0].name);const navigateNode=encloseWithTag('b',Common.UIString('WASD'));this._landingPage=new UI.VBox();this._landingPage.contentElement.classList.add('timeline-landing-page','fill');const centered=this._landingPage.contentElement.createChild('div');const recordButton=UI.createInlineButton(UI.Toolbar.createActionButton(this._toggleRecordAction));const reloadButton=UI.createInlineButton(UI.Toolbar.createActionButtonForId('timeline.record-reload'));centered.createChild('p').appendChild(UI.formatLocalized('Click the record button %s or hit %s to start a new recording.\n'+'Click the reload button %s or hit %s to record the page load.',[recordButton,recordKey,reloadButton,reloadKey]));centered.createChild('p').appendChild(UI.formatLocalized('After recording, select an area of interest in the overview by dragging.\n'+'Then, zoom and pan the timeline with the mousewheel or %s keys.\n%s',[navigateNode,learnMoreNode]));this._landingPage.show(this._statusPaneContainer);}
_hideLandingPage(){this._landingPage.detach();}
loadingStarted(){this._hideLandingPage();if(this._statusPane)
this._statusPane.hide();this._statusPane=new Timeline.TimelinePanel.StatusPane(false,this._cancelLoading.bind(this));this._statusPane.showPane(this._statusPaneContainer);this._statusPane.updateStatus(Common.UIString('Loading profile\u2026'));if(!this._loader)
this._statusPane.finish();this.loadingProgress(0);}
loadingProgress(progress){if(typeof progress==='number')
this._statusPane.updateProgressBar(Common.UIString('Received'),progress*100);}
processingStarted(){this._statusPane.updateStatus(Common.UIString('Processing profile\u2026'));}
loadingComplete(tracingModel){delete this._loader;this._setState(Timeline.TimelinePanel.State.Idle);if(this._statusPane)
this._statusPane.hide();delete this._statusPane;if(!tracingModel){this._clear();return;}
if(!this._performanceModel)
this._performanceModel=new Timeline.PerformanceModel();this._performanceModel.setTracingModel(tracingModel);this._setModel(this._performanceModel);this._historyManager.addRecording(this._performanceModel);}
_showRecordingStarted(){if(this._statusPane)
return;this._statusPane=new Timeline.TimelinePanel.StatusPane(true,this._stopRecording.bind(this));this._statusPane.showPane(this._statusPaneContainer);this._statusPane.updateStatus(Common.UIString('Initializing profiler\u2026'));}
_cancelLoading(){if(this._loader)
this._loader.cancel();}
_setMarkers(timelineModel){const markers=new Map();const recordTypes=TimelineModel.TimelineModel.RecordType;const zeroTime=timelineModel.minimumRecordTime();const filter=Timeline.TimelineUIUtils.paintEventsFilter();for(const event of timelineModel.timeMarkerEvents()){if(event.name===recordTypes.TimeStamp||event.name===recordTypes.ConsoleTime)
continue;if(!filter.accept(event))
continue;markers.set(event.startTime,Timeline.TimelineUIUtils.createEventDivider(event,zeroTime));}
this._overviewPane.setMarkers(markers);}
async _loadEventFired(event){if(this._state!==Timeline.TimelinePanel.State.Recording||!this._recordingPageReload||this._controller.mainTarget()!==event.data.resourceTreeModel.target())
return;const controller=this._controller;await new Promise(r=>setTimeout(r,this._millisecondsToRecordAfterLoadEvent));if(controller!==this._controller||this._state!==Timeline.TimelinePanel.State.Recording)
return;this._stopRecording();}
_frameForSelection(selection){switch(selection.type()){case Timeline.TimelineSelection.Type.Frame:return(selection.object());case Timeline.TimelineSelection.Type.Range:return null;case Timeline.TimelineSelection.Type.TraceEvent:return this._performanceModel.frameModel().frames(selection._endTime,selection._endTime)[0];default:console.assert(false,'Should never be reached');return null;}}
_jumpToFrame(offset){const currentFrame=this._selection&&this._frameForSelection(this._selection);if(!currentFrame)
return;const frames=this._performanceModel.frames();let index=frames.indexOf(currentFrame);console.assert(index>=0,'Can\'t find current frame in the frame list');index=Number.constrain(index+offset,0,frames.length-1);const frame=frames[index];this._revealTimeRange(frame.startTime,frame.endTime);this.select(Timeline.TimelineSelection.fromFrame(frame));return true;}
select(selection){this._selection=selection;this._flameChart.setSelection(selection);}
selectEntryAtTime(events,time){if(!events)
return;for(let index=events.upperBound(time,(time,event)=>time-event.startTime)-1;index>=0;--index){const event=events[index];const endTime=event.endTime||event.startTime;if(SDK.TracingModel.isTopLevelEvent(event)&&endTime<time)
break;if(this._performanceModel.isVisible(event)&&endTime>=time){this.select(Timeline.TimelineSelection.fromTraceEvent(event));return;}}
this.select(null);}
highlightEvent(event){this._flameChart.highlightEvent(event);}
_revealTimeRange(startTime,endTime){const window=this._performanceModel.window();let offset=0;if(window.right<endTime)
offset=endTime-window.right;else if(window.left>startTime)
offset=startTime-window.left;this._performanceModel.setWindow({left:window.left+offset,right:window.right+offset},true);}
_handleDrop(dataTransfer){const items=dataTransfer.items;if(!items.length)
return;const item=items[0];if(item.kind==='string'){const url=dataTransfer.getData('text/uri-list');if(new Common.ParsedURL(url).isValid)
this._loadFromURL(url);}else if(item.kind==='file'){const entry=items[0].webkitGetAsEntry();if(!entry.isFile)
return;entry.file(this._loadFromFile.bind(this));}}};Timeline.TimelinePanel.State={Idle:Symbol('Idle'),StartPending:Symbol('StartPending'),Recording:Symbol('Recording'),StopPending:Symbol('StopPending'),Loading:Symbol('Loading')};Timeline.TimelinePanel.ViewMode={FlameChart:'FlameChart',BottomUp:'BottomUp',CallTree:'CallTree',EventLog:'EventLog'};Timeline.TimelinePanel.rowHeight=18;Timeline.TimelinePanel.headerHeight=20;Timeline.TimelinePanel.ModelSelectionData;Timeline.TimelineSelection=class{constructor(type,startTime,endTime,object){this._type=type;this._startTime=startTime;this._endTime=endTime;this._object=object||null;}
static fromFrame(frame){return new Timeline.TimelineSelection(Timeline.TimelineSelection.Type.Frame,frame.startTime,frame.endTime,frame);}
static fromNetworkRequest(request){return new Timeline.TimelineSelection(Timeline.TimelineSelection.Type.NetworkRequest,request.startTime,request.endTime||request.startTime,request);}
static fromTraceEvent(event){return new Timeline.TimelineSelection(Timeline.TimelineSelection.Type.TraceEvent,event.startTime,event.endTime||(event.startTime+1),event);}
static fromRange(startTime,endTime){return new Timeline.TimelineSelection(Timeline.TimelineSelection.Type.Range,startTime,endTime);}
type(){return this._type;}
object(){return this._object;}
startTime(){return this._startTime;}
endTime(){return this._endTime;}};Timeline.TimelineSelection.Type={Frame:'Frame',NetworkRequest:'NetworkRequest',TraceEvent:'TraceEvent',Range:'Range'};Timeline.TimelineModeViewDelegate=function(){};Timeline.TimelineModeViewDelegate.prototype={select(selection){},selectEntryAtTime(events,time){},highlightEvent(event){},};Timeline.TimelinePanel.StatusPane=class extends UI.VBox{constructor(showTimer,stopCallback){super(true);this.registerRequiredCSS('timeline/timelineStatusDialog.css');this.contentElement.classList.add('timeline-status-dialog');const statusLine=this.contentElement.createChild('div','status-dialog-line status');statusLine.createChild('div','label').textContent=Common.UIString('Status');this._status=statusLine.createChild('div','content');if(showTimer){const timeLine=this.contentElement.createChild('div','status-dialog-line time');timeLine.createChild('div','label').textContent=Common.UIString('Time');this._time=timeLine.createChild('div','content');}
const progressLine=this.contentElement.createChild('div','status-dialog-line progress');this._progressLabel=progressLine.createChild('div','label');this._progressBar=progressLine.createChild('div','indicator-container').createChild('div','indicator');this._stopButton=UI.createTextButton(Common.UIString('Stop'),stopCallback,'',true);this.contentElement.createChild('div','stop-button').appendChild(this._stopButton);}
finish(){this._stopTimer();this._stopButton.disabled=true;}
hide(){this.element.parentNode.classList.remove('tinted');this.element.remove();}
showPane(parent){this.show(parent);parent.classList.add('tinted');this._stopButton.focus();}
updateStatus(text){this._status.textContent=text;}
updateProgressBar(activity,percent){this._progressLabel.textContent=activity;this._progressBar.style.width=percent.toFixed(1)+'%';this._updateTimer();}
startTimer(){this._startTime=Date.now();this._timeUpdateTimer=setInterval(this._updateTimer.bind(this,false),1000);this._updateTimer();}
_stopTimer(){if(!this._timeUpdateTimer)
return;clearInterval(this._timeUpdateTimer);this._updateTimer(true);delete this._timeUpdateTimer;}
_updateTimer(precise){if(!this._timeUpdateTimer)
return;const elapsed=(Date.now()-this._startTime)/1000;this._time.textContent=Common.UIString('%s\xa0sec',elapsed.toFixed(precise?1:0));}};Timeline.LoadTimelineHandler=class{handleQueryParam(value){UI.viewManager.showView('timeline').then(()=>{Timeline.TimelinePanel.instance()._loadFromURL(window.decodeURIComponent(value));});}};Timeline.TimelinePanel.ActionDelegate=class{handleAction(context,actionId){const panel=UI.context.flavor(Timeline.TimelinePanel);console.assert(panel&&panel instanceof Timeline.TimelinePanel);switch(actionId){case'timeline.toggle-recording':panel._toggleRecording();return true;case'timeline.record-reload':panel._recordReload();return true;case'timeline.save-to-file':panel._saveToFile();return true;case'timeline.load-from-file':panel._selectFileToLoad();return true;case'timeline.jump-to-previous-frame':panel._jumpToFrame(-1);return true;case'timeline.jump-to-next-frame':panel._jumpToFrame(1);return true;case'timeline.show-history':panel._showHistory();return true;case'timeline.previous-recording':panel._navigateHistory(1);return true;case'timeline.next-recording':panel._navigateHistory(-1);return true;}
return false;}};Timeline.TimelinePanel._traceProviderSettingSymbol=Symbol('traceProviderSetting');;Runtime.cachedResources["timeline/historyToolbarButton.css"]="/*\n * Copyright 2017 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n:host {\n width: 160px;\n height: 26px;\n text-align: left;\n display: flex;\n}\n\n:host([disabled]) {\n opacity: .5;\n}\n\n.content {\n padding-right: 5px;\n overflow: hidden;\n text-overflow: ellipsis;\n flex: 1 1;\n min-width: 35px;\n}\n\n/*# sourceURL=timeline/historyToolbarButton.css */";Runtime.cachedResources["timeline/invalidationsTree.css"]="/*\n * Copyright 2015 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.header, .children, .content {\n min-height: initial;\n line-height: initial;\n}\n\n/* This TreeElement is always expanded and has no arrow. */\n/* FIXME(crbug.com/475618): Implement this in TreeElement. */\n.children li::before {\n display: none;\n}\n\n.content {\n margin-bottom: 4px;\n}\n\n.content .stack-preview-container {\n margin-left: 8px;\n}\n\n.content .node-list {\n margin-left: 10px;\n}\n\n/*# sourceURL=timeline/invalidationsTree.css */";Runtime.cachedResources["timeline/timelineFlamechartPopover.css"]="/*\n * Copyright (c) 2015 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.timeline-flamechart-popover {\n overflow: hidden;\n}\n\n.timeline-flamechart-popover span {\n margin-right: 5px;\n}\n\n.timeline-flamechart-popover span.timeline-info-network-time {\n color: #009;\n}\n\n.timeline-flamechart-popover span.timeline-info-time {\n color: #282;\n}\n\n.timeline-flamechart-popover span.timeline-info-warning {\n color: #e44;\n}\n\n.timeline-flamechart-popover span.timeline-info-warning * {\n color: inherit;\n}\n\n/*# sourceURL=timeline/timelineFlamechartPopover.css */";Runtime.cachedResources["timeline/timelineHistoryManager.css"]="/*\n * Copyright 2017 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.drop-down {\n padding: 1px;\n box-shadow: var(--drop-shadow);\n background: white;\n}\n\n.preview-item {\n border-color: transparent;\n border-style: solid;\n border-width: 1px 5px;\n padding: 2px 0px;\n margin: 2px 1px;\n}\n\n.preview-item.selected {\n border-color: var(--selection-bg-color);\n}\n\n.preview-item canvas {\n width: 100%;\n height: 100%;\n}\n\n.text-details {\n font-size: 11px;\n padding: 3px;\n}\n\n.text-details span {\n flex: 1 0;\n padding-left: 8px;\n padding-right: 8px;\n}\n\n.text-details .name {\n font-weight: bold;\n}\n\n.text-details span.time {\n color: #555;\n text-align: right;\n}\n\n.screenshot-thumb {\n display: flex;\n border: 1px solid #ccc;\n margin: 2px 4px;\n}\n\n.screenshot-thumb img {\n margin: auto;\n max-width: 100%;\n max-height: 100%;\n}\n\n/*# sourceURL=timeline/timelineHistoryManager.css */";Runtime.cachedResources["timeline/timelinePanel.css"]="/*\n * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.\n * Copyright (C) 2009 Anthony Ricaud <rik@webkit.org>\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of Apple Computer, Inc. (\"Apple\") nor the names of\n * its contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n.panel.timeline > .toolbar {\n background-color: var(--toolbar-bg-color);\n border-bottom: var(--divider-border);\n}\n\n.timeline-settings-pane {\n flex: none;\n background-color: var(--toolbar-bg-color);\n border-bottom: var(--divider-border);\n}\n\n#timeline-overview-panel {\n flex: none;\n position: relative;\n border-bottom: 1px solid #bbb;\n}\n\n#timeline-overview-panel .timeline-graph-bar {\n pointer-events: none;\n}\n\n#timeline-overview-grid {\n background-color: rgb(255, 255, 255);\n}\n\n#timeline-overview-grid .timeline-grid-header {\n height: 12px;\n}\n\n#timeline-overview-grid .resources-dividers-label-bar {\n pointer-events: auto;\n height: 12px;\n}\n\n#timeline-overview-grid .resources-divider-label {\n top: 1px;\n}\n\n.timeline-details-split {\n flex: auto;\n}\n\n.timeline-view-stack {\n flex: auto;\n display: flex;\n}\n\n#timeline-container .devtools-link {\n color: inherit;\n}\n\n.timeline-graph-side.hovered {\n background-color: rgba(0, 0, 0, 0.05) !important;\n}\n\n.timeline.panel .status-pane-container {\n z-index: 1000;\n display: flex;\n align-items: center;\n pointer-events: none;\n}\n\n.timeline.panel .status-pane-container.tinted {\n background-color: hsla(0, 0%, 90%, 0.8);\n pointer-events: auto;\n}\n\n.timeline.panel .status-pane-container > div {\n pointer-events: auto;\n}\n\n#timeline-overview-panel .overview-strip {\n margin-top: 2px;\n justify-content: center;\n}\n\n#timeline-overview-panel .overview-strip .timeline-overview-strip-title {\n color: #666;\n font-size: 10px;\n font-weight: bold;\n z-index: 100;\n background-color: rgba(255, 255, 255, 0.7);\n padding: 0 4px;\n position: absolute;\n top: -2px;\n right: 0;\n}\n\n#timeline-overview-cpu-activity {\n flex-basis: 20px;\n}\n\n#timeline-overview-network {\n flex-basis: 8px;\n}\n\n#timeline-overview-framerate {\n flex-basis: 16px;\n margin-top: 0 !important;\n}\n\n#timeline-overview-filmstrip {\n flex-basis: 30px;\n}\n\n#timeline-overview-memory {\n flex-basis: 20px;\n}\n\n#timeline-overview-framerate::before,\n#timeline-overview-network::before,\n#timeline-overview-cpu-activity::before {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n border-bottom: 1px solid hsla(0, 0%, 0%, 0.06);\n z-index: -200;\n}\n\n.overview-strip .background {\n z-index: -10;\n}\n\n#timeline-overview-responsiveness {\n flex-basis: 5px;\n margin-top: 0 !important;\n}\n\n#timeline-overview-input {\n flex-basis: 6px;\n}\n\n#timeline-overview-pane {\n flex: auto;\n position: relative;\n overflow: hidden;\n}\n\n#timeline-overview-container {\n display: flex;\n flex-direction: column;\n flex: none;\n position: relative;\n overflow: hidden;\n}\n\n#timeline-overview-container canvas {\n width: 100%;\n height: 100%;\n}\n\n#timeline-graphs {\n position: absolute;\n left: 0;\n right: 0;\n max-height: 100%;\n top: 20px;\n}\n\n.timeline-aggregated-legend-title {\n display: inline-block;\n}\n\n.timeline-aggregated-legend-value {\n display: inline-block;\n width: 70px;\n text-align: right;\n}\n\n.timeline-aggregated-legend-swatch {\n display: inline-block;\n width: 11px;\n height: 11px;\n margin: 0 6px;\n position: relative;\n top: 1px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n}\n\n.popover ul {\n margin: 0;\n padding: 0;\n list-style-type: none;\n}\n\n#resources-container-content {\n overflow: hidden;\n min-height: 100%;\n}\n\n.memory-graph-label {\n position: absolute;\n right: 0;\n bottom: 0;\n font-size: 9px;\n color: #888;\n white-space: nowrap;\n padding: 0 4px;\n background-color: hsla(0, 0%, 100%, 0.8);\n}\n\n#memory-graphs-canvas-container {\n overflow: hidden;\n flex: auto;\n position: relative;\n}\n\n#memory-counters-graph {\n flex: auto;\n}\n\n#memory-graphs-canvas-container .memory-counter-marker {\n position: absolute;\n border-radius: 3px;\n width: 5px;\n height: 5px;\n margin-left: -3px;\n margin-top: -2px;\n}\n\n#memory-graphs-container .timeline-memory-header {\n flex: 0 0 26px;\n background-color: #eee;\n border-bottom: 1px solid #ddd;\n justify-content: space-between;\n}\n\n#memory-graphs-container .timeline-memory-header::after {\n content: \"\";\n background-image: url(Images/toolbarResizerVertical.png);\n background-repeat: no-repeat;\n background-position: right center, center;\n flex: 20px 0 0;\n margin: 0 4px;\n}\n\n.timeline-memory-toolbar {\n flex-shrink: 1;\n}\n\n.memory-counter-selector-info {\n flex: 0 0 auto;\n margin-left: 5px;\n white-space: nowrap;\n}\n\n.memory-counter-selector-info .range {\n margin: 0 4px;\n align-items: center;\n display: inline-flex;\n}\n\n.memory-counter-value {\n margin: 8px;\n}\n\n#counter-values-bar {\n flex: 0 0 20px;\n border-top: solid 1px lightgray;\n width: 100%;\n overflow: hidden;\n line-height: 18px;\n}\n\n.timeline-filters-header {\n overflow: hidden;\n flex: none;\n}\n\n.timeline-details {\n vertical-align: top;\n}\n\n.timeline-details-title {\n border-bottom: 1px solid #B8B8B8;\n font-weight: bold;\n padding-bottom: 5px;\n padding-top: 0;\n white-space: nowrap;\n}\n\n.timeline-details-row-title {\n font-weight: bold;\n text-align: right;\n white-space: nowrap;\n}\n\n.timeline-details-row-data {\n white-space: nowrap;\n}\n\n.timeline-details-view {\n color: #333;\n overflow: hidden;\n}\n\n.timeline-details-view-body {\n flex: auto;\n overflow: auto;\n position: relative;\n background-color: var(--toolbar-bg-color);\n -webkit-user-select: text;\n}\n\n.timeline-details-view-body > div {\n overflow: hidden;\n}\n\n.timeline-details-view-block {\n flex: none;\n display: flex;\n background-color: white;\n flex-direction: column;\n padding-bottom: 5px;\n border-bottom: var(--divider-border);\n}\n\n.timeline-details-view-row {\n padding-left: 10px;\n flex-direction: row;\n display: flex;\n line-height: 20px;\n}\n\n.timeline-details-view-block .timeline-details-stack-values {\n flex-direction: column !important;\n}\n\n.timeline-details-chip-title {\n font-size: 13px;\n padding: 8px;\n display: flex;\n align-items: center;\n}\n\n.timeline-details-chip-title > div {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n display: inline-block;\n margin-right: 4px;\n content: \" \";\n}\n\n.timeline-details-view-row-title:not(:empty) {\n color: rgb(152, 152, 152);\n overflow: hidden;\n padding-right: 10px;\n}\n\n.timeline-details-warning {\n background-color: rgba(250, 209, 209, 0.48);\n}\n\n.timeline-details-warning .timeline-details-view-row-title {\n color: red;\n}\n\n.timeline-details-warning .timeline-details-view-row-value {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.timeline-details-view-row-value {\n -webkit-user-select: text;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.timeline-details-view-row-value .stack-preview-container {\n line-height: 11px;\n}\n\n.timeline-details-view-row-value .timeline-details-warning-marker {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.timeline-details-view-pie-chart-wrapper {\n margin: 4px 0;\n}\n\n.timeline-details-view-pie-chart {\n margin-top: 5px;\n}\n\n.timeline-details-view-row-stack-trace {\n padding: 4px 0;\n line-height: inherit;\n}\n\n.timeline-details-view-row-stack-trace div {\n white-space: nowrap;\n text-overflow: ellipsis;\n line-height: 12px;\n}\n\n.timeline-aggregated-info-legend > div {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.timeline-flamechart {\n overflow: hidden;\n}\n\n.timeline-flamechart-resizer {\n flex: 8px 0 0;\n background-color: var(--toolbar-bg-color);\n border: 1px #a3a3a3;\n border-style: solid none;\n display: flex;\n flex-direction: row;\n align-items: flex-end;\n justify-content: center;\n}\n\n.timeline-network-resizer-disabled > .timeline-flamechart-resizer {\n display: none;\n}\n\n.timeline-flamechart-resizer:after {\n content: \"...\";\n font-size: 14px;\n margin-bottom: -1px;\n}\n\n.timeline-status-pane.full-widget-dimmed-banner {\n text-align: left !important;\n}\n\n.timeline-layers-view > div:last-child,\n.timeline-layers-view-properties > div:last-child {\n background-color: #eee;\n}\n\n.timeline-layers-view-properties table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.timeline-layers-view-properties td {\n border: 1px solid #e1e1e1;\n line-height: 22px;\n}\n\n.timeline-paint-profiler-log-split > div:last-child {\n background-color: #eee;\n z-index: 0;\n}\n\n.timeline-gap {\n flex: none;\n}\n\n.timeline-filmstrip-preview > img {\n margin-top: 5px;\n max-width: 500px;\n max-height: 300px;\n cursor: pointer;\n border: 1px solid #ddd;\n}\n\n.timeline-tree-view {\n display: flex;\n overflow: hidden;\n}\n\n.timeline-tree-view .toolbar {\n background-color: var(--toolbar-bg-color);\n border-bottom: var(--divider-border);\n}\n\n.timeline-tree-view .data-grid {\n border: none;\n flex: auto;\n}\n\n.timeline-tree-view .data-grid .data-container {\n overflow-y: scroll;\n}\n\n.timeline-tree-view .data-grid.data-grid-fits-viewport .corner {\n display: table-cell;\n}\n\n.timeline-tree-view .data-grid table.data {\n background: white;\n}\n\n.timeline-tree-view .data-grid tr:not(.selected) .highlight {\n background-color: rgb(255, 230, 179);\n}\n\n.timeline-tree-view .data-grid tr:hover td:not(.bottom-filler-td) {\n background-color: rgba(0, 0, 0, 0.1);\n}\n\n.timeline-tree-view .data-grid td.numeric-column {\n text-align: right;\n position: relative;\n}\n\n.timeline-tree-view .data-grid div.background-percent-bar {\n float: right;\n}\n\n.timeline-tree-view .data-grid span.percent-column {\n color: #888;\n width: 45px;\n display: inline-block;\n}\n\n.timeline-tree-view .data-grid tr.selected span {\n color: inherit;\n}\n\n.timeline-tree-view .data-grid .name-container {\n display: flex;\n align-items: center;\n padding-left: 2px;\n}\n\n.timeline-tree-view .data-grid .name-container div {\n flex: none;\n}\n\n.timeline-tree-view .data-grid .name-container .activity-icon {\n width: 12px;\n height: 12px;\n border: 1px solid rgba(0, 0, 0, 0.05);\n margin: 3px 0;\n}\n\n.timeline-tree-view .data-grid .name-container .activity-icon-container {\n margin-right: 3px;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n overflow: hidden;\n}\n\n.timeline-tree-view .data-grid .name-container .activity-warning::after {\n content: \"[deopt]\";\n margin: 0 4px;\n line-height: 12px;\n font-size: 10px;\n color: #777;\n}\n\n.timeline-tree-view .data-grid tr.selected .name-container .activity-warning::after {\n color: white;\n}\n\n.timeline-tree-view .data-grid .name-container .activity-link {\n flex: auto;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-left: 5px;\n}\n\n.timeline-tree-view .data-grid .background-bar-container {\n position: absolute;\n left: 3px;\n right: 0;\n}\n\n.timeline-tree-view .data-grid .background-bar {\n float: right;\n height: 18px;\n background-color: hsla(43, 84%, 64%, 0.2);\n border-bottom: 1px solid hsl(43, 84%, 64%);\n}\n\n.timeline-tree-view .data-grid .selected .background-bar {\n background-color: rgba(255, 255, 255, 0.3);\n border-bottom-color: rgba(255, 255, 255, 0.9);\n}\n\n.timeline-tree-view .timeline-details-view-body .full-widget-dimmed-banner {\n background-color: inherit;\n}\n\n.timeline-details .filter-input-field {\n width: 120px;\n}\n\n.timeline-tree-view .data-grid .header-container {\n height: 21px;\n}\n\n.timeline-tree-view .data-grid .data-container {\n top: 21px;\n}\n\n.timeline-stack-view-header {\n height: 27px;\n background-color: var(--toolbar-bg-color);\n padding: 6px 10px;\n color: #5a5a5a;\n white-space: nowrap;\n border-bottom: var(--divider-border);\n}\n\n.timeline-landing-page {\n position: absolute;\n background-color: white;\n justify-content: center;\n align-items: center;\n overflow: auto;\n font-size: 13px;\n color: #777;\n}\n\n.timeline-landing-page > div {\n max-width: 450px;\n margin: 10px;\n}\n\n.timeline-landing-page > div > p {\n flex: none;\n white-space: pre-line;\n}\n\n/*# sourceURL=timeline/timelinePanel.css */";Runtime.cachedResources["timeline/timelinePaintProfiler.css"]="/*\n * Copyright 2016 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.paint-profiler-image-view {\n overflow: hidden;\n}\n\n.paint-profiler-image-view .paint-profiler-image-container {\n -webkit-transform-origin: 0 0;\n}\n\n.paint-profiler-image-view .paint-profiler-image-container div {\n border-color: rgba(100, 100, 100, 0.4);\n border-style: solid;\n z-index: 100;\n position: absolute;\n top: 0;\n left: 0;\n}\n\n.paint-profiler-image-view img {\n border: solid 1px black;\n}\n\n/*# sourceURL=timeline/timelinePaintProfiler.css */";Runtime.cachedResources["timeline/timelineStatusDialog.css"]="/*\n * Copyright (c) 2015 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.timeline-status-dialog {\n display: flex;\n flex-direction: column;\n padding: 16px 16px 12px 16px;\n align-self: center;\n background-color: white;\n box-shadow: var(--drop-shadow);\n}\n\n.status-dialog-line {\n margin: 2px;\n height: 14px;\n display: flex;\n align-items: baseline;\n}\n\n.status-dialog-line .label {\n display: inline-block;\n width: 80px;\n text-align: right;\n color: #aaa;\n margin-right: 10px;\n}\n\n.timeline-status-dialog .progress .indicator-container {\n display: inline-block;\n width: 200px;\n height: 8px;\n background-color: #f4f4f4;\n display: inline-block;\n margin: 0 10px 0 0;\n}\n\n.timeline-status-dialog .progress .indicator {\n background-color: rgb(112, 166, 255);\n height: 100%;\n width: 0;\n margin: 0;\n}\n\n.timeline-status-dialog .stop-button {\n margin-top: 8px;\n height: 100%;\n align-self: center;\n}\n\n.timeline-status-dialog .stop-button button {\n min-width: 80px;\n}\n\n/*# sourceURL=timeline/timelineStatusDialog.css */";