import{BottomUpProfileDataGridTree}from'./BottomUpProfileDataGrid.js';import{CPUProfileFlameChart,ProfileFlameChartDataProvider}from'./CPUProfileFlameChart.js';import{Formatter,ProfileDataGridNode,ProfileDataGridTree}from'./ProfileDataGrid.js';import{DataDisplayDelegate,Events,ProfileHeader,ProfileType}from'./ProfileHeader.js';import{ProfileSidebarTreeElement}from'./ProfileSidebarTreeElement.js';import{TopDownProfileDataGridTree}from'./TopDownProfileDataGrid.js';export class ProfileView extends UI.SimpleView{constructor(){super(Common.UIString('Profile'));this._profile=null;this._searchableView=new UI.SearchableView(this);this._searchableView.setPlaceholder(Common.UIString('Find by cost (>50ms), name or file'));this._searchableView.show(this.element);const columns=([]);columns.push({id:'self',title:this.columnHeader('self'),width:'120px',fixedWidth:true,sortable:true,sort:DataGrid.DataGrid.Order.Descending});columns.push({id:'total',title:this.columnHeader('total'),width:'120px',fixedWidth:true,sortable:true});columns.push({id:'function',title:Common.UIString('Function'),disclosure:true,sortable:true});this.dataGrid=new DataGrid.DataGrid({displayName:ls`Profiler`,columns});this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged,this._sortProfile,this);this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode,this._nodeSelected.bind(this,true));this.dataGrid.addEventListener(DataGrid.DataGrid.Events.DeselectedNode,this._nodeSelected.bind(this,false));this.dataGrid.setRowContextMenuCallback(this._populateContextMenu.bind(this));this.viewSelectComboBox=new UI.ToolbarComboBox(this._changeView.bind(this),ls`Profile view mode`);this.focusButton=new UI.ToolbarButton(Common.UIString('Focus selected function'),'largeicon-visibility');this.focusButton.setEnabled(false);this.focusButton.addEventListener(UI.ToolbarButton.Events.Click,this._focusClicked,this);this.excludeButton=new UI.ToolbarButton(Common.UIString('Exclude selected function'),'largeicon-delete');this.excludeButton.setEnabled(false);this.excludeButton.addEventListener(UI.ToolbarButton.Events.Click,this._excludeClicked,this);this.resetButton=new UI.ToolbarButton(Common.UIString('Restore all functions'),'largeicon-refresh');this.resetButton.setEnabled(false);this.resetButton.addEventListener(UI.ToolbarButton.Events.Click,this._resetClicked,this);this._linkifier=new Components.Linkifier(maxLinkLength);}
static buildPopoverTable(entryInfo){const table=createElement('table');for(const entry of entryInfo){const row=table.createChild('tr');row.createChild('td').textContent=entry.title;row.createChild('td').textContent=entry.value;}
return table;}
setProfile(profile){this._profile=profile;this._bottomUpProfileDataGridTree=null;this._topDownProfileDataGridTree=null;this._changeView();this.refresh();}
profile(){return this._profile;}
initialize(nodeFormatter,viewTypes){this._nodeFormatter=nodeFormatter;this._viewType=self.Common.settings.createSetting('profileView',ViewTypes.Heavy);viewTypes=viewTypes||[ViewTypes.Flame,ViewTypes.Heavy,ViewTypes.Tree];const optionNames=new Map([[ViewTypes.Flame,ls`Chart`],[ViewTypes.Heavy,ls`Heavy (Bottom Up)`],[ViewTypes.Tree,ls`Tree (Top Down)`],[ViewTypes.Text,ls`Text (Top Down)`],]);const options=new Map(viewTypes.map(type=>[type,this.viewSelectComboBox.createOption(optionNames.get(type),type)]));const optionName=this._viewType.get()||viewTypes[0];const option=options.get(optionName)||options.get(viewTypes[0]);this.viewSelectComboBox.select(option);this._changeView();if(this._flameChart){this._flameChart.update();}}
focus(){if(this._flameChart){this._flameChart.focus();}else{super.focus();}}
columnHeader(columnId){throw'Not implemented';}
selectRange(timeLeft,timeRight){if(!this._flameChart){return;}
this._flameChart.selectRange(timeLeft,timeRight);}
async toolbarItems(){return[this.viewSelectComboBox,this.focusButton,this.excludeButton,this.resetButton];}
_getBottomUpProfileDataGridTree(){if(!this._bottomUpProfileDataGridTree){this._bottomUpProfileDataGridTree=new BottomUpProfileDataGridTree(this._nodeFormatter,this._searchableView,this._profile.root,this.adjustedTotal);}
return this._bottomUpProfileDataGridTree;}
_getTopDownProfileDataGridTree(){if(!this._topDownProfileDataGridTree){this._topDownProfileDataGridTree=new TopDownProfileDataGridTree(this._nodeFormatter,this._searchableView,this._profile.root,this.adjustedTotal);}
return this._topDownProfileDataGridTree;}
_populateContextMenu(contextMenu,gridNode){const node=(gridNode);if(node.linkElement&&!contextMenu.containsTarget(node.linkElement)){contextMenu.appendApplicableItems(node.linkElement);}}
willHide(){this._currentSearchResultIndex=-1;}
refresh(){if(!this.profileDataGridTree){return;}
const selectedProfileNode=this.dataGrid.selectedNode?this.dataGrid.selectedNode.profileNode:null;this.dataGrid.rootNode().removeChildren();const children=this.profileDataGridTree.children;const count=children.length;for(let index=0;index<count;++index){this.dataGrid.rootNode().appendChild(children[index]);}
if(selectedProfileNode){selectedProfileNode.selected=true;}}
refreshVisibleData(){let child=this.dataGrid.rootNode().children[0];while(child){child.refresh();child=child.traverseNextNode(false,null,true);}}
searchableView(){return this._searchableView;}
supportsCaseSensitiveSearch(){return true;}
supportsRegexSearch(){return false;}
searchCanceled(){this._searchableElement.searchCanceled();}
performSearch(searchConfig,shouldJump,jumpBackwards){this._searchableElement.performSearch(searchConfig,shouldJump,jumpBackwards);}
jumpToNextSearchResult(){this._searchableElement.jumpToNextSearchResult();}
jumpToPreviousSearchResult(){this._searchableElement.jumpToPreviousSearchResult();}
linkifier(){return this._linkifier;}
_ensureTextViewCreated(){if(this._textView){return;}
this._textView=new UI.SimpleView(ls`Call tree`);this._textView.registerRequiredCSS('profiler/profilesPanel.css');this.populateTextView(this._textView);}
populateTextView(view){}
createFlameChartDataProvider(){throw'Not implemented';}
_ensureFlameChartCreated(){if(this._flameChart){return;}
this._dataProvider=this.createFlameChartDataProvider();this._flameChart=new CPUProfileFlameChart(this._searchableView,this._dataProvider);this._flameChart.addEventListener(PerfUI.FlameChart.Events.EntryInvoked,this._onEntryInvoked.bind(this));}
_onEntryInvoked(event){const entryIndex=event.data;const node=this._dataProvider._entryNodes[entryIndex];const debuggerModel=this._profileHeader._debuggerModel;if(!node||!node.scriptId||!debuggerModel){return;}
const script=debuggerModel.scriptForId(node.scriptId);if(!script){return;}
const location=(debuggerModel.createRawLocation(script,node.lineNumber,node.columnNumber));Common.Revealer.reveal(self.Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location));}
_changeView(){if(!this._profile){return;}
this._searchableView.closeSearch();if(this._visibleView){this._visibleView.detach();}
this._viewType.set(this.viewSelectComboBox.selectedOption().value);switch(this._viewType.get()){case ViewTypes.Flame:this._ensureFlameChartCreated();this._visibleView=this._flameChart;this._searchableElement=this._flameChart;break;case ViewTypes.Tree:this.profileDataGridTree=this._getTopDownProfileDataGridTree();this._sortProfile();this._visibleView=this.dataGrid.asWidget();this._searchableElement=this.profileDataGridTree;break;case ViewTypes.Heavy:this.profileDataGridTree=this._getBottomUpProfileDataGridTree();this._sortProfile();this._visibleView=this.dataGrid.asWidget();this._searchableElement=this.profileDataGridTree;break;case ViewTypes.Text:this._ensureTextViewCreated();this._visibleView=this._textView;this._searchableElement=this._textView;break;}
const isFlame=this._viewType.get()===ViewTypes.Flame;this.focusButton.setVisible(!isFlame);this.excludeButton.setVisible(!isFlame);this.resetButton.setVisible(!isFlame);this._visibleView.show(this._searchableView.element);}
_nodeSelected(selected){this.focusButton.setEnabled(selected);this.excludeButton.setEnabled(selected);}
_focusClicked(event){if(!this.dataGrid.selectedNode){return;}
this.resetButton.setEnabled(true);this.profileDataGridTree.focus(this.dataGrid.selectedNode);this.refresh();this.refreshVisibleData();Host.userMetrics.actionTaken(Host.UserMetrics.Action.CpuProfileNodeFocused);}
_excludeClicked(event){const selectedNode=this.dataGrid.selectedNode;if(!selectedNode){return;}
selectedNode.deselect();this.resetButton.setEnabled(true);this.profileDataGridTree.exclude(selectedNode);this.refresh();this.refreshVisibleData();Host.userMetrics.actionTaken(Host.UserMetrics.Action.CpuProfileNodeExcluded);}
_resetClicked(event){this.resetButton.setEnabled(false);this.profileDataGridTree.restore();this._linkifier.reset();this.refresh();this.refreshVisibleData();}
_sortProfile(){const sortAscending=this.dataGrid.isSortOrderAscending();const sortColumnId=this.dataGrid.sortColumnId();const sortProperty=sortColumnId==='function'?'functionName':sortColumnId||'';this.profileDataGridTree.sort(ProfileDataGridTree.propertyComparator(sortProperty,sortAscending));this.refresh();}}
export const maxLinkLength=30;export const ViewTypes={Flame:'Flame',Tree:'Tree',Heavy:'Heavy',Text:'Text'};export class WritableProfileHeader extends ProfileHeader{constructor(debuggerModel,type,title){super(type,title||Common.UIString('Profile %d',type.nextProfileUid()));this._debuggerModel=debuggerModel;this._tempFile=null;}
_onChunkTransferred(reader){this.updateStatus(Common.UIString('Loading\u2026 %d%%',Number.bytesToString(this._jsonifiedProfile.length)));}
_onError(reader){this.updateStatus(Common.UIString(`File '%s' read error: %s`,reader.fileName(),reader.error().message));}
async write(text){this._jsonifiedProfile+=text;}
close(){}
dispose(){this.removeTempFile();}
createSidebarTreeElement(panel){return new ProfileSidebarTreeElement(panel,this,'profile-sidebar-tree-item');}
canSaveToFile(){return!this.fromFile()&&this._protocolProfile;}
async saveToFile(){const fileOutputStream=new Bindings.FileOutputStream();this._fileName=this._fileName||`${this.profileType().typeName()}-${new Date().toISO8601Compact()}${this.profileType().fileExtension()}`;const accepted=await fileOutputStream.open(this._fileName);if(!accepted||!this._tempFile){return;}
const data=await this._tempFile.read();if(data){await fileOutputStream.write(data);}
fileOutputStream.close();}
async loadFromFile(file){this.updateStatus(Common.UIString('Loading\u2026'),true);const fileReader=new Bindings.ChunkedFileReader(file,10000000,this._onChunkTransferred.bind(this));this._jsonifiedProfile='';const success=await fileReader.read(this);if(!success){this._onError(fileReader);return new Error(Common.UIString('Failed to read file'));}
this.updateStatus(Common.UIString('Parsing\u2026'),true);let error=null;try{this._profile=(JSON.parse(this._jsonifiedProfile));this.setProfile(this._profile);this.updateStatus(Common.UIString('Loaded'),false);}catch(e){error=e;this.profileType().removeProfile(this);}
this._jsonifiedProfile=null;if(this.profileType().profileBeingRecorded()===this){this.profileType().setProfileBeingRecorded(null);}
return error;}
setProtocolProfile(profile){this.setProfile(profile);this._protocolProfile=profile;this._tempFile=new Bindings.TempFile();this._tempFile.write([JSON.stringify(profile)]);if(this.canSaveToFile()){this.dispatchEventToListeners(Events.ProfileReceived);}}}