📄 profileview.js
字号:
/* * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */WebInspector.ProfileView = function(profile){ WebInspector.View.call(this); this.element.addStyleClass("profile-view"); this.showSelfTimeAsPercent = true; this.showTotalTimeAsPercent = true; var columns = { "self": { title: WebInspector.UIString("Self"), width: "72px", sort: "descending", sortable: true }, "total": { title: WebInspector.UIString("Total"), width: "72px", sortable: true }, "calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true }, "function": { title: WebInspector.UIString("Function"), disclosure: true, sortable: true } }; this.dataGrid = new WebInspector.DataGrid(columns); this.dataGrid.addEventListener("sorting changed", this._sortData, this); this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true); this.element.appendChild(this.dataGrid.element); this.viewSelectElement = document.createElement("select"); this.viewSelectElement.className = "status-bar-item"; this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false); this.view = "Heavy"; var heavyViewOption = document.createElement("option"); heavyViewOption.label = WebInspector.UIString("Heavy (Bottom Up)"); var treeViewOption = document.createElement("option"); treeViewOption.label = WebInspector.UIString("Tree (Top Down)"); this.viewSelectElement.appendChild(heavyViewOption); this.viewSelectElement.appendChild(treeViewOption); this.percentButton = document.createElement("button"); this.percentButton.className = "percent-time-status-bar-item status-bar-item"; this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); this.focusButton = document.createElement("button"); this.focusButton.title = WebInspector.UIString("Focus selected function."); this.focusButton.className = "focus-profile-node-status-bar-item status-bar-item"; this.focusButton.disabled = true; this.focusButton.addEventListener("click", this._focusClicked.bind(this), false); this.excludeButton = document.createElement("button"); this.excludeButton.title = WebInspector.UIString("Exclude selected function."); this.excludeButton.className = "exclude-profile-node-status-bar-item status-bar-item"; this.excludeButton.disabled = true; this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false); this.resetButton = document.createElement("button"); this.resetButton.title = WebInspector.UIString("Restore all functions."); this.resetButton.className = "reset-profile-status-bar-item status-bar-item hidden"; this.resetButton.addEventListener("click", this._resetClicked.bind(this), false); // Default to the heavy profile. profile = profile.heavyProfile; // By default the profile isn't sorted, so sort based on our default sort // column and direction added to the DataGrid columns above. profile.sortSelfTimeDescending(); this._updatePercentButton(); this.profile = profile;}WebInspector.ProfileView.prototype = { get statusBarItems() { return [this.viewSelectElement, this.percentButton, this.focusButton, this.excludeButton, this.resetButton]; }, get profile() { return this._profile; }, set profile(profile) { this._profile = profile; this.refresh(); }, hide: function() { WebInspector.View.prototype.hide.call(this); this._currentSearchResultIndex = -1; }, refresh: function() { var selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null; this.dataGrid.removeChildren(); var children = this.profile.head.children; var childrenLength = children.length; for (var i = 0; i < childrenLength; ++i) if (children[i].visible) this.dataGrid.appendChild(new WebInspector.ProfileDataGridNode(this, children[i])); if (selectedProfileNode && selectedProfileNode._dataGridNode) selectedProfileNode._dataGridNode.selected = true; }, refreshShowAsPercents: function() { this._updatePercentButton(); var child = this.dataGrid.children[0]; while (child) { child.refresh(); child = child.traverseNextNode(false, null, true); } }, searchCanceled: function() { if (this._searchResults) { for (var i = 0; i < this._searchResults.length; ++i) { var profileNode = this._searchResults[i].profileNode; delete profileNode._searchMatchedSelfColumn; delete profileNode._searchMatchedTotalColumn; delete profileNode._searchMatchedCallsColumn; delete profileNode._searchMatchedFunctionColumn; if (profileNode._dataGridNode) profileNode._dataGridNode.refresh(); } } delete this._searchFinishedCallback; this._currentSearchResultIndex = -1; this._searchResults = []; }, performSearch: function(query, finishedCallback) { // Call searchCanceled since it will reset everything we need before doing a new search. this.searchCanceled(); query = query.trimWhitespace(); if (!query.length) return; this._searchFinishedCallback = finishedCallback; var greaterThan = (query.indexOf(">") === 0); var lessThan = (query.indexOf("<") === 0); var equalTo = (query.indexOf("=") === 0 || ((greaterThan || lessThan) && query.indexOf("=") === 1)); var percentUnits = (query.lastIndexOf("%") === (query.length - 1)); var millisecondsUnits = (query.length > 2 && query.lastIndexOf("ms") === (query.length - 2)); var secondsUnits = (!millisecondsUnits && query.lastIndexOf("s") === (query.length - 1)); var queryNumber = parseFloat(query); if (greaterThan || lessThan || equalTo) { if (equalTo && (greaterThan || lessThan)) queryNumber = parseFloat(query.substring(2)); else queryNumber = parseFloat(query.substring(1)); } var queryNumberMilliseconds = (secondsUnits ? (queryNumber * 1000) : queryNumber); // Make equalTo implicitly true if it wasn't specified there is no other operator. if (!isNaN(queryNumber) && !(greaterThan || lessThan)) equalTo = true; function matchesQuery(profileNode) { delete profileNode._searchMatchedSelfColumn; delete profileNode._searchMatchedTotalColumn; delete profileNode._searchMatchedCallsColumn; delete profileNode._searchMatchedFunctionColumn; if (percentUnits) { if (lessThan) { if (profileNode.selfPercent < queryNumber) profileNode._searchMatchedSelfColumn = true; if (profileNode.totalPercent < queryNumber) profileNode._searchMatchedTotalColumn = true; } else if (greaterThan) { if (profileNode.selfPercent > queryNumber) profileNode._searchMatchedSelfColumn = true; if (profileNode.totalPercent > queryNumber) profileNode._searchMatchedTotalColumn = true; } if (equalTo) { if (profileNode.selfPercent == queryNumber) profileNode._searchMatchedSelfColumn = true; if (profileNode.totalPercent == queryNumber) profileNode._searchMatchedTotalColumn = true; } } else if (millisecondsUnits || secondsUnits) { if (lessThan) { if (profileNode.selfTime < queryNumberMilliseconds) profileNode._searchMatchedSelfColumn = true; if (profileNode.totalTime < queryNumberMilliseconds) profileNode._searchMatchedTotalColumn = true; } else if (greaterThan) { if (profileNode.selfTime > queryNumberMilliseconds) profileNode._searchMatchedSelfColumn = true; if (profileNode.totalTime > queryNumberMilliseconds) profileNode._searchMatchedTotalColumn = true; } if (equalTo) { if (profileNode.selfTime == queryNumberMilliseconds) profileNode._searchMatchedSelfColumn = true; if (profileNode.totalTime == queryNumberMilliseconds) profileNode._searchMatchedTotalColumn = true; } } else { if (equalTo && profileNode.numberOfCalls == queryNumber) profileNode._searchMatchedCallsColumn = true; if (greaterThan && profileNode.numberOfCalls > queryNumber) profileNode._searchMatchedCallsColumn = true; if (lessThan && profileNode.numberOfCalls < queryNumber) profileNode._searchMatchedCallsColumn = true; } if (profileNode.functionName.hasSubstring(query, true) || profileNode.url.hasSubstring(query, true)) profileNode._searchMatchedFunctionColumn = true; var matched = (profileNode._searchMatchedSelfColumn || profileNode._searchMatchedTotalColumn || profileNode._searchMatchedCallsColumn || profileNode._searchMatchedFunctionColumn); if (matched && profileNode._dataGridNode) profileNode._dataGridNode.refresh(); return matched; } var current = this.profile.head; var ancestors = []; var nextIndexes = []; var startIndex = 0; while (current) { var children = current.children; var childrenLength = children.length; if (startIndex >= childrenLength) { current = ancestors.pop(); startIndex = nextIndexes.pop(); continue; } for (var i = startIndex; i < childrenLength; ++i) { var child = children[i]; if (matchesQuery(child)) { if (child._dataGridNode) { // The child has a data grid node already, no need to remember the ancestors. this._searchResults.push({ profileNode: child }); } else { var ancestorsCopy = [].concat(ancestors); ancestorsCopy.push(current); this._searchResults.push({ profileNode: child, ancestors: ancestorsCopy }); } } if (child.children.length) { ancestors.push(current); nextIndexes.push(i + 1); current = child; startIndex = 0; break; } if (i === (childrenLength - 1)) { current = ancestors.pop(); startIndex = nextIndexes.pop(); } } } finishedCallback(this, this._searchResults.length); }, jumpToFirstSearchResult: function() { if (!this._searchResults || !this._searchResults.length) return; this._currentSearchResultIndex = 0; this._jumpToSearchResult(this._currentSearchResultIndex); }, jumpToLastSearchResult: function() { if (!this._searchResults || !this._searchResults.length) return; this._currentSearchResultIndex = (this._searchResults.length - 1); this._jumpToSearchResult(this._currentSearchResultIndex); }, jumpToNextSearchResult: function() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -