devil-windows
Version:
Debugger, profiler and runtime with embedded WebKit DevTools client (for Windows).
1,030 lines (1,021 loc) • 295 kB
JavaScript
WebInspector.ProfileType = function (id, name) {
WebInspector.Object.call(this);
this._id = id;
this._name = name;
this._profiles = [];
this._profileBeingRecorded = null;
console.trace("RESETTING SETTING PROFILE");
this._nextProfileUid = 1;
window.addEventListener("unload", this._clearTempStorage.bind(this), false);
}
WebInspector.ProfileType.Events = {AddProfileHeader: "add-profile-header", ProfileComplete: "profile-complete", RemoveProfileHeader: "remove-profile-header", ViewUpdated: "view-updated"}
WebInspector.ProfileType.prototype = {
nextProfileUid: function () {
return this._nextProfileUid;
}, hasTemporaryView: function () {
return false;
}, fileExtension: function () {
return null;
}, get statusBarItems() {
return [];
}, get buttonTooltip() {
return "";
}, get id() {
return this._id;
}, get treeItemTitle() {
return this._name;
}, get name() {
return this._name;
}, buttonClicked: function () {
return false;
}, get description() {
return "";
}, isInstantProfile: function () {
return false;
}, isEnabled: function () {
return true;
}, getProfiles: function () {
function isFinished(profile) {
return this._profileBeingRecorded !== profile;
}
return this._profiles.filter(isFinished.bind(this));
}, decorationElement: function () {
return null;
}, getProfile: function (uid) {
for (var i = 0; i < this._profiles.length; ++i) {
if (this._profiles[i].uid === uid)
return this._profiles[i];
}
return null;
}, loadFromFile: function (file) {
var name = file.name;
if (name.endsWith(this.fileExtension()))
name = name.substr(0, name.length - this.fileExtension().length);
var profile = this.createProfileLoadedFromFile(name);
profile.setFromFile();
this.setProfileBeingRecorded(profile);
this.addProfile(profile);
profile.loadFromFile(file);
}, createProfileLoadedFromFile: function (title) {
throw new Error("Needs implemented.");
}, addProfile: function (profile) {
this._profiles.push(profile);
this.dispatchEventToListeners(WebInspector.ProfileType.Events.AddProfileHeader, profile);
}, removeProfile: function (profile) {
var index = this._profiles.indexOf(profile);
if (index === -1)
return;
this._profiles.splice(index, 1);
this._disposeProfile(profile);
}, _clearTempStorage: function () {
for (var i = 0; i < this._profiles.length; ++i)
this._profiles[i].removeTempFile();
}, profileBeingRecorded: function () {
return this._profileBeingRecorded;
}, setProfileBeingRecorded: function (profile) {
console.trace("THIS SETTING PROFILE", profile);
if (this._profileBeingRecorded && this._profileBeingRecorded.target())
WebInspector.profilingLock().release();
if (profile && profile.target())
WebInspector.profilingLock().acquire();
console.trace("THIS SETTING PROFILE", profile);
this._profileBeingRecorded = profile;
}, profileBeingRecordedRemoved: function () {
}, _reset: function () {
var profiles = this._profiles.slice(0);
for (var i = 0; i < profiles.length; ++i)
this._disposeProfile(profiles[i]);
this._profiles = [];
this._nextProfileUid = 1;
}, _disposeProfile: function (profile) {
this.dispatchEventToListeners(WebInspector.ProfileType.Events.RemoveProfileHeader, profile);
profile.dispose();
if (this._profileBeingRecorded === profile) {
this.profileBeingRecordedRemoved();
this.setProfileBeingRecorded(null);
}
}, __proto__: WebInspector.Object.prototype
}
WebInspector.ProfileType.DataDisplayDelegate = function () {
}
WebInspector.ProfileType.DataDisplayDelegate.prototype = {
showProfile: function (profile) {
}, showObject: function (snapshotObjectId, perspectiveName) {
}
}
WebInspector.ProfileHeader = function (target, profileType, title) {
this._weakTarget = target ? target.weakReference() : new WeakReference(null);
this._profileType = profileType;
this.title = title;
this.uid = profileType._nextProfileUid++;
this._fromFile = false;
}
WebInspector.ProfileHeader.StatusUpdate = function (subtitle, wait) {
this.subtitle = subtitle;
this.wait = wait;
}
WebInspector.ProfileHeader.Events = {UpdateStatus: "UpdateStatus", ProfileReceived: "ProfileReceived"}
WebInspector.ProfileHeader.prototype = {
target: function () {
return this._weakTarget.get();
}, weakTarget: function () {
return this._weakTarget;
}, profileType: function () {
return this._profileType;
}, updateStatus: function (subtitle, wait) {
this.dispatchEventToListeners(WebInspector.ProfileHeader.Events.UpdateStatus, new WebInspector.ProfileHeader.StatusUpdate(subtitle, wait));
}, createSidebarTreeElement: function (dataDisplayDelegate) {
throw new Error("Needs implemented.");
}, createView: function (dataDisplayDelegate) {
throw new Error("Not implemented.");
}, removeTempFile: function () {
if (this._tempFile)
this._tempFile.remove();
}, dispose: function () {
}, load: function (callback) {
}, canSaveToFile: function () {
return false;
}, saveToFile: function () {
throw new Error("Needs implemented");
}, loadFromFile: function (file) {
throw new Error("Needs implemented");
}, fromFile: function () {
return this._fromFile;
}, setFromFile: function () {
this._fromFile = true;
}, __proto__: WebInspector.Object.prototype
}
WebInspector.ProfilesPanel = function () {
WebInspector.PanelWithSidebarTree.call(this, "profiles");
this.registerRequiredCSS("panelEnablerView.css");
this.registerRequiredCSS("heapProfiler.css");
this.registerRequiredCSS("profilesPanel.css");
this._searchableView = new WebInspector.SearchableView(this);
var mainView = new WebInspector.VBox();
this._searchableView.show(mainView.element);
mainView.show(this.mainElement());
this.profilesItemTreeElement = new WebInspector.ProfilesSidebarTreeElement(this);
this.sidebarTree.appendChild(this.profilesItemTreeElement);
this.profileViews = document.createElement("div");
this.profileViews.id = "profile-views";
this.profileViews.classList.add("vbox");
this._searchableView.element.appendChild(this.profileViews);
var statusBarContainer = document.createElementWithClass("div", "profiles-status-bar");
mainView.element.insertBefore(statusBarContainer, mainView.element.firstChild);
this._statusBarElement = statusBarContainer.createChild("div", "status-bar");
this.sidebarElement().classList.add("profiles-sidebar-tree-box");
var statusBarContainerLeft = document.createElementWithClass("div", "profiles-status-bar");
this.sidebarElement().insertBefore(statusBarContainerLeft, this.sidebarElement().firstChild);
this._statusBarButtons = statusBarContainerLeft.createChild("div", "status-bar");
this.recordButton = new WebInspector.StatusBarButton("", "record-profile-status-bar-item");
this.recordButton.addEventListener("click", this.toggleRecordButton, this);
this._statusBarButtons.appendChild(this.recordButton.element);
this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear all profiles."), "clear-status-bar-item");
this.clearResultsButton.addEventListener("click", this._reset, this);
this._statusBarButtons.appendChild(this.clearResultsButton.element);
this._profileTypeStatusBarItemsContainer = this._statusBarElement.createChild("div");
this._profileViewStatusBarItemsContainer = this._statusBarElement.createChild("div");
this._profileGroups = {};
this._launcherView = new WebInspector.MultiProfileLauncherView(this);
this._launcherView.addEventListener(WebInspector.MultiProfileLauncherView.EventTypes.ProfileTypeSelected, this._onProfileTypeSelected, this);
this._profileToView = [];
this._typeIdToSidebarSection = {};
var types = WebInspector.ProfileTypeRegistry.instance.profileTypes();
for (var i = 0; i < types.length; i++)
this._registerProfileType(types[i]);
this._launcherView.restoreSelectedProfileType();
this.profilesItemTreeElement.select();
this._showLauncherView();
this._createFileSelectorElement();
this.element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
this._registerShortcuts();
WebInspector.profilingLock().addEventListener(WebInspector.Lock.Events.StateChanged, this._onProfilingStateChanged, this);
}
WebInspector.ProfilesPanel.prototype = {
searchableView: function () {
return this._searchableView;
}, _createFileSelectorElement: function () {
if (this._fileSelectorElement)
this.element.removeChild(this._fileSelectorElement);
this._fileSelectorElement = WebInspector.createFileSelectorElement(this._loadFromFile.bind(this));
this.element.appendChild(this._fileSelectorElement);
}, _findProfileTypeByExtension: function (fileName) {
var types = WebInspector.ProfileTypeRegistry.instance.profileTypes();
for (var i = 0; i < types.length; i++) {
var type = types[i];
var extension = type.fileExtension();
if (!extension)
continue;
if (fileName.endsWith(type.fileExtension()))
return type;
}
return null;
}, _registerShortcuts: function () {
this.registerShortcuts(WebInspector.ShortcutsScreen.ProfilesPanelShortcuts.StartStopRecording, this.toggleRecordButton.bind(this));
}, _loadFromFile: function (file) {
this._createFileSelectorElement();
var profileType = this._findProfileTypeByExtension(file.name);
if (!profileType) {
var extensions = [];
var types = WebInspector.ProfileTypeRegistry.instance.profileTypes();
for (var i = 0; i < types.length; i++) {
var extension = types[i].fileExtension();
if (!extension || extensions.indexOf(extension) !== -1)
continue;
extensions.push(extension);
}
WebInspector.console.error(WebInspector.UIString("Can't load file. Only files with extensions '%s' can be loaded.", extensions.join("', '")));
return;
}
if (!!profileType.profileBeingRecorded()) {
WebInspector.console.error(WebInspector.UIString("Can't load profile while another profile is recording."));
return;
}
profileType.loadFromFile(file);
}, toggleRecordButton: function () {
if (!this.recordButton.enabled())
return true;
var type = this._selectedProfileType;
var isProfiling = type.buttonClicked();
this._updateRecordButton(isProfiling);
if (isProfiling) {
this._launcherView.profileStarted();
if (type.hasTemporaryView())
this.showProfile(type.profileBeingRecorded());
} else {
this._launcherView.profileFinished();
}
return true;
}, _onProfilingStateChanged: function () {
this._updateRecordButton(this.recordButton.toggled);
}, _updateRecordButton: function (toggled) {
if (WebInspector.experimentsSettings.disableAgentsWhenProfile.isEnabled())
WebInspector.inspectorView.setCurrentPanelLocked(toggled);
var isAcquiredInSomeTarget = WebInspector.profilingLock().isAcquired();
var enable = toggled || !isAcquiredInSomeTarget;
this.recordButton.setEnabled(enable);
this.recordButton.toggled = toggled;
if (enable)
this.recordButton.title = this._selectedProfileType ? this._selectedProfileType.buttonTooltip : ""; else
this.recordButton.title = WebInspector.anotherProfilerActiveLabel();
if (this._selectedProfileType)
this._launcherView.updateProfileType(this._selectedProfileType, enable);
}, _profileBeingRecordedRemoved: function () {
this._updateRecordButton(false);
this._launcherView.profileFinished();
}, _onProfileTypeSelected: function (event) {
this._selectedProfileType = (event.data);
this._updateProfileTypeSpecificUI();
}, _updateProfileTypeSpecificUI: function () {
this._updateRecordButton(this.recordButton.toggled);
this._profileTypeStatusBarItemsContainer.removeChildren();
var statusBarItems = this._selectedProfileType.statusBarItems;
if (statusBarItems) {
for (var i = 0; i < statusBarItems.length; ++i)
this._profileTypeStatusBarItemsContainer.appendChild(statusBarItems[i]);
}
}, _reset: function () {
WebInspector.Panel.prototype.reset.call(this);
var types = WebInspector.ProfileTypeRegistry.instance.profileTypes();
for (var i = 0; i < types.length; i++)
types[i]._reset();
delete this.visibleView;
delete this.currentQuery;
this.searchCanceled();
this._profileGroups = {};
this._updateRecordButton(false);
this._launcherView.profileFinished();
this.sidebarTree.element.classList.remove("some-expandable");
this._launcherView.detach();
this.profileViews.removeChildren();
this._profileViewStatusBarItemsContainer.removeChildren();
this.removeAllListeners();
this.recordButton.visible = true;
this._profileViewStatusBarItemsContainer.classList.remove("hidden");
this.clearResultsButton.element.classList.remove("hidden");
this.profilesItemTreeElement.select();
this._showLauncherView();
}, _showLauncherView: function () {
this.closeVisibleView();
this._profileViewStatusBarItemsContainer.removeChildren();
this._launcherView.show(this.profileViews);
this.visibleView = this._launcherView;
}, _registerProfileType: function (profileType) {
this._launcherView.addProfileType(profileType);
var profileTypeSection = new WebInspector.ProfileTypeSidebarSection(this, profileType);
this._typeIdToSidebarSection[profileType.id] = profileTypeSection
this.sidebarTree.appendChild(profileTypeSection);
profileTypeSection.childrenListElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
function onAddProfileHeader(event) {
this._addProfileHeader((event.data));
}
function onRemoveProfileHeader(event) {
this._removeProfileHeader((event.data));
}
function profileComplete(event) {
this.showProfile((event.data));
}
profileType.addEventListener(WebInspector.ProfileType.Events.ViewUpdated, this._updateProfileTypeSpecificUI, this);
profileType.addEventListener(WebInspector.ProfileType.Events.AddProfileHeader, onAddProfileHeader, this);
profileType.addEventListener(WebInspector.ProfileType.Events.RemoveProfileHeader, onRemoveProfileHeader, this);
profileType.addEventListener(WebInspector.ProfileType.Events.ProfileComplete, profileComplete, this);
var profiles = profileType.getProfiles();
for (var i = 0; i < profiles.length; i++)
this._addProfileHeader(profiles[i]);
}, _handleContextMenuEvent: function (event) {
var element = event.srcElement;
while (element && !element.treeElement && element !== this.element)
element = element.parentElement;
if (!element)
return;
if (element.treeElement && element.treeElement.handleContextMenuEvent) {
element.treeElement.handleContextMenuEvent(event, this);
return;
}
var contextMenu = new WebInspector.ContextMenu(event);
if (this.visibleView instanceof WebInspector.HeapSnapshotView) {
this.visibleView.populateContextMenu(contextMenu, event);
}
if (element !== this.element || event.srcElement === this.sidebarElement()) {
contextMenu.appendItem(WebInspector.UIString("Load\u2026"), this._fileSelectorElement.click.bind(this._fileSelectorElement));
}
contextMenu.show();
}, showLoadFromFileDialog: function () {
this._fileSelectorElement.click();
}, _addProfileHeader: function (profile) {
var profileType = profile.profileType();
var typeId = profileType.id;
this._typeIdToSidebarSection[typeId].addProfileHeader(profile);
if (!this.visibleView || this.visibleView === this._launcherView)
this.showProfile(profile);
}, _removeProfileHeader: function (profile) {
if (profile.profileType()._profileBeingRecorded === profile)
this._profileBeingRecordedRemoved();
var i = this._indexOfViewForProfile(profile);
if (i !== -1)
this._profileToView.splice(i, 1);
var profileType = profile.profileType();
var typeId = profileType.id;
var sectionIsEmpty = this._typeIdToSidebarSection[typeId].removeProfileHeader(profile);
if (sectionIsEmpty) {
this.profilesItemTreeElement.select();
this._showLauncherView();
}
}, showProfile: function (profile) {
if (!profile || (profile.profileType().profileBeingRecorded() === profile) && !profile.profileType().hasTemporaryView())
return null;
var view = this._viewForProfile(profile);
if (view === this.visibleView)
return view;
this.closeVisibleView();
view.show(this.profileViews);
this.visibleView = view;
var profileTypeSection = this._typeIdToSidebarSection[profile.profileType().id];
var sidebarElement = profileTypeSection.sidebarElementForProfile(profile);
sidebarElement.revealAndSelect();
this._profileViewStatusBarItemsContainer.removeChildren();
var statusBarItems = view.statusBarItems;
if (statusBarItems)
for (var i = 0; i < statusBarItems.length; ++i)
this._profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
return view;
}, showObject: function (snapshotObjectId, perspectiveName) {
var heapProfiles = WebInspector.ProfileTypeRegistry.instance.heapSnapshotProfileType.getProfiles();
for (var i = 0; i < heapProfiles.length; i++) {
var profile = heapProfiles[i];
if (profile.maxJSObjectId >= snapshotObjectId) {
this.showProfile(profile);
var view = this._viewForProfile(profile);
view.highlightLiveObject(perspectiveName, snapshotObjectId);
break;
}
}
}, _viewForProfile: function (profile) {
var index = this._indexOfViewForProfile(profile);
if (index !== -1)
return this._profileToView[index].view;
var view = profile.createView(this);
view.element.classList.add("profile-view");
this._profileToView.push({profile: profile, view: view});
return view;
}, _indexOfViewForProfile: function (profile) {
for (var i = 0; i < this._profileToView.length; i++) {
if (this._profileToView[i].profile === profile)
return i;
}
return -1;
}, closeVisibleView: function () {
if (this.visibleView)
this.visibleView.detach();
delete this.visibleView;
}, performSearch: function (query, shouldJump, jumpBackwards) {
this.searchCanceled();
var visibleView = this.visibleView;
if (!visibleView)
return;
function finishedCallback(view, searchMatches) {
if (!searchMatches)
return;
this._searchableView.updateSearchMatchesCount(searchMatches);
this._searchResultsView = view;
if (shouldJump) {
if (jumpBackwards)
view.jumpToLastSearchResult(); else
view.jumpToFirstSearchResult();
this._searchableView.updateCurrentMatchIndex(view.currentSearchResultIndex());
}
}
visibleView.currentQuery = query;
visibleView.performSearch(query, finishedCallback.bind(this));
}, jumpToNextSearchResult: function () {
if (!this._searchResultsView)
return;
if (this._searchResultsView !== this.visibleView)
return;
this._searchResultsView.jumpToNextSearchResult();
this._searchableView.updateCurrentMatchIndex(this._searchResultsView.currentSearchResultIndex());
}, jumpToPreviousSearchResult: function () {
if (!this._searchResultsView)
return;
if (this._searchResultsView !== this.visibleView)
return;
this._searchResultsView.jumpToPreviousSearchResult();
this._searchableView.updateCurrentMatchIndex(this._searchResultsView.currentSearchResultIndex());
}, searchCanceled: function () {
if (this._searchResultsView) {
if (this._searchResultsView.searchCanceled)
this._searchResultsView.searchCanceled();
this._searchResultsView.currentQuery = null;
this._searchResultsView = null;
}
this._searchableView.updateSearchMatchesCount(0);
}, appendApplicableItems: function (event, contextMenu, target) {
if (!(target instanceof WebInspector.RemoteObject))
return;
if (WebInspector.inspectorView.currentPanel() !== this)
return;
var object = (target);
var objectId = object.objectId;
if (!objectId)
return;
var heapProfiles = WebInspector.ProfileTypeRegistry.instance.heapSnapshotProfileType.getProfiles();
if (!heapProfiles.length)
return;
function revealInView(viewName) {
object.target().heapProfilerAgent().getHeapObjectId(objectId, didReceiveHeapObjectId.bind(this, viewName));
}
function didReceiveHeapObjectId(viewName, error, result) {
if (WebInspector.inspectorView.currentPanel() !== this)
return;
if (!error)
this.showObject(result, viewName);
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Reveal in Summary view" : "Reveal in Summary View"), revealInView.bind(this, "Summary"));
}, __proto__: WebInspector.PanelWithSidebarTree.prototype
}
WebInspector.ProfileTypeSidebarSection = function (dataDisplayDelegate, profileType) {
WebInspector.SidebarSectionTreeElement.call(this, profileType.treeItemTitle, null, true);
this._dataDisplayDelegate = dataDisplayDelegate;
this._profileTreeElements = [];
this._profileGroups = {};
this.hidden = true;
}
WebInspector.ProfileTypeSidebarSection.ProfileGroup = function () {
this.profileSidebarTreeElements = [];
this.sidebarTreeElement = null;
}
WebInspector.ProfileTypeSidebarSection.prototype = {
addProfileHeader: function (profile) {
this.hidden = false;
var profileType = profile.profileType();
var sidebarParent = this;
var profileTreeElement = profile.createSidebarTreeElement(this._dataDisplayDelegate);
this._profileTreeElements.push(profileTreeElement);
if (!profile.fromFile() && profileType.profileBeingRecorded() !== profile) {
var profileTitle = profile.title;
var group = this._profileGroups[profileTitle];
if (!group) {
group = new WebInspector.ProfileTypeSidebarSection.ProfileGroup();
this._profileGroups[profileTitle] = group;
}
group.profileSidebarTreeElements.push(profileTreeElement);
var groupSize = group.profileSidebarTreeElements.length;
if (groupSize === 2) {
group.sidebarTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(this._dataDisplayDelegate, profile.title);
var firstProfileTreeElement = group.profileSidebarTreeElements[0];
var index = this.children.indexOf(firstProfileTreeElement);
this.insertChild(group.sidebarTreeElement, index);
var selected = firstProfileTreeElement.selected;
this.removeChild(firstProfileTreeElement);
group.sidebarTreeElement.appendChild(firstProfileTreeElement);
if (selected)
firstProfileTreeElement.revealAndSelect();
firstProfileTreeElement.small = true;
firstProfileTreeElement.mainTitle = WebInspector.UIString("Run %d", 1);
this.treeOutline.element.classList.add("some-expandable");
}
if (groupSize >= 2) {
sidebarParent = group.sidebarTreeElement;
profileTreeElement.small = true;
profileTreeElement.mainTitle = WebInspector.UIString("Run %d", groupSize);
}
}
sidebarParent.appendChild(profileTreeElement);
}, removeProfileHeader: function (profile) {
var index = this._sidebarElementIndex(profile);
if (index === -1)
return false;
var profileTreeElement = this._profileTreeElements[index];
this._profileTreeElements.splice(index, 1);
var sidebarParent = this;
var group = this._profileGroups[profile.title];
if (group) {
var groupElements = group.profileSidebarTreeElements;
groupElements.splice(groupElements.indexOf(profileTreeElement), 1);
if (groupElements.length === 1) {
var pos = sidebarParent.children.indexOf(group.sidebarTreeElement);
this.insertChild(groupElements[0], pos);
groupElements[0].small = false;
groupElements[0].mainTitle = group.sidebarTreeElement.title;
this.removeChild(group.sidebarTreeElement);
}
if (groupElements.length !== 0)
sidebarParent = group.sidebarTreeElement;
}
sidebarParent.removeChild(profileTreeElement);
profileTreeElement.dispose();
if (this.children.length)
return false;
this.hidden = true;
return true;
}, sidebarElementForProfile: function (profile) {
var index = this._sidebarElementIndex(profile);
return index === -1 ? null : this._profileTreeElements[index];
}, _sidebarElementIndex: function (profile) {
var elements = this._profileTreeElements;
for (var i = 0; i < elements.length; i++) {
if (elements[i].profile === profile)
return i;
}
return -1;
}, __proto__: WebInspector.SidebarSectionTreeElement.prototype
}
WebInspector.ProfilesPanel.ContextMenuProvider = function () {
}
WebInspector.ProfilesPanel.ContextMenuProvider.prototype = {
appendApplicableItems: function (event, contextMenu, target) {
WebInspector.inspectorView.panel("profiles").appendApplicableItems(event, contextMenu, target);
}
}
WebInspector.ProfileSidebarTreeElement = function (dataDisplayDelegate, profile, className) {
this._dataDisplayDelegate = dataDisplayDelegate;
this.profile = profile;
WebInspector.SidebarTreeElement.call(this, className, profile.title, "", profile, false);
this.refreshTitles();
profile.addEventListener(WebInspector.ProfileHeader.Events.UpdateStatus, this._updateStatus, this);
if (profile.canSaveToFile())
this._createSaveLink(); else
profile.addEventListener(WebInspector.ProfileHeader.Events.ProfileReceived, this._onProfileReceived, this);
}
WebInspector.ProfileSidebarTreeElement.prototype = {
_createSaveLink: function () {
this._saveLinkElement = this.titleContainer.createChild("span", "save-link");
this._saveLinkElement.textContent = WebInspector.UIString("Save");
this._saveLinkElement.addEventListener("click", this._saveProfile.bind(this), false);
}, _onProfileReceived: function (event) {
this._createSaveLink();
}, _updateStatus: function (event) {
var statusUpdate = event.data;
if (statusUpdate.subtitle !== null)
this.subtitle = statusUpdate.subtitle;
if (typeof statusUpdate.wait === "boolean")
this.wait = statusUpdate.wait;
this.refreshTitles();
}, dispose: function () {
this.profile.removeEventListener(WebInspector.ProfileHeader.Events.UpdateStatus, this._updateStatus, this);
this.profile.removeEventListener(WebInspector.ProfileHeader.Events.ProfileReceived, this._onProfileReceived, this);
}, onselect: function () {
this._dataDisplayDelegate.showProfile(this.profile);
}, ondelete: function () {
this.profile.profileType().removeProfile(this.profile);
return true;
}, handleContextMenuEvent: function (event, panel) {
var profile = this.profile;
var contextMenu = new WebInspector.ContextMenu(event);
contextMenu.appendItem(WebInspector.UIString("Load\u2026"), panel._fileSelectorElement.click.bind(panel._fileSelectorElement));
if (profile.canSaveToFile())
contextMenu.appendItem(WebInspector.UIString("Save\u2026"), profile.saveToFile.bind(profile));
contextMenu.appendItem(WebInspector.UIString("Delete"), this.ondelete.bind(this));
contextMenu.show();
}, _saveProfile: function (event) {
this.profile.saveToFile();
}, __proto__: WebInspector.SidebarTreeElement.prototype
}
WebInspector.ProfileGroupSidebarTreeElement = function (dataDisplayDelegate, title, subtitle) {
WebInspector.SidebarTreeElement.call(this, "profile-group-sidebar-tree-item", title, subtitle, null, true);
this._dataDisplayDelegate = dataDisplayDelegate;
}
WebInspector.ProfileGroupSidebarTreeElement.prototype = {
onselect: function () {
if (this.children.length > 0)
this._dataDisplayDelegate.showProfile(this.children[this.children.length - 1].profile);
}, __proto__: WebInspector.SidebarTreeElement.prototype
}
WebInspector.ProfilesSidebarTreeElement = function (panel) {
this._panel = panel;
this.small = false;
WebInspector.SidebarTreeElement.call(this, "profile-launcher-view-tree-item", WebInspector.UIString("Profiles"), "", null, false);
}
WebInspector.ProfilesSidebarTreeElement.prototype = {
onselect: function () {
this._panel._showLauncherView();
}, get selectable() {
return true;
}, __proto__: WebInspector.SidebarTreeElement.prototype
};
WebInspector.ProfileDataGridNode = function (profileNode, owningTree, hasChildren) {
this.profileNode = profileNode;
WebInspector.DataGridNode.call(this, null, hasChildren);
this.tree = owningTree;
this.childrenByCallUID = {};
this.lastComparator = null;
this.callUID = profileNode.callUID;
this.selfTime = profileNode.selfTime;
this.totalTime = profileNode.totalTime;
this.functionName = WebInspector.CPUProfileDataModel.beautifyFunctionName(profileNode.functionName);
this._deoptReason = (!profileNode.deoptReason || profileNode.deoptReason === "no reason") ? "" : profileNode.deoptReason;
this.url = profileNode.url;
}
WebInspector.ProfileDataGridNode.prototype = {
createCell: function (columnIdentifier) {
var cell = this._createValueCell(columnIdentifier) || WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
if (columnIdentifier === "self" && this._searchMatchedSelfColumn)
cell.classList.add("highlight"); else if (columnIdentifier === "total" && this._searchMatchedTotalColumn)
cell.classList.add("highlight");
if (columnIdentifier !== "function")
return cell;
if (this._deoptReason)
cell.classList.add("not-optimized");
if (this._searchMatchedFunctionColumn)
cell.classList.add("highlight");
if (this.profileNode.scriptId !== "0") {
var lineNumber = this.profileNode.lineNumber ? this.profileNode.lineNumber - 1 : 0;
var columnNumber = this.profileNode.columnNumber ? this.profileNode.columnNumber - 1 : 0;
var target = this.tree.profileView.target();
var urlElement = this.tree.profileView._linkifier.linkifyScriptLocation(target, this.profileNode.scriptId, this.profileNode.url, lineNumber, columnNumber, "profile-node-file");
urlElement.style.maxWidth = "75%";
cell.insertBefore(urlElement, cell.firstChild);
}
return cell;
}, _createValueCell: function (columnIdentifier) {
if (columnIdentifier !== "self" && columnIdentifier !== "total")
return null;
var cell = document.createElement("td");
cell.className = "numeric-column";
var div = document.createElement("div");
var valueSpan = document.createElement("span");
valueSpan.textContent = this.data[columnIdentifier];
div.appendChild(valueSpan);
var percentColumn = columnIdentifier + "-percent";
if (percentColumn in this.data) {
var percentSpan = document.createElement("span");
percentSpan.className = "percent-column";
percentSpan.textContent = this.data[percentColumn];
div.appendChild(percentSpan);
div.classList.add("profile-multiple-values");
}
cell.appendChild(div);
return cell;
}, buildData: function () {
function formatMilliseconds(time) {
return WebInspector.UIString("%.1f\u2009ms", time);
}
function formatPercent(value) {
return WebInspector.UIString("%.2f\u2009%", value);
}
var functionName;
if (this._deoptReason) {
var content = document.createDocumentFragment();
var marker = content.createChild("span", "profile-warn-marker");
marker.title = WebInspector.UIString("Not optimized: %s", this._deoptReason);
content.createTextChild(this.functionName);
functionName = content;
} else {
functionName = this.functionName;
}
this.data = {"function": functionName, "self-percent": formatPercent(this.selfPercent), "self": formatMilliseconds(this.selfTime), "total-percent": formatPercent(this.totalPercent), "total": formatMilliseconds(this.totalTime),};
}, select: function (supressSelectedEvent) {
WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent);
this.tree.profileView._dataGridNodeSelected(this);
}, deselect: function (supressDeselectedEvent) {
WebInspector.DataGridNode.prototype.deselect.call(this, supressDeselectedEvent);
this.tree.profileView._dataGridNodeDeselected(this);
}, sort: function (comparator, force) {
var gridNodeGroups = [[this]];
for (var gridNodeGroupIndex = 0; gridNodeGroupIndex < gridNodeGroups.length; ++gridNodeGroupIndex) {
var gridNodes = gridNodeGroups[gridNodeGroupIndex];
var count = gridNodes.length;
for (var index = 0; index < count; ++index) {
var gridNode = gridNodes[index];
if (!force && (!gridNode.expanded || gridNode.lastComparator === comparator)) {
if (gridNode.children.length)
gridNode.shouldRefreshChildren = true;
continue;
}
gridNode.lastComparator = comparator;
var children = gridNode.children;
var childCount = children.length;
if (childCount) {
children.sort(comparator);
for (var childIndex = 0; childIndex < childCount; ++childIndex)
children[childIndex].recalculateSiblings(childIndex);
gridNodeGroups.push(children);
}
}
}
}, insertChild: function (profileDataGridNode, index) {
WebInspector.DataGridNode.prototype.insertChild.call(this, profileDataGridNode, index);
this.childrenByCallUID[profileDataGridNode.callUID] = profileDataGridNode;
}, removeChild: function (profileDataGridNode) {
WebInspector.DataGridNode.prototype.removeChild.call(this, profileDataGridNode);
delete this.childrenByCallUID[profileDataGridNode.callUID];
}, removeChildren: function () {
WebInspector.DataGridNode.prototype.removeChildren.call(this);
this.childrenByCallUID = {};
}, findChild: function (node) {
if (!node)
return null;
return this.childrenByCallUID[node.callUID];
}, get selfPercent() {
return this.selfTime / this.tree.totalTime * 100.0;
}, get totalPercent() {
return this.totalTime / this.tree.totalTime * 100.0;
}, populate: function () {
WebInspector.ProfileDataGridNode.populate(this);
}, populateChildren: function () {
}, save: function () {
if (this._savedChildren)
return;
this._savedSelfTime = this.selfTime;
this._savedTotalTime = this.totalTime;
this._savedChildren = this.children.slice();
}, restore: function () {
if (!this._savedChildren)
return;
this.selfTime = this._savedSelfTime;
this.totalTime = this._savedTotalTime;
this.removeChildren();
var children = this._savedChildren;
var count = children.length;
for (var index = 0; index < count; ++index) {
children[index].restore();
this.appendChild(children[index]);
}
}, merge: function (child, shouldAbsorb) {
WebInspector.ProfileDataGridNode.merge(this, child, shouldAbsorb);
}, __proto__: WebInspector.DataGridNode.prototype
}
WebInspector.ProfileDataGridNode.merge = function (container, child, shouldAbsorb) {
container.selfTime += child.selfTime;
if (!shouldAbsorb)
container.totalTime += child.totalTime;
var children = container.children.slice();
container.removeChildren();
var count = children.length;
for (var index = 0; index < count; ++index) {
if (!shouldAbsorb || children[index] !== child)
container.appendChild(children[index]);
}
children = child.children.slice();
count = children.length;
for (var index = 0; index < count; ++index) {
var orphanedChild = children[index];
var existingChild = container.childrenByCallUID[orphanedChild.callUID];
if (existingChild)
existingChild.merge(orphanedChild, false); else
container.appendChild(orphanedChild);
}
}
WebInspector.ProfileDataGridNode.populate = function (container) {
if (container._populated)
return;
container._populated = true;
container.populateChildren();
var currentComparator = container.tree.lastComparator;
if (currentComparator)
container.sort(currentComparator, true);
}
WebInspector.ProfileDataGridTree = function (profileView, rootProfileNode) {
this.tree = this;
this.children = [];
this.profileView = profileView;
this.totalTime = rootProfileNode.totalTime;
this.lastComparator = null;
this.childrenByCallUID = {};
}
WebInspector.ProfileDataGridTree.prototype = {
get expanded() {
return true;
}, appendChild: function (child) {
this.insertChild(child, this.children.length);
}, insertChild: function (child, index) {
this.children.splice(index, 0, child);
this.childrenByCallUID[child.callUID] = child;
}, removeChildren: function () {
this.children = [];
this.childrenByCallUID = {};
}, populateChildren: function () {
}, findChild: WebInspector.ProfileDataGridNode.prototype.findChild, sort: WebInspector.ProfileDataGridNode.prototype.sort, save: function () {
if (this._savedChildren)
return;
this._savedTotalTime = this.totalTime;
this._savedChildren = this.children.slice();
}, restore: function () {
if (!this._savedChildren)
return;
this.children = this._savedChildren;
this.totalTime = this._savedTotalTime;
var children = this.children;
var count = children.length;
for (var index = 0; index < count; ++index)
children[index].restore();
this._savedChildren = null;
}
}
WebInspector.ProfileDataGridTree.propertyComparators = [{}, {}];
WebInspector.ProfileDataGridTree.propertyComparator = function (property, isAscending) {
var comparator = WebInspector.ProfileDataGridTree.propertyComparators[(isAscending ? 1 : 0)][property];
if (!comparator) {
if (isAscending) {
comparator = function (lhs, rhs) {
if (lhs[property] < rhs[property])
return -1;
if (lhs[property] > rhs[property])
return 1;
return 0;
}
} else {
comparator = function (lhs, rhs) {
if (lhs[property] > rhs[property])
return -1;
if (lhs[property] < rhs[property])
return 1;
return 0;
}
}
WebInspector.ProfileDataGridTree.propertyComparators[(isAscending ? 1 : 0)][property] = comparator;
}
return comparator;
};
WebInspector.BottomUpProfileDataGridNode = function (profileNode, owningTree) {
WebInspector.ProfileDataGridNode.call(this, profileNode, owningTree, this._willHaveChildren(profileNode));
this._remainingNodeInfos = [];
}
WebInspector.BottomUpProfileDataGridNode.prototype = {
_takePropertiesFromProfileDataGridNode: function (profileDataGridNode) {
this.save();
this.selfTime = profileDataGridNode.selfTime;
this.totalTime = profileDataGridNode.totalTime;
}, _keepOnlyChild: function (child) {
this.save();
this.removeChildren();
this.appendChild(child);
}, _exclude: function (aCallUID) {
if (this._remainingNodeInfos)
this.populate();
this.save();
var children = this.children;
var index = this.children.length;
while (index--)
children[index]._exclude(aCallUID);
var child = this.childrenByCallUID[aCallUID];
if (child)
this.merge(child, true);
}, restore: function () {
WebInspector.ProfileDataGridNode.prototype.restore.call(this);
if (!this.children.length)
this.hasChildren = this._willHaveChildren(this.profileNode);
}, merge: function (child, shouldAbsorb) {
this.selfTime -= child.selfTime;
WebInspector.ProfileDataGridNode.prototype.merge.call(this, child, shouldAbsorb);
}, populateChildren: function () {
WebInspector.BottomUpProfileDataGridNode._sharedPopulate(this);
}, _willHaveChildren: function (profileNode) {
return !!(profileNode.parent && profileNode.parent.parent);
}, __proto__: WebInspector.ProfileDataGridNode.prototype
}
WebInspector.BottomUpProfileDataGridNode._sharedPopulate = function (container) {
var remainingNodeInfos = container._remainingNodeInfos;
var count = remainingNodeInfos.length;
for (var index = 0; index < count; ++index) {
var nodeInfo = remainingNodeInfos[index];
var ancestor = nodeInfo.ancestor;
var focusNode = nodeInfo.focusNode;
var child = container.findChild(ancestor);
if (child) {
var totalTimeAccountedFor = nodeInfo.totalTimeAccountedFor;
child.selfTime += focusNode.selfTime;
if (!totalTimeAccountedFor)
child.totalTime += focusNode.totalTime;
} else {
child = new WebInspector.BottomUpProfileDataGridNode(ancestor, container.tree);
if (ancestor !== focusNode) {
child.selfTime = focusNode.selfTime;
child.totalTime = focusNode.totalTime;
}
container.appendChild(child);
}
var parent = ancestor.parent;
if (parent && parent.parent) {
nodeInfo.ancestor = parent;
child._remainingNodeInfos.push(nodeInfo);
}
}
for (var i = 0; i < container.children.length; ++i)
container.children[i].buildData();
delete container._remainingNodeInfos;
}
WebInspector.BottomUpProfileDataGridTree = function (profileView, rootProfileNode) {
WebInspector.ProfileDataGridTree.call(this, profileView, rootProfileNode);
var profileNodeUIDs = 0;
var profileNodeGroups = [[], [rootProfileNode]];
var visitedProfileNodesForCallUID = {};
this._remainingNodeInfos = [];
for (var profileNodeGroupIndex = 0; profileNodeGroupIndex < profileNodeGroups.length; ++profileNodeGroupIndex) {
var parentProfileNodes = profileNodeGroups[profileNodeGroupIndex];
var profileNodes = profileNodeGroups[++profileNodeGroupIndex];
var count = profileNodes.length;
for (var index = 0; index < count; ++index) {
var profileNode = profileNodes[index];
if (!profileNode.UID)
profileNode.UID = ++profileNodeUIDs;
if (profileNode.parent) {
var visitedNodes = visitedProfileNodesForCallUID[profileNode.callUID];
var totalTimeAccountedFor = false;
if (!visitedNodes) {
visitedNodes = {}
visitedProfileNodesForCallUID[profileNode.callUID] = visitedNodes;
} else {
var parentCount = parentProfileNodes.length;
for (var parentIndex = 0; parentIndex < parentCount; ++parentIndex) {
if (visitedNodes[parentProfileNodes[parentIndex].UID]) {
totalTimeAccountedFor = true;
break;
}
}
}
visitedNodes[profileNode.UID] = true;
this._remainingNodeInfos.push({ancestor: profileNode, focusNode: profileNode, totalTimeAccountedFor: totalTimeAccountedFor});
}
var children = profileNode.children;
if (children.length) {
profileNodeGroups.push(parentProfileNodes.concat([profileNode]))
profileNodeGroups.push(children);
}
}
}
WebInspector.ProfileDataGridNode.populate(this);
return this;
}
WebInspector.BottomUpProfileDataGridTree.prototype = {
focus: function (profileDataGridNode) {
if (!profileDataGridNode)
return;
this.save();
var currentNode = profileDataGridNode;
var focusNode = profileDataGridNode;
while (currentNode.parent && (currentNode instanceof WebInspector.ProfileDataGridNode)) {
currentNode._takePropertiesFromProfileDataGridNode(profileDataGridNode);
focusNode = currentNode;
currentNode = currentNode.parent;
if (currentNode instanceof WebInspector.ProfileDataGridNode)
currentNode._keepOnlyChild(focusNode);
}
this.children = [focusNode];
this.totalTime = profileDataGridNode.totalTime;
}, exclude: function (profileDataGridNode) {
if (!profileDataGridNode)
return;
this.save();
var excludedCallUID = profileDataGridNode.callUID;
var excludedTopLevelChild = this.childrenByCallUID[excludedCallUID];
if (excludedTopLevelChild)
this.children.remove(excludedTopLevelChild);
var children = this.children;
var count = children.length;
for (var index = 0; index < count; ++index)
children[index]._exclude(excludedCallUID);
if (this.lastComparator)
this.sort(this.lastComparator, true);
}, buildData: function () {
}, populateChildren: function () {
WebInspector.BottomUpProfileDataGridNode._sharedPopulate(this);
}, __proto__: WebInspector.ProfileDataGridTree.prototype
};
WebInspector.TopDownProfileDataGridNode = function (profileNode, owningTree) {
var hasChildren = !!(profileNode.children && profileNode.children.length);
WebInspector.ProfileDataGridNode.call(this, profileNode, owningTree, hasChildren);
this._remainingChildren = profileNode.children;
this.buildData();
}
WebInsp