| Index: third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
|
| index 1079cc894a2ba5882037cebe788fd7648a90aca0..1c2bc1c1519a0760082451cd93dd0f1646cd314f 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
|
| @@ -27,28 +27,31 @@
|
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| */
|
| -
|
| /**
|
| - * @constructor
|
| * @implements {WebInspector.ProfileType.DataDisplayDelegate}
|
| * @implements {WebInspector.Searchable}
|
| - * @extends {WebInspector.SimpleView}
|
| - * @param {!WebInspector.ProfileType.DataDisplayDelegate} dataDisplayDelegate
|
| - * @param {!WebInspector.HeapProfileHeader} profile
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapSnapshotView = function(dataDisplayDelegate, profile)
|
| -{
|
| - WebInspector.SimpleView.call(this, WebInspector.UIString("Heap Snapshot"));
|
| +WebInspector.HeapSnapshotView = class extends WebInspector.SimpleView {
|
| + /**
|
| + * @param {!WebInspector.ProfileType.DataDisplayDelegate} dataDisplayDelegate
|
| + * @param {!WebInspector.HeapProfileHeader} profile
|
| + */
|
| + constructor(dataDisplayDelegate, profile) {
|
| + super(WebInspector.UIString('Heap Snapshot'));
|
|
|
| - this.element.classList.add("heap-snapshot-view");
|
| + this.element.classList.add('heap-snapshot-view');
|
|
|
| - profile.profileType().addEventListener(WebInspector.HeapSnapshotProfileType.SnapshotReceived, this._onReceiveSnapshot, this);
|
| - profile.profileType().addEventListener(WebInspector.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
|
| + profile.profileType().addEventListener(
|
| + WebInspector.HeapSnapshotProfileType.SnapshotReceived, this._onReceiveSnapshot, this);
|
| + profile.profileType().addEventListener(
|
| + WebInspector.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
|
|
|
| var isHeapTimeline = profile.profileType().id === WebInspector.TrackingHeapSnapshotProfileType.TypeId;
|
| if (isHeapTimeline) {
|
| - this._trackingOverviewGrid = new WebInspector.HeapTrackingOverviewGrid(profile);
|
| - this._trackingOverviewGrid.addEventListener(WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged, this._onIdsRangeChanged.bind(this));
|
| + this._trackingOverviewGrid = new WebInspector.HeapTrackingOverviewGrid(profile);
|
| + this._trackingOverviewGrid.addEventListener(
|
| + WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged, this._onIdsRangeChanged.bind(this));
|
| }
|
|
|
| this._parentDataDisplayDelegate = dataDisplayDelegate;
|
| @@ -56,7 +59,7 @@ WebInspector.HeapSnapshotView = function(dataDisplayDelegate, profile)
|
| this._searchableView = new WebInspector.SearchableView(this);
|
| this._searchableView.show(this.element);
|
|
|
| - this._splitWidget = new WebInspector.SplitWidget(false, true, "heapSnapshotSplitViewState", 200, 200);
|
| + this._splitWidget = new WebInspector.SplitWidget(false, true, 'heapSnapshotSplitViewState', 200, 200);
|
| this._splitWidget.show(this._searchableView.element);
|
|
|
| this._containmentDataGrid = new WebInspector.HeapSnapshotContainmentDataGrid(this);
|
| @@ -67,7 +70,8 @@ WebInspector.HeapSnapshotView = function(dataDisplayDelegate, profile)
|
| this._statisticsView = new WebInspector.HeapSnapshotStatisticsView();
|
|
|
| this._constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid(this);
|
| - this._constructorsDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);
|
| + this._constructorsDataGrid.addEventListener(
|
| + WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);
|
| this._constructorsWidget = this._constructorsDataGrid.asWidget();
|
| this._constructorsWidget.setMinimumSize(50, 25);
|
|
|
| @@ -76,61 +80,64 @@ WebInspector.HeapSnapshotView = function(dataDisplayDelegate, profile)
|
| this._diffWidget = this._diffDataGrid.asWidget();
|
| this._diffWidget.setMinimumSize(50, 25);
|
|
|
| - if (isHeapTimeline && WebInspector.moduleSetting("recordAllocationStacks").get()) {
|
| - this._allocationDataGrid = new WebInspector.AllocationDataGrid(profile.target() , this);
|
| - this._allocationDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._onSelectAllocationNode, this);
|
| - this._allocationWidget = this._allocationDataGrid.asWidget();
|
| - this._allocationWidget.setMinimumSize(50, 25);
|
| + if (isHeapTimeline && WebInspector.moduleSetting('recordAllocationStacks').get()) {
|
| + this._allocationDataGrid = new WebInspector.AllocationDataGrid(profile.target(), this);
|
| + this._allocationDataGrid.addEventListener(
|
| + WebInspector.DataGrid.Events.SelectedNode, this._onSelectAllocationNode, this);
|
| + this._allocationWidget = this._allocationDataGrid.asWidget();
|
| + this._allocationWidget.setMinimumSize(50, 25);
|
|
|
| - this._allocationStackView = new WebInspector.HeapAllocationStackView(profile.target());
|
| - this._allocationStackView.setMinimumSize(50, 25);
|
| + this._allocationStackView = new WebInspector.HeapAllocationStackView(profile.target());
|
| + this._allocationStackView.setMinimumSize(50, 25);
|
|
|
| - this._tabbedPane = new WebInspector.TabbedPane();
|
| + this._tabbedPane = new WebInspector.TabbedPane();
|
| }
|
|
|
| this._retainmentDataGrid = new WebInspector.HeapSnapshotRetainmentDataGrid(this);
|
| this._retainmentWidget = this._retainmentDataGrid.asWidget();
|
| this._retainmentWidget.setMinimumSize(50, 21);
|
| - this._retainmentWidget.element.classList.add("retaining-paths-view");
|
| + this._retainmentWidget.element.classList.add('retaining-paths-view');
|
|
|
| var splitWidgetResizer;
|
| if (this._allocationStackView) {
|
| - this._tabbedPane = new WebInspector.TabbedPane();
|
| + this._tabbedPane = new WebInspector.TabbedPane();
|
|
|
| - this._tabbedPane.appendTab("retainers", WebInspector.UIString("Retainers"), this._retainmentWidget);
|
| - this._tabbedPane.appendTab("allocation-stack", WebInspector.UIString("Allocation stack"), this._allocationStackView);
|
| + this._tabbedPane.appendTab('retainers', WebInspector.UIString('Retainers'), this._retainmentWidget);
|
| + this._tabbedPane.appendTab(
|
| + 'allocation-stack', WebInspector.UIString('Allocation stack'), this._allocationStackView);
|
|
|
| - splitWidgetResizer = this._tabbedPane.headerElement();
|
| - this._objectDetailsView = this._tabbedPane;
|
| + splitWidgetResizer = this._tabbedPane.headerElement();
|
| + this._objectDetailsView = this._tabbedPane;
|
| } else {
|
| - var retainmentViewHeader = createElementWithClass("div", "heap-snapshot-view-resizer");
|
| - var retainingPathsTitleDiv = retainmentViewHeader.createChild("div", "title");
|
| - var retainingPathsTitle = retainingPathsTitleDiv.createChild("span");
|
| - retainingPathsTitle.textContent = WebInspector.UIString("Retainers");
|
| -
|
| - splitWidgetResizer = retainmentViewHeader;
|
| - this._objectDetailsView = new WebInspector.VBox();
|
| - this._objectDetailsView.element.appendChild(retainmentViewHeader);
|
| - this._retainmentWidget.show(this._objectDetailsView.element);
|
| + var retainmentViewHeader = createElementWithClass('div', 'heap-snapshot-view-resizer');
|
| + var retainingPathsTitleDiv = retainmentViewHeader.createChild('div', 'title');
|
| + var retainingPathsTitle = retainingPathsTitleDiv.createChild('span');
|
| + retainingPathsTitle.textContent = WebInspector.UIString('Retainers');
|
| +
|
| + splitWidgetResizer = retainmentViewHeader;
|
| + this._objectDetailsView = new WebInspector.VBox();
|
| + this._objectDetailsView.element.appendChild(retainmentViewHeader);
|
| + this._retainmentWidget.show(this._objectDetailsView.element);
|
| }
|
| this._splitWidget.hideDefaultResizer();
|
| this._splitWidget.installResizer(splitWidgetResizer);
|
|
|
| - this._retainmentDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._inspectedObjectChanged, this);
|
| + this._retainmentDataGrid.addEventListener(
|
| + WebInspector.DataGrid.Events.SelectedNode, this._inspectedObjectChanged, this);
|
| this._retainmentDataGrid.reset();
|
|
|
| this._perspectives = [];
|
| this._perspectives.push(new WebInspector.HeapSnapshotView.SummaryPerspective());
|
| if (profile.profileType() !== WebInspector.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType)
|
| - this._perspectives.push(new WebInspector.HeapSnapshotView.ComparisonPerspective());
|
| + this._perspectives.push(new WebInspector.HeapSnapshotView.ComparisonPerspective());
|
| this._perspectives.push(new WebInspector.HeapSnapshotView.ContainmentPerspective());
|
| if (this._allocationWidget)
|
| - this._perspectives.push(new WebInspector.HeapSnapshotView.AllocationPerspective());
|
| + this._perspectives.push(new WebInspector.HeapSnapshotView.AllocationPerspective());
|
| this._perspectives.push(new WebInspector.HeapSnapshotView.StatisticsPerspective());
|
|
|
| this._perspectiveSelect = new WebInspector.ToolbarComboBox(this._onSelectedPerspectiveChanged.bind(this));
|
| for (var i = 0; i < this._perspectives.length; ++i)
|
| - this._perspectiveSelect.createOption(this._perspectives[i].title());
|
| + this._perspectiveSelect.createOption(this._perspectives[i].title());
|
|
|
| this._profile = profile;
|
|
|
| @@ -142,14 +149,15 @@ WebInspector.HeapSnapshotView = function(dataDisplayDelegate, profile)
|
| this._filterSelect.setVisible(false);
|
| this._updateFilterOptions();
|
|
|
| - this._classNameFilter = new WebInspector.ToolbarInput("Class filter");
|
| + this._classNameFilter = new WebInspector.ToolbarInput('Class filter');
|
| this._classNameFilter.setVisible(false);
|
| this._constructorsDataGrid.setNameFilter(this._classNameFilter);
|
| this._diffDataGrid.setNameFilter(this._classNameFilter);
|
|
|
| this._selectedSizeText = new WebInspector.ToolbarText();
|
|
|
| - this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.element, this._getHoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), undefined, true);
|
| + this._popoverHelper = new WebInspector.ObjectPopoverHelper(
|
| + this.element, this._getHoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), undefined, true);
|
|
|
| this._currentPerspectiveIndex = 0;
|
| this._currentPerspective = this._perspectives[0];
|
| @@ -158,1039 +166,1127 @@ WebInspector.HeapSnapshotView = function(dataDisplayDelegate, profile)
|
|
|
| this._populate();
|
| this._searchThrottler = new WebInspector.Throttler(0);
|
| -};
|
| -
|
| -/**
|
| - * @constructor
|
| - * @param {string} title
|
| - */
|
| -WebInspector.HeapSnapshotView.Perspective = function(title)
|
| -{
|
| - this._title = title;
|
| -};
|
| + }
|
| +
|
| + /**
|
| + * @return {!WebInspector.SearchableView}
|
| + */
|
| + searchableView() {
|
| + return this._searchableView;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {?WebInspector.ProfileHeader} profile
|
| + * @return {?WebInspector.Widget}
|
| + */
|
| + showProfile(profile) {
|
| + return this._parentDataDisplayDelegate.showProfile(profile);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!HeapProfilerAgent.HeapSnapshotObjectId} snapshotObjectId
|
| + * @param {string} perspectiveName
|
| + */
|
| + showObject(snapshotObjectId, perspectiveName) {
|
| + if (snapshotObjectId <= this._profile.maxJSObjectId)
|
| + this.selectLiveObject(perspectiveName, snapshotObjectId);
|
| + else
|
| + this._parentDataDisplayDelegate.showObject(snapshotObjectId, perspectiveName);
|
| + }
|
| +
|
| + _populate() {
|
| + this._profile._loadPromise
|
| + .then(heapSnapshotProxy => {
|
| + heapSnapshotProxy.getStatistics().then(this._gotStatistics.bind(this));
|
| + this._dataGrid.setDataSource(heapSnapshotProxy);
|
| + if (this._profile.profileType().id === WebInspector.TrackingHeapSnapshotProfileType.TypeId &&
|
| + this._profile.fromFile())
|
| + return heapSnapshotProxy.getSamples().then(samples => this._trackingOverviewGrid._setSamples(samples));
|
| + })
|
| + .then(_ => {
|
| + var list = this._profiles();
|
| + var profileIndex = list.indexOf(this._profile);
|
| + this._baseSelect.setSelectedIndex(Math.max(0, profileIndex - 1));
|
| + if (this._trackingOverviewGrid)
|
| + this._trackingOverviewGrid._updateGrid();
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.HeapSnapshotCommon.Statistics} statistics
|
| + */
|
| + _gotStatistics(statistics) {
|
| + this._statisticsView.setTotal(statistics.total);
|
| + this._statisticsView.addRecord(statistics.code, WebInspector.UIString('Code'), '#f77');
|
| + this._statisticsView.addRecord(statistics.strings, WebInspector.UIString('Strings'), '#5e5');
|
| + this._statisticsView.addRecord(statistics.jsArrays, WebInspector.UIString('JS Arrays'), '#7af');
|
| + this._statisticsView.addRecord(statistics.native, WebInspector.UIString('Typed Arrays'), '#fc5');
|
| + this._statisticsView.addRecord(statistics.system, WebInspector.UIString('System Objects'), '#98f');
|
| + this._statisticsView.addRecord(statistics.total, WebInspector.UIString('Total'));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _onIdsRangeChanged(event) {
|
| + var minId = event.data.minId;
|
| + var maxId = event.data.maxId;
|
| + this._selectedSizeText.setText(WebInspector.UIString('Selected size: %s', Number.bytesToString(event.data.size)));
|
| + if (this._constructorsDataGrid.snapshot)
|
| + this._constructorsDataGrid.setSelectionRange(minId, maxId);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {!Array.<!WebInspector.ToolbarItem>}
|
| + */
|
| + syncToolbarItems() {
|
| + var result = [this._perspectiveSelect, this._classNameFilter];
|
| + if (this._profile.profileType() !== WebInspector.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType)
|
| + result.push(this._baseSelect, this._filterSelect);
|
| + result.push(this._selectedSizeText);
|
| + return result;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + wasShown() {
|
| + this._profile._loadPromise.then(this._profile._wasShown.bind(this._profile));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + willHide() {
|
| + this._currentSearchResultIndex = -1;
|
| + this._popoverHelper.hidePopover();
|
| + if (this.helpPopover && this.helpPopover.isShowing())
|
| + this.helpPopover.hide();
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + supportsCaseSensitiveSearch() {
|
| + return true;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + supportsRegexSearch() {
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + searchCanceled() {
|
| + this._currentSearchResultIndex = -1;
|
| + this._searchResults = [];
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.HeapSnapshotGridNode} node
|
| + */
|
| + _selectRevealedNode(node) {
|
| + if (node)
|
| + node.select();
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
|
| + * @param {boolean} shouldJump
|
| + * @param {boolean=} jumpBackwards
|
| + */
|
| + performSearch(searchConfig, shouldJump, jumpBackwards) {
|
| + var nextQuery = new WebInspector.HeapSnapshotCommon.SearchConfig(
|
| + searchConfig.query.trim(), searchConfig.caseSensitive, searchConfig.isRegex, shouldJump,
|
| + jumpBackwards || false);
|
| +
|
| + this._searchThrottler.schedule(this._performSearch.bind(this, nextQuery));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.HeapSnapshotCommon.SearchConfig} nextQuery
|
| + * @return {!Promise<?>}
|
| + */
|
| + _performSearch(nextQuery) {
|
| + // Call searchCanceled since it will reset everything we need before doing a new search.
|
| + this.searchCanceled();
|
| +
|
| + if (!this._currentPerspective.supportsSearch())
|
| + return Promise.resolve();
|
| +
|
| + this.currentQuery = nextQuery;
|
| + var query = nextQuery.query.trim();
|
| +
|
| + if (!query)
|
| + return Promise.resolve();
|
| +
|
| + if (query.charAt(0) === '@') {
|
| + var snapshotNodeId = parseInt(query.substring(1), 10);
|
| + if (isNaN(snapshotNodeId))
|
| + return Promise.resolve();
|
| + return this._dataGrid.revealObjectByHeapSnapshotId(String(snapshotNodeId))
|
| + .then(this._selectRevealedNode.bind(this));
|
| + }
|
|
|
| -WebInspector.HeapSnapshotView.Perspective.prototype = {
|
| /**
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - */
|
| - activate: function(heapSnapshotView) { },
|
| + * @param {!Array<number>} entryIds
|
| + * @return {!Promise<?>}
|
| + * @this {WebInspector.HeapSnapshotView}
|
| + */
|
| + function didSearch(entryIds) {
|
| + this._searchResults = entryIds;
|
| + this._searchableView.updateSearchMatchesCount(this._searchResults.length);
|
| + if (this._searchResults.length)
|
| + this._currentSearchResultIndex = nextQuery.jumpBackwards ? this._searchResults.length - 1 : 0;
|
| + return this._jumpToSearchResult(this._currentSearchResultIndex);
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - */
|
| - deactivate: function(heapSnapshotView)
|
| - {
|
| - heapSnapshotView._baseSelect.setVisible(false);
|
| - heapSnapshotView._filterSelect.setVisible(false);
|
| - heapSnapshotView._classNameFilter.setVisible(false);
|
| - if (heapSnapshotView._trackingOverviewGrid)
|
| - heapSnapshotView._trackingOverviewGrid.detach();
|
| - if (heapSnapshotView._allocationWidget)
|
| - heapSnapshotView._allocationWidget.detach();
|
| - if (heapSnapshotView._statisticsView)
|
| - heapSnapshotView._statisticsView.detach();
|
| -
|
| - heapSnapshotView._splitWidget.detach();
|
| - heapSnapshotView._splitWidget.detachChildWidgets();
|
| - },
|
| + return this._profile._snapshotProxy.search(this.currentQuery, this._dataGrid.nodeFilter())
|
| + .then(didSearch.bind(this));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + jumpToNextSearchResult() {
|
| + if (!this._searchResults.length)
|
| + return;
|
| + this._currentSearchResultIndex = (this._currentSearchResultIndex + 1) % this._searchResults.length;
|
| + this._searchThrottler.schedule(this._jumpToSearchResult.bind(this, this._currentSearchResultIndex));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + jumpToPreviousSearchResult() {
|
| + if (!this._searchResults.length)
|
| + return;
|
| + this._currentSearchResultIndex =
|
| + (this._currentSearchResultIndex + this._searchResults.length - 1) % this._searchResults.length;
|
| + this._searchThrottler.schedule(this._jumpToSearchResult.bind(this, this._currentSearchResultIndex));
|
| + }
|
| +
|
| + /**
|
| + * @param {number} searchResultIndex
|
| + * @return {!Promise<undefined>}
|
| + */
|
| + _jumpToSearchResult(searchResultIndex) {
|
| + this._searchableView.updateCurrentMatchIndex(searchResultIndex);
|
| + return this._dataGrid.revealObjectByHeapSnapshotId(String(this._searchResults[searchResultIndex]))
|
| + .then(this._selectRevealedNode.bind(this));
|
| + }
|
| +
|
| + refreshVisibleData() {
|
| + if (!this._dataGrid)
|
| + return;
|
| + var child = this._dataGrid.rootNode().children[0];
|
| + while (child) {
|
| + child.refresh();
|
| + child = child.traverseNextNode(false, null, true);
|
| + }
|
| + }
|
| +
|
| + _changeBase() {
|
| + if (this._baseProfile === this._profiles()[this._baseSelect.selectedIndex()])
|
| + return;
|
| +
|
| + this._baseProfile = this._profiles()[this._baseSelect.selectedIndex()];
|
| + var dataGrid = /** @type {!WebInspector.HeapSnapshotDiffDataGrid} */ (this._dataGrid);
|
| + // Change set base data source only if main data source is already set.
|
| + if (dataGrid.snapshot)
|
| + this._baseProfile._loadPromise.then(dataGrid.setBaseDataSource.bind(dataGrid));
|
| +
|
| + if (!this.currentQuery || !this._searchResults)
|
| + return;
|
| +
|
| + // The current search needs to be performed again. First negate out previous match
|
| + // count by calling the search finished callback with a negative number of matches.
|
| + // Then perform the search again with the same query and callback.
|
| + this.performSearch(this.currentQuery, false);
|
| + }
|
| +
|
| + _changeFilter() {
|
| + var profileIndex = this._filterSelect.selectedIndex() - 1;
|
| + this._dataGrid.filterSelectIndexChanged(this._profiles(), profileIndex);
|
| +
|
| + if (!this.currentQuery || !this._searchResults)
|
| + return;
|
| +
|
| + // The current search needs to be performed again. First negate out previous match
|
| + // count by calling the search finished callback with a negative number of matches.
|
| + // Then perform the search again with the same query and callback.
|
| + this.performSearch(this.currentQuery, false);
|
| + }
|
| +
|
| + /**
|
| + * @return {!Array.<!WebInspector.ProfileHeader>}
|
| + */
|
| + _profiles() {
|
| + return this._profile.profileType().getProfiles();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ContextMenu} contextMenu
|
| + * @param {!Event} event
|
| + */
|
| + populateContextMenu(contextMenu, event) {
|
| + if (this._dataGrid)
|
| + this._dataGrid.populateContextMenu(contextMenu, event);
|
| + }
|
| +
|
| + _selectionChanged(event) {
|
| + var selectedNode = event.target.selectedNode;
|
| + this._setSelectedNodeForDetailsView(selectedNode);
|
| + this._inspectedObjectChanged(event);
|
| + }
|
| +
|
| + _onSelectAllocationNode(event) {
|
| + var selectedNode = event.target.selectedNode;
|
| + this._constructorsDataGrid.setAllocationNodeId(selectedNode.allocationNodeId());
|
| + this._setSelectedNodeForDetailsView(null);
|
| + }
|
| +
|
| + _inspectedObjectChanged(event) {
|
| + var selectedNode = event.target.selectedNode;
|
| + var target = this._profile.target();
|
| + if (target && selectedNode instanceof WebInspector.HeapSnapshotGenericObjectNode)
|
| + target.heapProfilerAgent().addInspectedHeapObject(String(selectedNode.snapshotNodeId));
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.HeapSnapshotGridNode} nodeItem
|
| + */
|
| + _setSelectedNodeForDetailsView(nodeItem) {
|
| + var dataSource = nodeItem && nodeItem.retainersDataSource();
|
| + if (dataSource) {
|
| + this._retainmentDataGrid.setDataSource(dataSource.snapshot, dataSource.snapshotNodeIndex);
|
| + if (this._allocationStackView)
|
| + this._allocationStackView.setAllocatedObject(dataSource.snapshot, dataSource.snapshotNodeIndex);
|
| + } else {
|
| + if (this._allocationStackView)
|
| + this._allocationStackView.clear();
|
| + this._retainmentDataGrid.reset();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {string} perspectiveTitle
|
| + * @param {function()} callback
|
| + */
|
| + _changePerspectiveAndWait(perspectiveTitle, callback) {
|
| + var perspectiveIndex = null;
|
| + for (var i = 0; i < this._perspectives.length; ++i) {
|
| + if (this._perspectives[i].title() === perspectiveTitle) {
|
| + perspectiveIndex = i;
|
| + break;
|
| + }
|
| + }
|
| + if (this._currentPerspectiveIndex === perspectiveIndex || perspectiveIndex === null) {
|
| + setTimeout(callback, 0);
|
| + return;
|
| + }
|
|
|
| /**
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - * @return {?WebInspector.DataGrid}
|
| + * @this {WebInspector.HeapSnapshotView}
|
| */
|
| - masterGrid: function(heapSnapshotView)
|
| - {
|
| - return null;
|
| - },
|
| + function dataGridContentShown(event) {
|
| + var dataGrid = event.data;
|
| + dataGrid.removeEventListener(
|
| + WebInspector.HeapSnapshotSortableDataGrid.Events.ContentShown, dataGridContentShown, this);
|
| + if (dataGrid === this._dataGrid)
|
| + callback();
|
| + }
|
| + this._perspectives[perspectiveIndex].masterGrid(this).addEventListener(
|
| + WebInspector.HeapSnapshotSortableDataGrid.Events.ContentShown, dataGridContentShown, this);
|
|
|
| - /**
|
| - * @return {string}
|
| - */
|
| - title: function()
|
| - {
|
| - return this._title;
|
| - },
|
| + this._perspectiveSelect.setSelectedIndex(perspectiveIndex);
|
| + this._changePerspective(perspectiveIndex);
|
| + }
|
|
|
| - /**
|
| - * @return {boolean}
|
| - */
|
| - supportsSearch: function()
|
| - {
|
| - return false;
|
| - }
|
| -};
|
| + _updateDataSourceAndView() {
|
| + var dataGrid = this._dataGrid;
|
| + if (!dataGrid || dataGrid.snapshot)
|
| + return;
|
|
|
| -/**
|
| - * @constructor
|
| - * @extends {WebInspector.HeapSnapshotView.Perspective}
|
| - */
|
| -WebInspector.HeapSnapshotView.SummaryPerspective = function()
|
| -{
|
| - WebInspector.HeapSnapshotView.Perspective.call(this, WebInspector.UIString("Summary"));
|
| -};
|
| + this._profile._loadPromise.then(didLoadSnapshot.bind(this));
|
|
|
| -WebInspector.HeapSnapshotView.SummaryPerspective.prototype = {
|
| /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @this {WebInspector.HeapSnapshotView}
|
| */
|
| - activate: function(heapSnapshotView)
|
| - {
|
| - heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._constructorsWidget);
|
| - heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| - heapSnapshotView._splitWidget.show(heapSnapshotView._searchableView.element);
|
| - heapSnapshotView._filterSelect.setVisible(true);
|
| - heapSnapshotView._classNameFilter.setVisible(true);
|
| - if (heapSnapshotView._trackingOverviewGrid) {
|
| - heapSnapshotView._trackingOverviewGrid.show(heapSnapshotView._searchableView.element, heapSnapshotView._splitWidget.element);
|
| - heapSnapshotView._trackingOverviewGrid.update();
|
| - heapSnapshotView._trackingOverviewGrid._updateGrid();
|
| - }
|
| - },
|
| + function didLoadSnapshot(snapshotProxy) {
|
| + if (this._dataGrid !== dataGrid)
|
| + return;
|
| + if (dataGrid.snapshot !== snapshotProxy)
|
| + dataGrid.setDataSource(snapshotProxy);
|
| + if (dataGrid === this._diffDataGrid) {
|
| + if (!this._baseProfile)
|
| + this._baseProfile = this._profiles()[this._baseSelect.selectedIndex()];
|
| + this._baseProfile._loadPromise.then(didLoadBaseSnapshot.bind(this));
|
| + }
|
| + }
|
|
|
| /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - * @return {?WebInspector.DataGrid}
|
| + * @this {WebInspector.HeapSnapshotView}
|
| */
|
| - masterGrid: function(heapSnapshotView)
|
| - {
|
| - return heapSnapshotView._constructorsDataGrid;
|
| - },
|
| + function didLoadBaseSnapshot(baseSnapshotProxy) {
|
| + if (this._diffDataGrid.baseSnapshot !== baseSnapshotProxy)
|
| + this._diffDataGrid.setBaseDataSource(baseSnapshotProxy);
|
| + }
|
| + }
|
|
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - supportsSearch: function()
|
| - {
|
| - return true;
|
| - },
|
| + _onSelectedPerspectiveChanged(event) {
|
| + this._changePerspective(event.target.selectedIndex);
|
| + }
|
|
|
| - __proto__: WebInspector.HeapSnapshotView.Perspective.prototype
|
| -};
|
| + /**
|
| + * @param {number} selectedIndex
|
| + */
|
| + _changePerspective(selectedIndex) {
|
| + if (selectedIndex === this._currentPerspectiveIndex)
|
| + return;
|
|
|
| -/**
|
| - * @constructor
|
| - * @extends {WebInspector.HeapSnapshotView.Perspective}
|
| - */
|
| -WebInspector.HeapSnapshotView.ComparisonPerspective = function()
|
| -{
|
| - WebInspector.HeapSnapshotView.Perspective.call(this, WebInspector.UIString("Comparison"));
|
| -};
|
| + this._currentPerspectiveIndex = selectedIndex;
|
|
|
| -WebInspector.HeapSnapshotView.ComparisonPerspective.prototype = {
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - */
|
| - activate: function(heapSnapshotView)
|
| - {
|
| - heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._diffWidget);
|
| - heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| - heapSnapshotView._splitWidget.show(heapSnapshotView._searchableView.element);
|
| - heapSnapshotView._baseSelect.setVisible(true);
|
| - heapSnapshotView._classNameFilter.setVisible(true);
|
| - },
|
| + this._currentPerspective.deactivate(this);
|
| + var perspective = this._perspectives[selectedIndex];
|
| + this._currentPerspective = perspective;
|
| + this._dataGrid = perspective.masterGrid(this);
|
| + perspective.activate(this);
|
|
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - * @return {?WebInspector.DataGrid}
|
| - */
|
| - masterGrid: function(heapSnapshotView)
|
| - {
|
| - return heapSnapshotView._diffDataGrid;
|
| - },
|
| + this.refreshVisibleData();
|
| + if (this._dataGrid)
|
| + this._dataGrid.updateWidths();
|
|
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - supportsSearch: function()
|
| - {
|
| - return true;
|
| - },
|
| + this._updateDataSourceAndView();
|
|
|
| - __proto__: WebInspector.HeapSnapshotView.Perspective.prototype
|
| -};
|
| + if (!this.currentQuery || !this._searchResults)
|
| + return;
|
|
|
| -/**
|
| - * @constructor
|
| - * @extends {WebInspector.HeapSnapshotView.Perspective}
|
| - */
|
| -WebInspector.HeapSnapshotView.ContainmentPerspective = function()
|
| -{
|
| - WebInspector.HeapSnapshotView.Perspective.call(this, WebInspector.UIString("Containment"));
|
| -};
|
| + // The current search needs to be performed again. First negate out previous match
|
| + // count by calling the search finished callback with a negative number of matches.
|
| + // Then perform the search again the with same query and callback.
|
| + this.performSearch(this.currentQuery, false);
|
| + }
|
| +
|
| + /**
|
| + * @param {string} perspectiveName
|
| + * @param {!HeapProfilerAgent.HeapSnapshotObjectId} snapshotObjectId
|
| + */
|
| + selectLiveObject(perspectiveName, snapshotObjectId) {
|
| + this._changePerspectiveAndWait(perspectiveName, didChangePerspective.bind(this));
|
|
|
| -WebInspector.HeapSnapshotView.ContainmentPerspective.prototype = {
|
| /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @this {WebInspector.HeapSnapshotView}
|
| */
|
| - activate: function(heapSnapshotView)
|
| - {
|
| - heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._containmentWidget);
|
| - heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| - heapSnapshotView._splitWidget.show(heapSnapshotView._searchableView.element);
|
| - },
|
| + function didChangePerspective() {
|
| + this._dataGrid.revealObjectByHeapSnapshotId(snapshotObjectId, didRevealObject);
|
| + }
|
|
|
| /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - * @return {?WebInspector.DataGrid}
|
| + * @param {?WebInspector.HeapSnapshotGridNode} node
|
| */
|
| - masterGrid: function(heapSnapshotView)
|
| - {
|
| - return heapSnapshotView._containmentDataGrid;
|
| - },
|
| + function didRevealObject(node) {
|
| + if (node)
|
| + node.select();
|
| + else
|
| + WebInspector.console.error('Cannot find corresponding heap snapshot node');
|
| + }
|
| + }
|
| +
|
| + _getHoverAnchor(target) {
|
| + var span = target.enclosingNodeOrSelfWithNodeName('span');
|
| + if (!span)
|
| + return;
|
| + var row = target.enclosingNodeOrSelfWithNodeName('tr');
|
| + if (!row)
|
| + return;
|
| + span.node = row._dataGridNode;
|
| + return span;
|
| + }
|
| +
|
| + _resolveObjectForPopover(element, showCallback, objectGroupName) {
|
| + if (!this._profile.target())
|
| + return;
|
| + if (!element.node)
|
| + return;
|
| + element.node.queryObjectContent(this._profile.target(), showCallback, objectGroupName);
|
| + }
|
| +
|
| + _updateBaseOptions() {
|
| + var list = this._profiles();
|
| + // We're assuming that snapshots can only be added.
|
| + if (this._baseSelect.size() === list.length)
|
| + return;
|
| +
|
| + for (var i = this._baseSelect.size(), n = list.length; i < n; ++i) {
|
| + var title = list[i].title;
|
| + this._baseSelect.createOption(title);
|
| + }
|
| + }
|
| +
|
| + _updateFilterOptions() {
|
| + var list = this._profiles();
|
| + // We're assuming that snapshots can only be added.
|
| + if (this._filterSelect.size() - 1 === list.length)
|
| + return;
|
| +
|
| + if (!this._filterSelect.size())
|
| + this._filterSelect.createOption(WebInspector.UIString('All objects'));
|
| +
|
| + for (var i = this._filterSelect.size() - 1, n = list.length; i < n; ++i) {
|
| + var title = list[i].title;
|
| + if (!i)
|
| + title = WebInspector.UIString('Objects allocated before %s', title);
|
| + else
|
| + title = WebInspector.UIString('Objects allocated between %s and %s', list[i - 1].title, title);
|
| + this._filterSelect.createOption(title);
|
| + }
|
| + }
|
| +
|
| + _updateControls() {
|
| + this._updateBaseOptions();
|
| + this._updateFilterOptions();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _onReceiveSnapshot(event) {
|
| + this._updateControls();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _onProfileHeaderRemoved(event) {
|
| + var profile = event.data;
|
| + if (this._profile === profile) {
|
| + this.detach();
|
| + this._profile.profileType().removeEventListener(
|
| + WebInspector.HeapSnapshotProfileType.SnapshotReceived, this._onReceiveSnapshot, this);
|
| + this._profile.profileType().removeEventListener(
|
| + WebInspector.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
|
| + this.dispose();
|
| + } else {
|
| + this._updateControls();
|
| + }
|
| + }
|
|
|
| - __proto__: WebInspector.HeapSnapshotView.Perspective.prototype
|
| + dispose() {
|
| + if (this._allocationStackView) {
|
| + this._allocationStackView.clear();
|
| + this._allocationDataGrid.dispose();
|
| + }
|
| + if (this._trackingOverviewGrid)
|
| + this._trackingOverviewGrid.dispose();
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.HeapSnapshotView.Perspective}
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapSnapshotView.AllocationPerspective = function()
|
| -{
|
| - WebInspector.HeapSnapshotView.Perspective.call(this, WebInspector.UIString("Allocation"));
|
| - this._allocationSplitWidget = new WebInspector.SplitWidget(false, true, "heapSnapshotAllocationSplitViewState", 200, 200);
|
| - this._allocationSplitWidget.setSidebarWidget(new WebInspector.VBox());
|
| -
|
| +WebInspector.HeapSnapshotView.Perspective = class {
|
| + /**
|
| + * @param {string} title
|
| + */
|
| + constructor(title) {
|
| + this._title = title;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + activate(heapSnapshotView) {
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + deactivate(heapSnapshotView) {
|
| + heapSnapshotView._baseSelect.setVisible(false);
|
| + heapSnapshotView._filterSelect.setVisible(false);
|
| + heapSnapshotView._classNameFilter.setVisible(false);
|
| + if (heapSnapshotView._trackingOverviewGrid)
|
| + heapSnapshotView._trackingOverviewGrid.detach();
|
| + if (heapSnapshotView._allocationWidget)
|
| + heapSnapshotView._allocationWidget.detach();
|
| + if (heapSnapshotView._statisticsView)
|
| + heapSnapshotView._statisticsView.detach();
|
| +
|
| + heapSnapshotView._splitWidget.detach();
|
| + heapSnapshotView._splitWidget.detachChildWidgets();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @return {?WebInspector.DataGrid}
|
| + */
|
| + masterGrid(heapSnapshotView) {
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| + * @return {string}
|
| + */
|
| + title() {
|
| + return this._title;
|
| + }
|
| +
|
| + /**
|
| + * @return {boolean}
|
| + */
|
| + supportsSearch() {
|
| + return false;
|
| + }
|
| };
|
|
|
| -WebInspector.HeapSnapshotView.AllocationPerspective.prototype = {
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - */
|
| - activate: function(heapSnapshotView)
|
| - {
|
| - this._allocationSplitWidget.setMainWidget(heapSnapshotView._allocationWidget);
|
| - heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._constructorsWidget);
|
| - heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| -
|
| - var allocatedObjectsView = new WebInspector.VBox();
|
| - var resizer = createElementWithClass("div", "heap-snapshot-view-resizer");
|
| - var title = resizer.createChild("div", "title").createChild("span");
|
| - title.textContent = WebInspector.UIString("Live objects");
|
| - this._allocationSplitWidget.hideDefaultResizer();
|
| - this._allocationSplitWidget.installResizer(resizer);
|
| - allocatedObjectsView.element.appendChild(resizer);
|
| - heapSnapshotView._splitWidget.show(allocatedObjectsView.element);
|
| - this._allocationSplitWidget.setSidebarWidget(allocatedObjectsView);
|
| -
|
| - this._allocationSplitWidget.show(heapSnapshotView._searchableView.element);
|
| -
|
| - heapSnapshotView._constructorsDataGrid.clear();
|
| - var selectedNode = heapSnapshotView._allocationDataGrid.selectedNode;
|
| - if (selectedNode)
|
| - heapSnapshotView._constructorsDataGrid.setAllocationNodeId(selectedNode.allocationNodeId());
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - */
|
| - deactivate: function(heapSnapshotView)
|
| - {
|
| - this._allocationSplitWidget.detach();
|
| - WebInspector.HeapSnapshotView.Perspective.prototype.deactivate.call(this, heapSnapshotView);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - * @return {?WebInspector.DataGrid}
|
| - */
|
| - masterGrid: function(heapSnapshotView)
|
| - {
|
| - return heapSnapshotView._allocationDataGrid;
|
| - },
|
| -
|
| - __proto__: WebInspector.HeapSnapshotView.Perspective.prototype
|
| +/**
|
| + * @unrestricted
|
| + */
|
| +WebInspector.HeapSnapshotView.SummaryPerspective = class extends WebInspector.HeapSnapshotView.Perspective {
|
| + constructor() {
|
| + super(WebInspector.UIString('Summary'));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + activate(heapSnapshotView) {
|
| + heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._constructorsWidget);
|
| + heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| + heapSnapshotView._splitWidget.show(heapSnapshotView._searchableView.element);
|
| + heapSnapshotView._filterSelect.setVisible(true);
|
| + heapSnapshotView._classNameFilter.setVisible(true);
|
| + if (heapSnapshotView._trackingOverviewGrid) {
|
| + heapSnapshotView._trackingOverviewGrid.show(
|
| + heapSnapshotView._searchableView.element, heapSnapshotView._splitWidget.element);
|
| + heapSnapshotView._trackingOverviewGrid.update();
|
| + heapSnapshotView._trackingOverviewGrid._updateGrid();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @return {?WebInspector.DataGrid}
|
| + */
|
| + masterGrid(heapSnapshotView) {
|
| + return heapSnapshotView._constructorsDataGrid;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + supportsSearch() {
|
| + return true;
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.HeapSnapshotView.Perspective}
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapSnapshotView.StatisticsPerspective = function()
|
| -{
|
| - WebInspector.HeapSnapshotView.Perspective.call(this, WebInspector.UIString("Statistics"));
|
| +WebInspector.HeapSnapshotView.ComparisonPerspective = class extends WebInspector.HeapSnapshotView.Perspective {
|
| + constructor() {
|
| + super(WebInspector.UIString('Comparison'));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + activate(heapSnapshotView) {
|
| + heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._diffWidget);
|
| + heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| + heapSnapshotView._splitWidget.show(heapSnapshotView._searchableView.element);
|
| + heapSnapshotView._baseSelect.setVisible(true);
|
| + heapSnapshotView._classNameFilter.setVisible(true);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @return {?WebInspector.DataGrid}
|
| + */
|
| + masterGrid(heapSnapshotView) {
|
| + return heapSnapshotView._diffDataGrid;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + supportsSearch() {
|
| + return true;
|
| + }
|
| };
|
|
|
| -WebInspector.HeapSnapshotView.StatisticsPerspective.prototype = {
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - */
|
| - activate: function(heapSnapshotView)
|
| - {
|
| - heapSnapshotView._statisticsView.show(heapSnapshotView._searchableView.element);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| - * @return {?WebInspector.DataGrid}
|
| - */
|
| - masterGrid: function(heapSnapshotView)
|
| - {
|
| - return null;
|
| - },
|
| -
|
| - __proto__: WebInspector.HeapSnapshotView.Perspective.prototype
|
| +/**
|
| + * @unrestricted
|
| + */
|
| +WebInspector.HeapSnapshotView.ContainmentPerspective = class extends WebInspector.HeapSnapshotView.Perspective {
|
| + constructor() {
|
| + super(WebInspector.UIString('Containment'));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + activate(heapSnapshotView) {
|
| + heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._containmentWidget);
|
| + heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| + heapSnapshotView._splitWidget.show(heapSnapshotView._searchableView.element);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @return {?WebInspector.DataGrid}
|
| + */
|
| + masterGrid(heapSnapshotView) {
|
| + return heapSnapshotView._containmentDataGrid;
|
| + }
|
| };
|
|
|
| +/**
|
| + * @unrestricted
|
| + */
|
| +WebInspector.HeapSnapshotView.AllocationPerspective = class extends WebInspector.HeapSnapshotView.Perspective {
|
| + constructor() {
|
| + super(WebInspector.UIString('Allocation'));
|
| + this._allocationSplitWidget =
|
| + new WebInspector.SplitWidget(false, true, 'heapSnapshotAllocationSplitViewState', 200, 200);
|
| + this._allocationSplitWidget.setSidebarWidget(new WebInspector.VBox());
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + activate(heapSnapshotView) {
|
| + this._allocationSplitWidget.setMainWidget(heapSnapshotView._allocationWidget);
|
| + heapSnapshotView._splitWidget.setMainWidget(heapSnapshotView._constructorsWidget);
|
| + heapSnapshotView._splitWidget.setSidebarWidget(heapSnapshotView._objectDetailsView);
|
| +
|
| + var allocatedObjectsView = new WebInspector.VBox();
|
| + var resizer = createElementWithClass('div', 'heap-snapshot-view-resizer');
|
| + var title = resizer.createChild('div', 'title').createChild('span');
|
| + title.textContent = WebInspector.UIString('Live objects');
|
| + this._allocationSplitWidget.hideDefaultResizer();
|
| + this._allocationSplitWidget.installResizer(resizer);
|
| + allocatedObjectsView.element.appendChild(resizer);
|
| + heapSnapshotView._splitWidget.show(allocatedObjectsView.element);
|
| + this._allocationSplitWidget.setSidebarWidget(allocatedObjectsView);
|
| +
|
| + this._allocationSplitWidget.show(heapSnapshotView._searchableView.element);
|
| +
|
| + heapSnapshotView._constructorsDataGrid.clear();
|
| + var selectedNode = heapSnapshotView._allocationDataGrid.selectedNode;
|
| + if (selectedNode)
|
| + heapSnapshotView._constructorsDataGrid.setAllocationNodeId(selectedNode.allocationNodeId());
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + deactivate(heapSnapshotView) {
|
| + this._allocationSplitWidget.detach();
|
| + super.deactivate(heapSnapshotView);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @return {?WebInspector.DataGrid}
|
| + */
|
| + masterGrid(heapSnapshotView) {
|
| + return heapSnapshotView._allocationDataGrid;
|
| + }
|
| +};
|
|
|
| -WebInspector.HeapSnapshotView.prototype = {
|
| - /**
|
| - * @return {!WebInspector.SearchableView}
|
| - */
|
| - searchableView: function()
|
| - {
|
| - return this._searchableView;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {?WebInspector.ProfileHeader} profile
|
| - * @return {?WebInspector.Widget}
|
| - */
|
| - showProfile: function(profile)
|
| - {
|
| - return this._parentDataDisplayDelegate.showProfile(profile);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!HeapProfilerAgent.HeapSnapshotObjectId} snapshotObjectId
|
| - * @param {string} perspectiveName
|
| - */
|
| - showObject: function(snapshotObjectId, perspectiveName)
|
| - {
|
| - if (snapshotObjectId <= this._profile.maxJSObjectId)
|
| - this.selectLiveObject(perspectiveName, snapshotObjectId);
|
| - else
|
| - this._parentDataDisplayDelegate.showObject(snapshotObjectId, perspectiveName);
|
| - },
|
| -
|
| - _populate: function()
|
| - {
|
| - this._profile._loadPromise.then(heapSnapshotProxy => {
|
| - heapSnapshotProxy.getStatistics().then(this._gotStatistics.bind(this));
|
| - this._dataGrid.setDataSource(heapSnapshotProxy);
|
| - if (this._profile.profileType().id === WebInspector.TrackingHeapSnapshotProfileType.TypeId && this._profile.fromFile())
|
| - return heapSnapshotProxy.getSamples().then(samples => this._trackingOverviewGrid._setSamples(samples));
|
| - }).then(_ => {
|
| - var list = this._profiles();
|
| - var profileIndex = list.indexOf(this._profile);
|
| - this._baseSelect.setSelectedIndex(Math.max(0, profileIndex - 1));
|
| - if (this._trackingOverviewGrid)
|
| - this._trackingOverviewGrid._updateGrid();
|
| - });
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.HeapSnapshotCommon.Statistics} statistics
|
| - */
|
| - _gotStatistics: function(statistics)
|
| - {
|
| - this._statisticsView.setTotal(statistics.total);
|
| - this._statisticsView.addRecord(statistics.code, WebInspector.UIString("Code"), "#f77");
|
| - this._statisticsView.addRecord(statistics.strings, WebInspector.UIString("Strings"), "#5e5");
|
| - this._statisticsView.addRecord(statistics.jsArrays, WebInspector.UIString("JS Arrays"), "#7af");
|
| - this._statisticsView.addRecord(statistics.native, WebInspector.UIString("Typed Arrays"), "#fc5");
|
| - this._statisticsView.addRecord(statistics.system, WebInspector.UIString("System Objects"), "#98f");
|
| - this._statisticsView.addRecord(statistics.total, WebInspector.UIString("Total"));
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _onIdsRangeChanged: function(event)
|
| - {
|
| - var minId = event.data.minId;
|
| - var maxId = event.data.maxId;
|
| - this._selectedSizeText.setText(WebInspector.UIString("Selected size: %s", Number.bytesToString(event.data.size)));
|
| - if (this._constructorsDataGrid.snapshot)
|
| - this._constructorsDataGrid.setSelectionRange(minId, maxId);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {!Array.<!WebInspector.ToolbarItem>}
|
| - */
|
| - syncToolbarItems: function()
|
| - {
|
| - var result = [this._perspectiveSelect, this._classNameFilter];
|
| - if (this._profile.profileType() !== WebInspector.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType)
|
| - result.push(this._baseSelect, this._filterSelect);
|
| - result.push(this._selectedSizeText);
|
| - return result;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - wasShown: function()
|
| - {
|
| - this._profile._loadPromise.then(this._profile._wasShown.bind(this._profile));
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - willHide: function()
|
| - {
|
| - this._currentSearchResultIndex = -1;
|
| - this._popoverHelper.hidePopover();
|
| - if (this.helpPopover && this.helpPopover.isShowing())
|
| - this.helpPopover.hide();
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - supportsCaseSensitiveSearch: function()
|
| - {
|
| - return true;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - supportsRegexSearch: function()
|
| - {
|
| - return false;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - searchCanceled: function()
|
| - {
|
| - this._currentSearchResultIndex = -1;
|
| - this._searchResults = [];
|
| - },
|
| -
|
| - /**
|
| - * @param {?WebInspector.HeapSnapshotGridNode} node
|
| - */
|
| - _selectRevealedNode: function(node)
|
| - {
|
| - if (node)
|
| - node.select();
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
|
| - * @param {boolean} shouldJump
|
| - * @param {boolean=} jumpBackwards
|
| - */
|
| - performSearch: function(searchConfig, shouldJump, jumpBackwards)
|
| - {
|
| - var nextQuery = new WebInspector.HeapSnapshotCommon.SearchConfig(
|
| - searchConfig.query.trim(),
|
| - searchConfig.caseSensitive,
|
| - searchConfig.isRegex,
|
| - shouldJump,
|
| - jumpBackwards || false
|
| - );
|
| -
|
| - this._searchThrottler.schedule(this._performSearch.bind(this, nextQuery));
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.HeapSnapshotCommon.SearchConfig} nextQuery
|
| - * @return {!Promise<?>}
|
| - */
|
| - _performSearch: function(nextQuery)
|
| - {
|
| - // Call searchCanceled since it will reset everything we need before doing a new search.
|
| - this.searchCanceled();
|
| -
|
| - if (!this._currentPerspective.supportsSearch())
|
| - return Promise.resolve();
|
| -
|
| - this.currentQuery = nextQuery;
|
| - var query = nextQuery.query.trim();
|
| -
|
| - if (!query)
|
| - return Promise.resolve();
|
| -
|
| - if (query.charAt(0) === "@") {
|
| - var snapshotNodeId = parseInt(query.substring(1), 10);
|
| - if (isNaN(snapshotNodeId))
|
| - return Promise.resolve();
|
| - return this._dataGrid.revealObjectByHeapSnapshotId(String(snapshotNodeId)).then(this._selectRevealedNode.bind(this));
|
| - }
|
| -
|
| - /**
|
| - * @param {!Array<number>} entryIds
|
| - * @return {!Promise<?>}
|
| - * @this {WebInspector.HeapSnapshotView}
|
| - */
|
| - function didSearch(entryIds)
|
| - {
|
| - this._searchResults = entryIds;
|
| - this._searchableView.updateSearchMatchesCount(this._searchResults.length);
|
| - if (this._searchResults.length)
|
| - this._currentSearchResultIndex = nextQuery.jumpBackwards ? this._searchResults.length - 1 : 0;
|
| - return this._jumpToSearchResult(this._currentSearchResultIndex);
|
| - }
|
| -
|
| - return this._profile._snapshotProxy.search(this.currentQuery, this._dataGrid.nodeFilter()).then(didSearch.bind(this));
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - jumpToNextSearchResult: function()
|
| - {
|
| - if (!this._searchResults.length)
|
| - return;
|
| - this._currentSearchResultIndex = (this._currentSearchResultIndex + 1) % this._searchResults.length;
|
| - this._searchThrottler.schedule(this._jumpToSearchResult.bind(this, this._currentSearchResultIndex));
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - jumpToPreviousSearchResult: function()
|
| - {
|
| - if (!this._searchResults.length)
|
| - return;
|
| - this._currentSearchResultIndex = (this._currentSearchResultIndex + this._searchResults.length - 1) % this._searchResults.length;
|
| - this._searchThrottler.schedule(this._jumpToSearchResult.bind(this, this._currentSearchResultIndex));
|
| - },
|
| -
|
| - /**
|
| - * @param {number} searchResultIndex
|
| - * @return {!Promise<undefined>}
|
| - */
|
| - _jumpToSearchResult: function(searchResultIndex)
|
| - {
|
| - this._searchableView.updateCurrentMatchIndex(searchResultIndex);
|
| - return this._dataGrid.revealObjectByHeapSnapshotId(String(this._searchResults[searchResultIndex])).then(this._selectRevealedNode.bind(this));
|
| - },
|
| -
|
| - refreshVisibleData: function()
|
| - {
|
| - if (!this._dataGrid)
|
| - return;
|
| - var child = this._dataGrid.rootNode().children[0];
|
| - while (child) {
|
| - child.refresh();
|
| - child = child.traverseNextNode(false, null, true);
|
| - }
|
| - },
|
| -
|
| - _changeBase: function()
|
| - {
|
| - if (this._baseProfile === this._profiles()[this._baseSelect.selectedIndex()])
|
| - return;
|
| -
|
| - this._baseProfile = this._profiles()[this._baseSelect.selectedIndex()];
|
| - var dataGrid = /** @type {!WebInspector.HeapSnapshotDiffDataGrid} */ (this._dataGrid);
|
| - // Change set base data source only if main data source is already set.
|
| - if (dataGrid.snapshot)
|
| - this._baseProfile._loadPromise.then(dataGrid.setBaseDataSource.bind(dataGrid));
|
| -
|
| - if (!this.currentQuery || !this._searchResults)
|
| - return;
|
| -
|
| - // The current search needs to be performed again. First negate out previous match
|
| - // count by calling the search finished callback with a negative number of matches.
|
| - // Then perform the search again with the same query and callback.
|
| - this.performSearch(this.currentQuery, false);
|
| - },
|
| -
|
| - _changeFilter: function()
|
| - {
|
| - var profileIndex = this._filterSelect.selectedIndex() - 1;
|
| - this._dataGrid.filterSelectIndexChanged(this._profiles(), profileIndex);
|
| -
|
| - if (!this.currentQuery || !this._searchResults)
|
| - return;
|
| -
|
| - // The current search needs to be performed again. First negate out previous match
|
| - // count by calling the search finished callback with a negative number of matches.
|
| - // Then perform the search again with the same query and callback.
|
| - this.performSearch(this.currentQuery, false);
|
| - },
|
| -
|
| - /**
|
| - * @return {!Array.<!WebInspector.ProfileHeader>}
|
| - */
|
| - _profiles: function()
|
| - {
|
| - return this._profile.profileType().getProfiles();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.ContextMenu} contextMenu
|
| - * @param {!Event} event
|
| - */
|
| - populateContextMenu: function(contextMenu, event)
|
| - {
|
| - if (this._dataGrid)
|
| - this._dataGrid.populateContextMenu(contextMenu, event);
|
| - },
|
| -
|
| - _selectionChanged: function(event)
|
| - {
|
| - var selectedNode = event.target.selectedNode;
|
| - this._setSelectedNodeForDetailsView(selectedNode);
|
| - this._inspectedObjectChanged(event);
|
| - },
|
| -
|
| - _onSelectAllocationNode: function(event)
|
| - {
|
| - var selectedNode = event.target.selectedNode;
|
| - this._constructorsDataGrid.setAllocationNodeId(selectedNode.allocationNodeId());
|
| - this._setSelectedNodeForDetailsView(null);
|
| - },
|
| -
|
| - _inspectedObjectChanged: function(event)
|
| - {
|
| - var selectedNode = event.target.selectedNode;
|
| - var target = this._profile.target();
|
| - if (target && selectedNode instanceof WebInspector.HeapSnapshotGenericObjectNode)
|
| - target.heapProfilerAgent().addInspectedHeapObject(String(selectedNode.snapshotNodeId));
|
| - },
|
| -
|
| - /**
|
| - * @param {?WebInspector.HeapSnapshotGridNode} nodeItem
|
| - */
|
| - _setSelectedNodeForDetailsView: function(nodeItem)
|
| - {
|
| - var dataSource = nodeItem && nodeItem.retainersDataSource();
|
| - if (dataSource) {
|
| - this._retainmentDataGrid.setDataSource(dataSource.snapshot, dataSource.snapshotNodeIndex);
|
| - if (this._allocationStackView)
|
| - this._allocationStackView.setAllocatedObject(dataSource.snapshot, dataSource.snapshotNodeIndex);
|
| - } else {
|
| - if (this._allocationStackView)
|
| - this._allocationStackView.clear();
|
| - this._retainmentDataGrid.reset();
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * @param {string} perspectiveTitle
|
| - * @param {function()} callback
|
| - */
|
| - _changePerspectiveAndWait: function(perspectiveTitle, callback)
|
| - {
|
| - var perspectiveIndex = null;
|
| - for (var i = 0; i < this._perspectives.length; ++i) {
|
| - if (this._perspectives[i].title() === perspectiveTitle) {
|
| - perspectiveIndex = i;
|
| - break;
|
| - }
|
| - }
|
| - if (this._currentPerspectiveIndex === perspectiveIndex || perspectiveIndex === null) {
|
| - setTimeout(callback, 0);
|
| - return;
|
| - }
|
| -
|
| - /**
|
| - * @this {WebInspector.HeapSnapshotView}
|
| - */
|
| - function dataGridContentShown(event)
|
| - {
|
| - var dataGrid = event.data;
|
| - dataGrid.removeEventListener(WebInspector.HeapSnapshotSortableDataGrid.Events.ContentShown, dataGridContentShown, this);
|
| - if (dataGrid === this._dataGrid)
|
| - callback();
|
| - }
|
| - this._perspectives[perspectiveIndex].masterGrid(this).addEventListener(WebInspector.HeapSnapshotSortableDataGrid.Events.ContentShown, dataGridContentShown, this);
|
| -
|
| - this._perspectiveSelect.setSelectedIndex(perspectiveIndex);
|
| - this._changePerspective(perspectiveIndex);
|
| - },
|
| -
|
| - _updateDataSourceAndView: function()
|
| - {
|
| - var dataGrid = this._dataGrid;
|
| - if (!dataGrid || dataGrid.snapshot)
|
| - return;
|
| -
|
| - this._profile._loadPromise.then(didLoadSnapshot.bind(this));
|
| -
|
| - /**
|
| - * @this {WebInspector.HeapSnapshotView}
|
| - */
|
| - function didLoadSnapshot(snapshotProxy)
|
| - {
|
| - if (this._dataGrid !== dataGrid)
|
| - return;
|
| - if (dataGrid.snapshot !== snapshotProxy)
|
| - dataGrid.setDataSource(snapshotProxy);
|
| - if (dataGrid === this._diffDataGrid) {
|
| - if (!this._baseProfile)
|
| - this._baseProfile = this._profiles()[this._baseSelect.selectedIndex()];
|
| - this._baseProfile._loadPromise.then(didLoadBaseSnapshot.bind(this));
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @this {WebInspector.HeapSnapshotView}
|
| - */
|
| - function didLoadBaseSnapshot(baseSnapshotProxy)
|
| - {
|
| - if (this._diffDataGrid.baseSnapshot !== baseSnapshotProxy)
|
| - this._diffDataGrid.setBaseDataSource(baseSnapshotProxy);
|
| - }
|
| - },
|
| -
|
| - _onSelectedPerspectiveChanged: function(event)
|
| - {
|
| - this._changePerspective(event.target.selectedIndex);
|
| - },
|
| -
|
| - /**
|
| - * @param {number} selectedIndex
|
| - */
|
| - _changePerspective: function(selectedIndex)
|
| - {
|
| - if (selectedIndex === this._currentPerspectiveIndex)
|
| - return;
|
| -
|
| - this._currentPerspectiveIndex = selectedIndex;
|
| -
|
| - this._currentPerspective.deactivate(this);
|
| - var perspective = this._perspectives[selectedIndex];
|
| - this._currentPerspective = perspective;
|
| - this._dataGrid = perspective.masterGrid(this);
|
| - perspective.activate(this);
|
| -
|
| - this.refreshVisibleData();
|
| - if (this._dataGrid)
|
| - this._dataGrid.updateWidths();
|
| -
|
| - this._updateDataSourceAndView();
|
| -
|
| - if (!this.currentQuery || !this._searchResults)
|
| - return;
|
| -
|
| - // The current search needs to be performed again. First negate out previous match
|
| - // count by calling the search finished callback with a negative number of matches.
|
| - // Then perform the search again the with same query and callback.
|
| - this.performSearch(this.currentQuery, false);
|
| - },
|
| -
|
| - /**
|
| - * @param {string} perspectiveName
|
| - * @param {!HeapProfilerAgent.HeapSnapshotObjectId} snapshotObjectId
|
| - */
|
| - selectLiveObject: function(perspectiveName, snapshotObjectId)
|
| - {
|
| - this._changePerspectiveAndWait(perspectiveName, didChangePerspective.bind(this));
|
| -
|
| - /**
|
| - * @this {WebInspector.HeapSnapshotView}
|
| - */
|
| - function didChangePerspective()
|
| - {
|
| - this._dataGrid.revealObjectByHeapSnapshotId(snapshotObjectId, didRevealObject);
|
| - }
|
| -
|
| - /**
|
| - * @param {?WebInspector.HeapSnapshotGridNode} node
|
| - */
|
| - function didRevealObject(node)
|
| - {
|
| - if (node)
|
| - node.select();
|
| - else
|
| - WebInspector.console.error("Cannot find corresponding heap snapshot node");
|
| - }
|
| - },
|
| -
|
| - _getHoverAnchor: function(target)
|
| - {
|
| - var span = target.enclosingNodeOrSelfWithNodeName("span");
|
| - if (!span)
|
| - return;
|
| - var row = target.enclosingNodeOrSelfWithNodeName("tr");
|
| - if (!row)
|
| - return;
|
| - span.node = row._dataGridNode;
|
| - return span;
|
| - },
|
| -
|
| - _resolveObjectForPopover: function(element, showCallback, objectGroupName)
|
| - {
|
| - if (!this._profile.target())
|
| - return;
|
| - if (!element.node)
|
| - return;
|
| - element.node.queryObjectContent(this._profile.target(), showCallback, objectGroupName);
|
| - },
|
| -
|
| - _updateBaseOptions: function()
|
| - {
|
| - var list = this._profiles();
|
| - // We're assuming that snapshots can only be added.
|
| - if (this._baseSelect.size() === list.length)
|
| - return;
|
| -
|
| - for (var i = this._baseSelect.size(), n = list.length; i < n; ++i) {
|
| - var title = list[i].title;
|
| - this._baseSelect.createOption(title);
|
| - }
|
| - },
|
| -
|
| - _updateFilterOptions: function()
|
| - {
|
| - var list = this._profiles();
|
| - // We're assuming that snapshots can only be added.
|
| - if (this._filterSelect.size() - 1 === list.length)
|
| - return;
|
| -
|
| - if (!this._filterSelect.size())
|
| - this._filterSelect.createOption(WebInspector.UIString("All objects"));
|
| -
|
| - for (var i = this._filterSelect.size() - 1, n = list.length; i < n; ++i) {
|
| - var title = list[i].title;
|
| - if (!i)
|
| - title = WebInspector.UIString("Objects allocated before %s", title);
|
| - else
|
| - title = WebInspector.UIString("Objects allocated between %s and %s", list[i - 1].title, title);
|
| - this._filterSelect.createOption(title);
|
| - }
|
| - },
|
| -
|
| - _updateControls: function()
|
| - {
|
| - this._updateBaseOptions();
|
| - this._updateFilterOptions();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _onReceiveSnapshot: function(event)
|
| - {
|
| - this._updateControls();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _onProfileHeaderRemoved: function(event)
|
| - {
|
| - var profile = event.data;
|
| - if (this._profile === profile) {
|
| - this.detach();
|
| - this._profile.profileType().removeEventListener(WebInspector.HeapSnapshotProfileType.SnapshotReceived, this._onReceiveSnapshot, this);
|
| - this._profile.profileType().removeEventListener(WebInspector.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
|
| - this.dispose();
|
| - } else {
|
| - this._updateControls();
|
| - }
|
| - },
|
| -
|
| - dispose: function()
|
| - {
|
| - if (this._allocationStackView) {
|
| - this._allocationStackView.clear();
|
| - this._allocationDataGrid.dispose();
|
| - }
|
| - if (this._trackingOverviewGrid)
|
| - this._trackingOverviewGrid.dispose();
|
| - },
|
| -
|
| - __proto__: WebInspector.SimpleView.prototype
|
| +/**
|
| + * @unrestricted
|
| + */
|
| +WebInspector.HeapSnapshotView.StatisticsPerspective = class extends WebInspector.HeapSnapshotView.Perspective {
|
| + constructor() {
|
| + super(WebInspector.UIString('Statistics'));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + */
|
| + activate(heapSnapshotView) {
|
| + heapSnapshotView._statisticsView.show(heapSnapshotView._searchableView.element);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.HeapSnapshotView} heapSnapshotView
|
| + * @return {?WebInspector.DataGrid}
|
| + */
|
| + masterGrid(heapSnapshotView) {
|
| + return null;
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.ProfileType}
|
| * @implements {WebInspector.TargetManager.Observer}
|
| - * @param {string=} id
|
| - * @param {string=} title
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapSnapshotProfileType = function(id, title)
|
| -{
|
| - WebInspector.ProfileType.call(this, id || WebInspector.HeapSnapshotProfileType.TypeId, title || WebInspector.UIString("Take Heap Snapshot"));
|
| +WebInspector.HeapSnapshotProfileType = class extends WebInspector.ProfileType {
|
| + /**
|
| + * @param {string=} id
|
| + * @param {string=} title
|
| + */
|
| + constructor(id, title) {
|
| + super(id || WebInspector.HeapSnapshotProfileType.TypeId, title || WebInspector.UIString('Take Heap Snapshot'));
|
| WebInspector.targetManager.observeTargets(this);
|
| - WebInspector.targetManager.addModelListener(WebInspector.HeapProfilerModel, WebInspector.HeapProfilerModel.Events.ResetProfiles, this._resetProfiles, this);
|
| - WebInspector.targetManager.addModelListener(WebInspector.HeapProfilerModel, WebInspector.HeapProfilerModel.Events.AddHeapSnapshotChunk, this._addHeapSnapshotChunk, this);
|
| - WebInspector.targetManager.addModelListener(WebInspector.HeapProfilerModel, WebInspector.HeapProfilerModel.Events.ReportHeapSnapshotProgress, this._reportHeapSnapshotProgress, this);
|
| -};
|
| -
|
| -WebInspector.HeapSnapshotProfileType.TypeId = "HEAP";
|
| -WebInspector.HeapSnapshotProfileType.SnapshotReceived = "SnapshotReceived";
|
| -
|
| -WebInspector.HeapSnapshotProfileType.prototype = {
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.Target} target
|
| - */
|
| - targetAdded: function(target)
|
| - {
|
| - target.heapProfilerModel.enable();
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.Target} target
|
| - */
|
| - targetRemoved: function(target)
|
| - {
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {string}
|
| - */
|
| - fileExtension: function()
|
| - {
|
| - return ".heapsnapshot";
|
| - },
|
| -
|
| - get buttonTooltip()
|
| - {
|
| - return WebInspector.UIString("Take heap snapshot");
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - isInstantProfile: function()
|
| - {
|
| - return true;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - buttonClicked: function()
|
| - {
|
| - this._takeHeapSnapshot(function() {});
|
| - WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.ProfilesHeapProfileTaken);
|
| - return false;
|
| - },
|
| -
|
| - get treeItemTitle()
|
| - {
|
| - return WebInspector.UIString("HEAP SNAPSHOTS");
|
| - },
|
| -
|
| - get description()
|
| - {
|
| - return WebInspector.UIString("Heap snapshot profiles show memory distribution among your page's JavaScript objects and related DOM nodes.");
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {string} title
|
| - * @return {!WebInspector.ProfileHeader}
|
| - */
|
| - createProfileLoadedFromFile: function(title)
|
| - {
|
| - return new WebInspector.HeapProfileHeader(null, this, title);
|
| - },
|
| -
|
| - _takeHeapSnapshot: function(callback)
|
| - {
|
| - if (this.profileBeingRecorded())
|
| - return;
|
| - var target = /** @type {!WebInspector.Target} */ (WebInspector.context.flavor(WebInspector.Target));
|
| - var profile = new WebInspector.HeapProfileHeader(target, this);
|
| - this.setProfileBeingRecorded(profile);
|
| - this.addProfile(profile);
|
| - profile.updateStatus(WebInspector.UIString("Snapshotting\u2026"));
|
| -
|
| - /**
|
| - * @param {?string} error
|
| - * @this {WebInspector.HeapSnapshotProfileType}
|
| - */
|
| - function didTakeHeapSnapshot(error)
|
| - {
|
| - var profile = this._profileBeingRecorded;
|
| - profile.title = WebInspector.UIString("Snapshot %d", profile.uid);
|
| - profile._finishLoad();
|
| - this.setProfileBeingRecorded(null);
|
| - this.dispatchEventToListeners(WebInspector.ProfileType.Events.ProfileComplete, profile);
|
| - callback();
|
| - }
|
| - target.heapProfilerAgent().takeHeapSnapshot(true, didTakeHeapSnapshot.bind(this));
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _addHeapSnapshotChunk: function(event)
|
| - {
|
| - if (!this.profileBeingRecorded())
|
| - return;
|
| - var chunk = /** @type {string} */(event.data);
|
| - this.profileBeingRecorded().transferChunk(chunk);
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _reportHeapSnapshotProgress: function(event)
|
| - {
|
| - var profile = this.profileBeingRecorded();
|
| - if (!profile)
|
| - return;
|
| - var data = /** @type {{done: number, total: number, finished: boolean}} */ (event.data);
|
| - profile.updateStatus(WebInspector.UIString("%.0f%%", (data.done / data.total) * 100), true);
|
| - if (data.finished)
|
| - profile._prepareToLoad();
|
| - },
|
| -
|
| - _resetProfiles: function()
|
| - {
|
| - this._reset();
|
| - },
|
| -
|
| - _snapshotReceived: function(profile)
|
| - {
|
| - if (this._profileBeingRecorded === profile)
|
| - this.setProfileBeingRecorded(null);
|
| - this.dispatchEventToListeners(WebInspector.HeapSnapshotProfileType.SnapshotReceived, profile);
|
| - },
|
| -
|
| - __proto__: WebInspector.ProfileType.prototype
|
| + WebInspector.targetManager.addModelListener(
|
| + WebInspector.HeapProfilerModel, WebInspector.HeapProfilerModel.Events.ResetProfiles, this._resetProfiles, this);
|
| + WebInspector.targetManager.addModelListener(
|
| + WebInspector.HeapProfilerModel, WebInspector.HeapProfilerModel.Events.AddHeapSnapshotChunk,
|
| + this._addHeapSnapshotChunk, this);
|
| + WebInspector.targetManager.addModelListener(
|
| + WebInspector.HeapProfilerModel, WebInspector.HeapProfilerModel.Events.ReportHeapSnapshotProgress,
|
| + this._reportHeapSnapshotProgress, this);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.Target} target
|
| + */
|
| + targetAdded(target) {
|
| + target.heapProfilerModel.enable();
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.Target} target
|
| + */
|
| + targetRemoved(target) {
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {string}
|
| + */
|
| + fileExtension() {
|
| + return '.heapsnapshot';
|
| + }
|
| +
|
| + get buttonTooltip() {
|
| + return WebInspector.UIString('Take heap snapshot');
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + isInstantProfile() {
|
| + return true;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + buttonClicked() {
|
| + this._takeHeapSnapshot(function() {});
|
| + WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.ProfilesHeapProfileTaken);
|
| + return false;
|
| + }
|
| +
|
| + get treeItemTitle() {
|
| + return WebInspector.UIString('HEAP SNAPSHOTS');
|
| + }
|
| +
|
| + get description() {
|
| + return WebInspector.UIString(
|
| + 'Heap snapshot profiles show memory distribution among your page\'s JavaScript objects and related DOM nodes.');
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {string} title
|
| + * @return {!WebInspector.ProfileHeader}
|
| + */
|
| + createProfileLoadedFromFile(title) {
|
| + return new WebInspector.HeapProfileHeader(null, this, title);
|
| + }
|
| +
|
| + _takeHeapSnapshot(callback) {
|
| + if (this.profileBeingRecorded())
|
| + return;
|
| + var target = /** @type {!WebInspector.Target} */ (WebInspector.context.flavor(WebInspector.Target));
|
| + var profile = new WebInspector.HeapProfileHeader(target, this);
|
| + this.setProfileBeingRecorded(profile);
|
| + this.addProfile(profile);
|
| + profile.updateStatus(WebInspector.UIString('Snapshotting\u2026'));
|
| +
|
| + /**
|
| + * @param {?string} error
|
| + * @this {WebInspector.HeapSnapshotProfileType}
|
| + */
|
| + function didTakeHeapSnapshot(error) {
|
| + var profile = this._profileBeingRecorded;
|
| + profile.title = WebInspector.UIString('Snapshot %d', profile.uid);
|
| + profile._finishLoad();
|
| + this.setProfileBeingRecorded(null);
|
| + this.dispatchEventToListeners(WebInspector.ProfileType.Events.ProfileComplete, profile);
|
| + callback();
|
| + }
|
| + target.heapProfilerAgent().takeHeapSnapshot(true, didTakeHeapSnapshot.bind(this));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _addHeapSnapshotChunk(event) {
|
| + if (!this.profileBeingRecorded())
|
| + return;
|
| + var chunk = /** @type {string} */ (event.data);
|
| + this.profileBeingRecorded().transferChunk(chunk);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _reportHeapSnapshotProgress(event) {
|
| + var profile = this.profileBeingRecorded();
|
| + if (!profile)
|
| + return;
|
| + var data = /** @type {{done: number, total: number, finished: boolean}} */ (event.data);
|
| + profile.updateStatus(WebInspector.UIString('%.0f%%', (data.done / data.total) * 100), true);
|
| + if (data.finished)
|
| + profile._prepareToLoad();
|
| + }
|
| +
|
| + _resetProfiles() {
|
| + this._reset();
|
| + }
|
| +
|
| + _snapshotReceived(profile) {
|
| + if (this._profileBeingRecorded === profile)
|
| + this.setProfileBeingRecorded(null);
|
| + this.dispatchEventToListeners(WebInspector.HeapSnapshotProfileType.SnapshotReceived, profile);
|
| + }
|
| };
|
|
|
| +WebInspector.HeapSnapshotProfileType.TypeId = 'HEAP';
|
| +WebInspector.HeapSnapshotProfileType.SnapshotReceived = 'SnapshotReceived';
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.HeapSnapshotProfileType}
|
| + * @unrestricted
|
| */
|
| -WebInspector.TrackingHeapSnapshotProfileType = function()
|
| -{
|
| - WebInspector.HeapSnapshotProfileType.call(this, WebInspector.TrackingHeapSnapshotProfileType.TypeId, WebInspector.UIString("Record Allocation Timeline"));
|
| -};
|
| +WebInspector.TrackingHeapSnapshotProfileType = class extends WebInspector.HeapSnapshotProfileType {
|
| + constructor() {
|
| + super(WebInspector.TrackingHeapSnapshotProfileType.TypeId, WebInspector.UIString('Record Allocation Timeline'));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.Target} target
|
| + */
|
| + targetAdded(target) {
|
| + super.targetAdded(target);
|
| + target.heapProfilerModel.addEventListener(
|
| + WebInspector.HeapProfilerModel.Events.HeapStatsUpdate, this._heapStatsUpdate, this);
|
| + target.heapProfilerModel.addEventListener(
|
| + WebInspector.HeapProfilerModel.Events.LastSeenObjectId, this._lastSeenObjectId, this);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.Target} target
|
| + */
|
| + targetRemoved(target) {
|
| + super.targetRemoved(target);
|
| + target.heapProfilerModel.removeEventListener(
|
| + WebInspector.HeapProfilerModel.Events.HeapStatsUpdate, this._heapStatsUpdate, this);
|
| + target.heapProfilerModel.removeEventListener(
|
| + WebInspector.HeapProfilerModel.Events.LastSeenObjectId, this._lastSeenObjectId, this);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _heapStatsUpdate(event) {
|
| + if (!this._profileSamples)
|
| + return;
|
| + var samples = /** @type {!Array.<number>} */ (event.data);
|
| + var index;
|
| + for (var i = 0; i < samples.length; i += 3) {
|
| + index = samples[i];
|
| + var size = samples[i + 2];
|
| + this._profileSamples.sizes[index] = size;
|
| + if (!this._profileSamples.max[index])
|
| + this._profileSamples.max[index] = size;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _lastSeenObjectId(event) {
|
| + var profileSamples = this._profileSamples;
|
| + if (!profileSamples)
|
| + return;
|
| + var data = /** @type {{lastSeenObjectId: number, timestamp: number}} */ (event.data);
|
| + var currentIndex = Math.max(profileSamples.ids.length, profileSamples.max.length - 1);
|
| + profileSamples.ids[currentIndex] = data.lastSeenObjectId;
|
| + if (!profileSamples.max[currentIndex]) {
|
| + profileSamples.max[currentIndex] = 0;
|
| + profileSamples.sizes[currentIndex] = 0;
|
| + }
|
| + profileSamples.timestamps[currentIndex] = data.timestamp;
|
| + if (profileSamples.totalTime < data.timestamp - profileSamples.timestamps[0])
|
| + profileSamples.totalTime *= 2;
|
| + this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._profileSamples);
|
| + this._profileBeingRecorded.updateStatus(null, true);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + hasTemporaryView() {
|
| + return true;
|
| + }
|
| +
|
| + get buttonTooltip() {
|
| + return this._recording ? WebInspector.UIString('Stop recording heap profile') :
|
| + WebInspector.UIString('Start recording heap profile');
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + isInstantProfile() {
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + buttonClicked() {
|
| + return this._toggleRecording();
|
| + }
|
| +
|
| + _startRecordingProfile() {
|
| + if (this.profileBeingRecorded())
|
| + return;
|
| + this._addNewProfile();
|
| + var recordAllocationStacks = WebInspector.moduleSetting('recordAllocationStacks').get();
|
| + this.profileBeingRecorded().target().heapProfilerAgent().startTrackingHeapObjects(recordAllocationStacks);
|
| + }
|
| +
|
| + _addNewProfile() {
|
| + var target = WebInspector.context.flavor(WebInspector.Target);
|
| + this.setProfileBeingRecorded(new WebInspector.HeapProfileHeader(target, this, undefined));
|
| + this._profileSamples = new WebInspector.TrackingHeapSnapshotProfileType.Samples();
|
| + this._profileBeingRecorded._profileSamples = this._profileSamples;
|
| + this._recording = true;
|
| + this.addProfile(this._profileBeingRecorded);
|
| + this._profileBeingRecorded.updateStatus(WebInspector.UIString('Recording\u2026'));
|
| + this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.TrackingStarted);
|
| + }
|
| +
|
| + _stopRecordingProfile() {
|
| + this._profileBeingRecorded.updateStatus(WebInspector.UIString('Snapshotting\u2026'));
|
| + /**
|
| + * @param {?string} error
|
| + * @this {WebInspector.HeapSnapshotProfileType}
|
| + */
|
| + function didTakeHeapSnapshot(error) {
|
| + var profile = this.profileBeingRecorded();
|
| + if (!profile)
|
| + return;
|
| + profile._finishLoad();
|
| + this._profileSamples = null;
|
| + this.setProfileBeingRecorded(null);
|
| + this.dispatchEventToListeners(WebInspector.ProfileType.Events.ProfileComplete, profile);
|
| + }
|
|
|
| -WebInspector.TrackingHeapSnapshotProfileType.TypeId = "HEAP-RECORD";
|
| + this._profileBeingRecorded.target().heapProfilerAgent().stopTrackingHeapObjects(
|
| + true, didTakeHeapSnapshot.bind(this));
|
| + this._recording = false;
|
| + this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped);
|
| + }
|
| +
|
| + _toggleRecording() {
|
| + if (this._recording)
|
| + this._stopRecordingProfile();
|
| + else
|
| + this._startRecordingProfile();
|
| + return this._recording;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {string}
|
| + */
|
| + fileExtension() {
|
| + return '.heaptimeline';
|
| + }
|
| +
|
| + get treeItemTitle() {
|
| + return WebInspector.UIString('ALLOCATION TIMELINES');
|
| + }
|
| +
|
| + get description() {
|
| + return WebInspector.UIString(
|
| + 'Allocation timelines show memory allocations from your heap over time. Use this profile type to isolate memory leaks.');
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + _resetProfiles() {
|
| + var wasRecording = this._recording;
|
| + // Clear current profile to avoid stopping backend.
|
| + this.setProfileBeingRecorded(null);
|
| + super._resetProfiles();
|
| + this._profileSamples = null;
|
| + if (wasRecording)
|
| + this._addNewProfile();
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + profileBeingRecordedRemoved() {
|
| + this._stopRecordingProfile();
|
| + this._profileSamples = null;
|
| + }
|
| +};
|
|
|
| -WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate = "HeapStatsUpdate";
|
| -WebInspector.TrackingHeapSnapshotProfileType.TrackingStarted = "TrackingStarted";
|
| -WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped = "TrackingStopped";
|
| +WebInspector.TrackingHeapSnapshotProfileType.TypeId = 'HEAP-RECORD';
|
|
|
| +WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate = 'HeapStatsUpdate';
|
| +WebInspector.TrackingHeapSnapshotProfileType.TrackingStarted = 'TrackingStarted';
|
| +WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped = 'TrackingStopped';
|
|
|
| /**
|
| - * @constructor
|
| + * @unrestricted
|
| */
|
| -WebInspector.TrackingHeapSnapshotProfileType.Samples = function()
|
| -{
|
| +WebInspector.TrackingHeapSnapshotProfileType.Samples = class {
|
| + constructor() {
|
| /** @type {!Array.<number>} */
|
| this.sizes = [];
|
| /** @type {!Array.<number>} */
|
| @@ -1201,212 +1297,20 @@ WebInspector.TrackingHeapSnapshotProfileType.Samples = function()
|
| this.max = [];
|
| /** @type {number} */
|
| this.totalTime = 30000;
|
| -};
|
| -
|
| -WebInspector.TrackingHeapSnapshotProfileType.prototype = {
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.Target} target
|
| - */
|
| - targetAdded: function(target)
|
| - {
|
| - WebInspector.HeapSnapshotProfileType.prototype.targetAdded.call(this, target);
|
| - target.heapProfilerModel.addEventListener(WebInspector.HeapProfilerModel.Events.HeapStatsUpdate, this._heapStatsUpdate, this);
|
| - target.heapProfilerModel.addEventListener(WebInspector.HeapProfilerModel.Events.LastSeenObjectId, this._lastSeenObjectId, this);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.Target} target
|
| - */
|
| - targetRemoved: function(target)
|
| - {
|
| - WebInspector.HeapSnapshotProfileType.prototype.targetRemoved.call(this, target);
|
| - target.heapProfilerModel.removeEventListener(WebInspector.HeapProfilerModel.Events.HeapStatsUpdate, this._heapStatsUpdate, this);
|
| - target.heapProfilerModel.removeEventListener(WebInspector.HeapProfilerModel.Events.LastSeenObjectId, this._lastSeenObjectId, this);
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _heapStatsUpdate: function(event)
|
| - {
|
| - if (!this._profileSamples)
|
| - return;
|
| - var samples = /** @type {!Array.<number>} */ (event.data);
|
| - var index;
|
| - for (var i = 0; i < samples.length; i += 3) {
|
| - index = samples[i];
|
| - var size = samples[i + 2];
|
| - this._profileSamples.sizes[index] = size;
|
| - if (!this._profileSamples.max[index])
|
| - this._profileSamples.max[index] = size;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _lastSeenObjectId: function(event)
|
| - {
|
| - var profileSamples = this._profileSamples;
|
| - if (!profileSamples)
|
| - return;
|
| - var data = /** @type {{lastSeenObjectId: number, timestamp: number}} */ (event.data);
|
| - var currentIndex = Math.max(profileSamples.ids.length, profileSamples.max.length - 1);
|
| - profileSamples.ids[currentIndex] = data.lastSeenObjectId;
|
| - if (!profileSamples.max[currentIndex]) {
|
| - profileSamples.max[currentIndex] = 0;
|
| - profileSamples.sizes[currentIndex] = 0;
|
| - }
|
| - profileSamples.timestamps[currentIndex] = data.timestamp;
|
| - if (profileSamples.totalTime < data.timestamp - profileSamples.timestamps[0])
|
| - profileSamples.totalTime *= 2;
|
| - this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._profileSamples);
|
| - this._profileBeingRecorded.updateStatus(null, true);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - hasTemporaryView: function()
|
| - {
|
| - return true;
|
| - },
|
| -
|
| - get buttonTooltip()
|
| - {
|
| - return this._recording ? WebInspector.UIString("Stop recording heap profile") : WebInspector.UIString("Start recording heap profile");
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - isInstantProfile: function()
|
| - {
|
| - return false;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - buttonClicked: function()
|
| - {
|
| - return this._toggleRecording();
|
| - },
|
| -
|
| - _startRecordingProfile: function()
|
| - {
|
| - if (this.profileBeingRecorded())
|
| - return;
|
| - this._addNewProfile();
|
| - var recordAllocationStacks = WebInspector.moduleSetting("recordAllocationStacks").get();
|
| - this.profileBeingRecorded().target().heapProfilerAgent().startTrackingHeapObjects(recordAllocationStacks);
|
| - },
|
| -
|
| - _addNewProfile: function()
|
| - {
|
| - var target = WebInspector.context.flavor(WebInspector.Target);
|
| - this.setProfileBeingRecorded(new WebInspector.HeapProfileHeader(target, this, undefined));
|
| - this._profileSamples = new WebInspector.TrackingHeapSnapshotProfileType.Samples();
|
| - this._profileBeingRecorded._profileSamples = this._profileSamples;
|
| - this._recording = true;
|
| - this.addProfile(this._profileBeingRecorded);
|
| - this._profileBeingRecorded.updateStatus(WebInspector.UIString("Recording\u2026"));
|
| - this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.TrackingStarted);
|
| - },
|
| -
|
| - _stopRecordingProfile: function()
|
| - {
|
| - this._profileBeingRecorded.updateStatus(WebInspector.UIString("Snapshotting\u2026"));
|
| - /**
|
| - * @param {?string} error
|
| - * @this {WebInspector.HeapSnapshotProfileType}
|
| - */
|
| - function didTakeHeapSnapshot(error)
|
| - {
|
| - var profile = this.profileBeingRecorded();
|
| - if (!profile)
|
| - return;
|
| - profile._finishLoad();
|
| - this._profileSamples = null;
|
| - this.setProfileBeingRecorded(null);
|
| - this.dispatchEventToListeners(WebInspector.ProfileType.Events.ProfileComplete, profile);
|
| - }
|
| -
|
| - this._profileBeingRecorded.target().heapProfilerAgent().stopTrackingHeapObjects(true, didTakeHeapSnapshot.bind(this));
|
| - this._recording = false;
|
| - this.dispatchEventToListeners(WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped);
|
| - },
|
| -
|
| - _toggleRecording: function()
|
| - {
|
| - if (this._recording)
|
| - this._stopRecordingProfile();
|
| - else
|
| - this._startRecordingProfile();
|
| - return this._recording;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {string}
|
| - */
|
| - fileExtension: function()
|
| - {
|
| - return ".heaptimeline";
|
| - },
|
| -
|
| - get treeItemTitle()
|
| - {
|
| - return WebInspector.UIString("ALLOCATION TIMELINES");
|
| - },
|
| -
|
| - get description()
|
| - {
|
| - return WebInspector.UIString("Allocation timelines show memory allocations from your heap over time. Use this profile type to isolate memory leaks.");
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - _resetProfiles: function()
|
| - {
|
| - var wasRecording = this._recording;
|
| - // Clear current profile to avoid stopping backend.
|
| - this.setProfileBeingRecorded(null);
|
| - WebInspector.HeapSnapshotProfileType.prototype._resetProfiles.call(this);
|
| - this._profileSamples = null;
|
| - if (wasRecording)
|
| - this._addNewProfile();
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - profileBeingRecordedRemoved: function()
|
| - {
|
| - this._stopRecordingProfile();
|
| - this._profileSamples = null;
|
| - },
|
| -
|
| - __proto__: WebInspector.HeapSnapshotProfileType.prototype
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.ProfileHeader}
|
| - * @param {?WebInspector.Target} target
|
| - * @param {!WebInspector.HeapSnapshotProfileType} type
|
| - * @param {string=} title
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapProfileHeader = function(target, type, title)
|
| -{
|
| - WebInspector.ProfileHeader.call(this, target, type, title || WebInspector.UIString("Snapshot %d", type.nextProfileUid()));
|
| +WebInspector.HeapProfileHeader = class extends WebInspector.ProfileHeader {
|
| + /**
|
| + * @param {?WebInspector.Target} target
|
| + * @param {!WebInspector.HeapSnapshotProfileType} type
|
| + * @param {string=} title
|
| + */
|
| + constructor(target, type, title) {
|
| + super(target, type, title || WebInspector.UIString('Snapshot %d', type.nextProfileUid()));
|
| this.maxJSObjectId = -1;
|
| /**
|
| * @type {?WebInspector.HeapSnapshotWorkerProxy}
|
| @@ -1431,827 +1335,764 @@ WebInspector.HeapProfileHeader = function(target, type, title)
|
| * @param {function(!WebInspector.HeapSnapshotProxy)} fulfill
|
| * @this {WebInspector.HeapProfileHeader}
|
| */
|
| - function loadResolver(fulfill)
|
| - {
|
| - this._fulfillLoad = fulfill;
|
| + function loadResolver(fulfill) {
|
| + this._fulfillLoad = fulfill;
|
| }
|
| -};
|
| -
|
| -WebInspector.HeapProfileHeader.prototype = {
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.ProfileType.DataDisplayDelegate} dataDisplayDelegate
|
| - * @return {!WebInspector.ProfileSidebarTreeElement}
|
| - */
|
| - createSidebarTreeElement: function(dataDisplayDelegate)
|
| - {
|
| - return new WebInspector.ProfileSidebarTreeElement(dataDisplayDelegate, this, "heap-snapshot-sidebar-tree-item");
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.ProfileType.DataDisplayDelegate} dataDisplayDelegate
|
| - * @return {!WebInspector.HeapSnapshotView}
|
| - */
|
| - createView: function(dataDisplayDelegate)
|
| - {
|
| - return new WebInspector.HeapSnapshotView(dataDisplayDelegate, this);
|
| - },
|
| -
|
| - _prepareToLoad: function()
|
| - {
|
| - console.assert(!this._receiver, "Already loading");
|
| - this._setupWorker();
|
| - this.updateStatus(WebInspector.UIString("Loading\u2026"), true);
|
| - },
|
| -
|
| - _finishLoad: function()
|
| - {
|
| - if (!this._wasDisposed)
|
| - this._receiver.close();
|
| - if (this._bufferedWriter) {
|
| - this._bufferedWriter.finishWriting(this._didWriteToTempFile.bind(this));
|
| - this._bufferedWriter = null;
|
| - }
|
| - },
|
| -
|
| - _didWriteToTempFile: function(tempFile)
|
| - {
|
| - if (this._wasDisposed) {
|
| - if (tempFile)
|
| - tempFile.remove();
|
| - return;
|
| - }
|
| - this._tempFile = tempFile;
|
| - if (!tempFile)
|
| - this._failedToCreateTempFile = true;
|
| - if (this._onTempFileReady) {
|
| - this._onTempFileReady();
|
| - this._onTempFileReady = null;
|
| - }
|
| - },
|
| -
|
| - _setupWorker: function()
|
| - {
|
| - /**
|
| - * @this {WebInspector.HeapProfileHeader}
|
| - */
|
| - function setProfileWait(event)
|
| - {
|
| - this.updateStatus(null, event.data);
|
| - }
|
| - console.assert(!this._workerProxy, "HeapSnapshotWorkerProxy already exists");
|
| - this._workerProxy = new WebInspector.HeapSnapshotWorkerProxy(this._handleWorkerEvent.bind(this));
|
| - this._workerProxy.addEventListener("wait", setProfileWait, this);
|
| - this._receiver = this._workerProxy.createLoader(this.uid, this._snapshotReceived.bind(this));
|
| - },
|
| -
|
| - /**
|
| - * @param {string} eventName
|
| - * @param {*} data
|
| - */
|
| - _handleWorkerEvent: function(eventName, data)
|
| - {
|
| - if (WebInspector.HeapSnapshotProgressEvent.BrokenSnapshot === eventName) {
|
| - var error = /** @type {string} */ (data);
|
| - WebInspector.console.error(error);
|
| - return;
|
| - }
|
| -
|
| - if (WebInspector.HeapSnapshotProgressEvent.Update !== eventName)
|
| - return;
|
| - var subtitle = /** @type {string} */ (data);
|
| - this.updateStatus(subtitle);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - dispose: function()
|
| - {
|
| - if (this._workerProxy)
|
| - this._workerProxy.dispose();
|
| - this.removeTempFile();
|
| - this._wasDisposed = true;
|
| - },
|
| -
|
| - _didCompleteSnapshotTransfer: function()
|
| - {
|
| - if (!this._snapshotProxy)
|
| - return;
|
| - this.updateStatus(Number.bytesToString(this._snapshotProxy.totalSize), false);
|
| - },
|
| -
|
| - /**
|
| - * @param {string} chunk
|
| - */
|
| - transferChunk: function(chunk)
|
| - {
|
| - if (!this._bufferedWriter)
|
| - this._bufferedWriter = new WebInspector.DeferredTempFile("heap-profiler", String(this.uid));
|
| - this._bufferedWriter.write([chunk]);
|
| -
|
| - ++this._totalNumberOfChunks;
|
| - this._receiver.write(chunk);
|
| - },
|
| -
|
| - _snapshotReceived: function(snapshotProxy)
|
| - {
|
| - if (this._wasDisposed)
|
| - return;
|
| - this._receiver = null;
|
| - this._snapshotProxy = snapshotProxy;
|
| - this.maxJSObjectId = snapshotProxy.maxJSObjectId();
|
| - this._didCompleteSnapshotTransfer();
|
| - this._workerProxy.startCheckingForLongRunningCalls();
|
| - this.notifySnapshotReceived();
|
| - },
|
| -
|
| - notifySnapshotReceived: function()
|
| - {
|
| - this._fulfillLoad(this._snapshotProxy);
|
| - this._profileType._snapshotReceived(this);
|
| - if (this.canSaveToFile())
|
| - this.dispatchEventToListeners(WebInspector.ProfileHeader.Events.ProfileReceived);
|
| - },
|
| -
|
| - // Hook point for tests.
|
| - _wasShown: function()
|
| - {
|
| - },
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.ProfileType.DataDisplayDelegate} dataDisplayDelegate
|
| + * @return {!WebInspector.ProfileSidebarTreeElement}
|
| + */
|
| + createSidebarTreeElement(dataDisplayDelegate) {
|
| + return new WebInspector.ProfileSidebarTreeElement(dataDisplayDelegate, this, 'heap-snapshot-sidebar-tree-item');
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.ProfileType.DataDisplayDelegate} dataDisplayDelegate
|
| + * @return {!WebInspector.HeapSnapshotView}
|
| + */
|
| + createView(dataDisplayDelegate) {
|
| + return new WebInspector.HeapSnapshotView(dataDisplayDelegate, this);
|
| + }
|
| +
|
| + _prepareToLoad() {
|
| + console.assert(!this._receiver, 'Already loading');
|
| + this._setupWorker();
|
| + this.updateStatus(WebInspector.UIString('Loading\u2026'), true);
|
| + }
|
| +
|
| + _finishLoad() {
|
| + if (!this._wasDisposed)
|
| + this._receiver.close();
|
| + if (this._bufferedWriter) {
|
| + this._bufferedWriter.finishWriting(this._didWriteToTempFile.bind(this));
|
| + this._bufferedWriter = null;
|
| + }
|
| + }
|
|
|
| - /**
|
| - * @override
|
| - * @return {boolean}
|
| - */
|
| - canSaveToFile: function()
|
| - {
|
| - return !this.fromFile() && !!this._snapshotProxy;
|
| - },
|
| + _didWriteToTempFile(tempFile) {
|
| + if (this._wasDisposed) {
|
| + if (tempFile)
|
| + tempFile.remove();
|
| + return;
|
| + }
|
| + this._tempFile = tempFile;
|
| + if (!tempFile)
|
| + this._failedToCreateTempFile = true;
|
| + if (this._onTempFileReady) {
|
| + this._onTempFileReady();
|
| + this._onTempFileReady = null;
|
| + }
|
| + }
|
|
|
| + _setupWorker() {
|
| /**
|
| - * @override
|
| + * @this {WebInspector.HeapProfileHeader}
|
| */
|
| - saveToFile: function()
|
| - {
|
| - var fileOutputStream = new WebInspector.FileOutputStream();
|
| -
|
| - /**
|
| - * @param {boolean} accepted
|
| - * @this {WebInspector.HeapProfileHeader}
|
| - */
|
| - function onOpen(accepted)
|
| - {
|
| - if (!accepted)
|
| - return;
|
| - if (this._failedToCreateTempFile) {
|
| - WebInspector.console.error("Failed to open temp file with heap snapshot");
|
| - fileOutputStream.close();
|
| - } else if (this._tempFile) {
|
| - var delegate = new WebInspector.SaveSnapshotOutputStreamDelegate(this);
|
| - this._tempFile.copyToOutputStream(fileOutputStream, delegate);
|
| - } else {
|
| - this._onTempFileReady = onOpen.bind(this, accepted);
|
| - this._updateSaveProgress(0, 1);
|
| - }
|
| - }
|
| - this._fileName = this._fileName || "Heap-" + new Date().toISO8601Compact() + this._profileType.fileExtension();
|
| - fileOutputStream.open(this._fileName, onOpen.bind(this));
|
| - },
|
| -
|
| - _updateSaveProgress: function(value, total)
|
| - {
|
| - var percentValue = ((total ? (value / total) : 0) * 100).toFixed(0);
|
| - this.updateStatus(WebInspector.UIString("Saving\u2026 %d%%", percentValue));
|
| - },
|
| + function setProfileWait(event) {
|
| + this.updateStatus(null, event.data);
|
| + }
|
| + console.assert(!this._workerProxy, 'HeapSnapshotWorkerProxy already exists');
|
| + this._workerProxy = new WebInspector.HeapSnapshotWorkerProxy(this._handleWorkerEvent.bind(this));
|
| + this._workerProxy.addEventListener('wait', setProfileWait, this);
|
| + this._receiver = this._workerProxy.createLoader(this.uid, this._snapshotReceived.bind(this));
|
| + }
|
| +
|
| + /**
|
| + * @param {string} eventName
|
| + * @param {*} data
|
| + */
|
| + _handleWorkerEvent(eventName, data) {
|
| + if (WebInspector.HeapSnapshotProgressEvent.BrokenSnapshot === eventName) {
|
| + var error = /** @type {string} */ (data);
|
| + WebInspector.console.error(error);
|
| + return;
|
| + }
|
|
|
| - /**
|
| - * @override
|
| - * @param {!File} file
|
| + if (WebInspector.HeapSnapshotProgressEvent.Update !== eventName)
|
| + return;
|
| + var subtitle = /** @type {string} */ (data);
|
| + this.updateStatus(subtitle);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + dispose() {
|
| + if (this._workerProxy)
|
| + this._workerProxy.dispose();
|
| + this.removeTempFile();
|
| + this._wasDisposed = true;
|
| + }
|
| +
|
| + _didCompleteSnapshotTransfer() {
|
| + if (!this._snapshotProxy)
|
| + return;
|
| + this.updateStatus(Number.bytesToString(this._snapshotProxy.totalSize), false);
|
| + }
|
| +
|
| + /**
|
| + * @param {string} chunk
|
| + */
|
| + transferChunk(chunk) {
|
| + if (!this._bufferedWriter)
|
| + this._bufferedWriter = new WebInspector.DeferredTempFile('heap-profiler', String(this.uid));
|
| + this._bufferedWriter.write([chunk]);
|
| +
|
| + ++this._totalNumberOfChunks;
|
| + this._receiver.write(chunk);
|
| + }
|
| +
|
| + _snapshotReceived(snapshotProxy) {
|
| + if (this._wasDisposed)
|
| + return;
|
| + this._receiver = null;
|
| + this._snapshotProxy = snapshotProxy;
|
| + this.maxJSObjectId = snapshotProxy.maxJSObjectId();
|
| + this._didCompleteSnapshotTransfer();
|
| + this._workerProxy.startCheckingForLongRunningCalls();
|
| + this.notifySnapshotReceived();
|
| + }
|
| +
|
| + notifySnapshotReceived() {
|
| + this._fulfillLoad(this._snapshotProxy);
|
| + this._profileType._snapshotReceived(this);
|
| + if (this.canSaveToFile())
|
| + this.dispatchEventToListeners(WebInspector.ProfileHeader.Events.ProfileReceived);
|
| + }
|
| +
|
| + // Hook point for tests.
|
| + _wasShown() {
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + canSaveToFile() {
|
| + return !this.fromFile() && !!this._snapshotProxy;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + saveToFile() {
|
| + var fileOutputStream = new WebInspector.FileOutputStream();
|
| +
|
| + /**
|
| + * @param {boolean} accepted
|
| + * @this {WebInspector.HeapProfileHeader}
|
| */
|
| - loadFromFile: function(file)
|
| - {
|
| - this.updateStatus(WebInspector.UIString("Loading\u2026"), true);
|
| - this._setupWorker();
|
| - var delegate = new WebInspector.HeapSnapshotLoadFromFileDelegate(this);
|
| - var fileReader = this._createFileReader(file, delegate);
|
| - fileReader.start(this._receiver);
|
| - },
|
| -
|
| - _createFileReader: function(file, delegate)
|
| - {
|
| - return new WebInspector.ChunkedFileReader(file, 10000000, delegate);
|
| - },
|
| -
|
| - __proto__: WebInspector.ProfileHeader.prototype
|
| + function onOpen(accepted) {
|
| + if (!accepted)
|
| + return;
|
| + if (this._failedToCreateTempFile) {
|
| + WebInspector.console.error('Failed to open temp file with heap snapshot');
|
| + fileOutputStream.close();
|
| + } else if (this._tempFile) {
|
| + var delegate = new WebInspector.SaveSnapshotOutputStreamDelegate(this);
|
| + this._tempFile.copyToOutputStream(fileOutputStream, delegate);
|
| + } else {
|
| + this._onTempFileReady = onOpen.bind(this, accepted);
|
| + this._updateSaveProgress(0, 1);
|
| + }
|
| + }
|
| + this._fileName = this._fileName || 'Heap-' + new Date().toISO8601Compact() + this._profileType.fileExtension();
|
| + fileOutputStream.open(this._fileName, onOpen.bind(this));
|
| + }
|
| +
|
| + _updateSaveProgress(value, total) {
|
| + var percentValue = ((total ? (value / total) : 0) * 100).toFixed(0);
|
| + this.updateStatus(WebInspector.UIString('Saving\u2026 %d%%', percentValue));
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!File} file
|
| + */
|
| + loadFromFile(file) {
|
| + this.updateStatus(WebInspector.UIString('Loading\u2026'), true);
|
| + this._setupWorker();
|
| + var delegate = new WebInspector.HeapSnapshotLoadFromFileDelegate(this);
|
| + var fileReader = this._createFileReader(file, delegate);
|
| + fileReader.start(this._receiver);
|
| + }
|
| +
|
| + _createFileReader(file, delegate) {
|
| + return new WebInspector.ChunkedFileReader(file, 10000000, delegate);
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| * @implements {WebInspector.OutputStreamDelegate}
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapSnapshotLoadFromFileDelegate = function(snapshotHeader)
|
| -{
|
| +WebInspector.HeapSnapshotLoadFromFileDelegate = class {
|
| + constructor(snapshotHeader) {
|
| this._snapshotHeader = snapshotHeader;
|
| -};
|
| -
|
| -WebInspector.HeapSnapshotLoadFromFileDelegate.prototype = {
|
| - /**
|
| - * @override
|
| - */
|
| - onTransferStarted: function()
|
| - {
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.ChunkedReader} reader
|
| - */
|
| - onChunkTransferred: function(reader)
|
| - {
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - onTransferFinished: function()
|
| - {
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.ChunkedReader} reader
|
| - * @param {!Event} e
|
| - */
|
| - onError: function(reader, e)
|
| - {
|
| - var subtitle;
|
| - switch (e.target.error.code) {
|
| - case e.target.error.NOT_FOUND_ERR:
|
| - subtitle = WebInspector.UIString("'%s' not found.", reader.fileName());
|
| - break;
|
| - case e.target.error.NOT_READABLE_ERR:
|
| - subtitle = WebInspector.UIString("'%s' is not readable", reader.fileName());
|
| - break;
|
| - case e.target.error.ABORT_ERR:
|
| - return;
|
| - default:
|
| - subtitle = WebInspector.UIString("'%s' error %d", reader.fileName(), e.target.error.code);
|
| - }
|
| - this._snapshotHeader.updateStatus(subtitle);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + onTransferStarted() {
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.ChunkedReader} reader
|
| + */
|
| + onChunkTransferred(reader) {
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + onTransferFinished() {
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.ChunkedReader} reader
|
| + * @param {!Event} e
|
| + */
|
| + onError(reader, e) {
|
| + var subtitle;
|
| + switch (e.target.error.code) {
|
| + case e.target.error.NOT_FOUND_ERR:
|
| + subtitle = WebInspector.UIString('\'%s\' not found.', reader.fileName());
|
| + break;
|
| + case e.target.error.NOT_READABLE_ERR:
|
| + subtitle = WebInspector.UIString('\'%s\' is not readable', reader.fileName());
|
| + break;
|
| + case e.target.error.ABORT_ERR:
|
| + return;
|
| + default:
|
| + subtitle = WebInspector.UIString('\'%s\' error %d', reader.fileName(), e.target.error.code);
|
| }
|
| + this._snapshotHeader.updateStatus(subtitle);
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| * @implements {WebInspector.OutputStreamDelegate}
|
| - * @param {!WebInspector.HeapProfileHeader} profileHeader
|
| + * @unrestricted
|
| */
|
| -WebInspector.SaveSnapshotOutputStreamDelegate = function(profileHeader)
|
| -{
|
| +WebInspector.SaveSnapshotOutputStreamDelegate = class {
|
| + /**
|
| + * @param {!WebInspector.HeapProfileHeader} profileHeader
|
| + */
|
| + constructor(profileHeader) {
|
| this._profileHeader = profileHeader;
|
| -};
|
| -
|
| -WebInspector.SaveSnapshotOutputStreamDelegate.prototype = {
|
| - /**
|
| - * @override
|
| - */
|
| - onTransferStarted: function()
|
| - {
|
| - this._profileHeader._updateSaveProgress(0, 1);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - */
|
| - onTransferFinished: function()
|
| - {
|
| - this._profileHeader._didCompleteSnapshotTransfer();
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.ChunkedReader} reader
|
| - */
|
| - onChunkTransferred: function(reader)
|
| - {
|
| - this._profileHeader._updateSaveProgress(reader.loadedSize(), reader.fileSize());
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {!WebInspector.ChunkedReader} reader
|
| - * @param {!Event} event
|
| - */
|
| - onError: function(reader, event)
|
| - {
|
| - WebInspector.console.error("Failed to read heap snapshot from temp file: " + /** @type {!ErrorEvent} */ (event).message);
|
| - this.onTransferFinished();
|
| - }
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + onTransferStarted() {
|
| + this._profileHeader._updateSaveProgress(0, 1);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + onTransferFinished() {
|
| + this._profileHeader._didCompleteSnapshotTransfer();
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.ChunkedReader} reader
|
| + */
|
| + onChunkTransferred(reader) {
|
| + this._profileHeader._updateSaveProgress(reader.loadedSize(), reader.fileSize());
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.ChunkedReader} reader
|
| + * @param {!Event} event
|
| + */
|
| + onError(reader, event) {
|
| + WebInspector.console.error(
|
| + 'Failed to read heap snapshot from temp file: ' + /** @type {!ErrorEvent} */ (event).message);
|
| + this.onTransferFinished();
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.VBox}
|
| - * @param {!WebInspector.HeapProfileHeader} heapProfileHeader
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapTrackingOverviewGrid = function(heapProfileHeader)
|
| -{
|
| - WebInspector.VBox.call(this);
|
| - this.element.id = "heap-recording-view";
|
| - this.element.classList.add("heap-tracking-overview");
|
| -
|
| - this._overviewContainer = this.element.createChild("div", "heap-overview-container");
|
| - this._overviewGrid = new WebInspector.OverviewGrid("heap-recording");
|
| - this._overviewGrid.element.classList.add("fill");
|
| -
|
| - this._overviewCanvas = this._overviewContainer.createChild("canvas", "heap-recording-overview-canvas");
|
| +WebInspector.HeapTrackingOverviewGrid = class extends WebInspector.VBox {
|
| + /**
|
| + * @param {!WebInspector.HeapProfileHeader} heapProfileHeader
|
| + */
|
| + constructor(heapProfileHeader) {
|
| + super();
|
| + this.element.id = 'heap-recording-view';
|
| + this.element.classList.add('heap-tracking-overview');
|
| +
|
| + this._overviewContainer = this.element.createChild('div', 'heap-overview-container');
|
| + this._overviewGrid = new WebInspector.OverviewGrid('heap-recording');
|
| + this._overviewGrid.element.classList.add('fill');
|
| +
|
| + this._overviewCanvas = this._overviewContainer.createChild('canvas', 'heap-recording-overview-canvas');
|
| this._overviewContainer.appendChild(this._overviewGrid.element);
|
| this._overviewCalculator = new WebInspector.HeapTrackingOverviewGrid.OverviewCalculator();
|
| this._overviewGrid.addEventListener(WebInspector.OverviewGrid.Events.WindowChanged, this._onWindowChanged, this);
|
|
|
| - this._profileSamples = heapProfileHeader.fromFile() ? new WebInspector.TrackingHeapSnapshotProfileType.Samples() : heapProfileHeader._profileSamples;
|
| + this._profileSamples = heapProfileHeader.fromFile() ? new WebInspector.TrackingHeapSnapshotProfileType.Samples() :
|
| + heapProfileHeader._profileSamples;
|
| this._profileType = heapProfileHeader.profileType();
|
| if (!heapProfileHeader.fromFile() && heapProfileHeader.profileType().profileBeingRecorded() === heapProfileHeader) {
|
| - this._profileType.addEventListener(WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
|
| - this._profileType.addEventListener(WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
|
| + this._profileType.addEventListener(
|
| + WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
|
| + this._profileType.addEventListener(
|
| + WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
|
| }
|
| this._windowLeft = 0.0;
|
| this._windowRight = 1.0;
|
| this._overviewGrid.setWindow(this._windowLeft, this._windowRight);
|
| this._yScale = new WebInspector.HeapTrackingOverviewGrid.SmoothScale();
|
| this._xScale = new WebInspector.HeapTrackingOverviewGrid.SmoothScale();
|
| -};
|
| -
|
| -WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged = "IdsRangeChanged";
|
| -
|
| -WebInspector.HeapTrackingOverviewGrid.prototype = {
|
| - dispose: function()
|
| - {
|
| - this._onStopTracking();
|
| - },
|
| -
|
| - _onStopTracking: function()
|
| - {
|
| - this._profileType.removeEventListener(WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
|
| - this._profileType.removeEventListener(WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
|
| - },
|
| -
|
| - _onHeapStatsUpdate: function(event)
|
| - {
|
| - this._profileSamples = event.data;
|
| - this._scheduleUpdate();
|
| - },
|
| -
|
| - /**
|
| - * @param {?WebInspector.HeapSnapshotCommon.Samples} samples
|
| - */
|
| - _setSamples: function(samples)
|
| - {
|
| - if (!samples)
|
| - return;
|
| - console.assert(!this._profileSamples.timestamps.length, "Should only call this method when loading from file.");
|
| - console.assert(samples.timestamps.length);
|
| - this._profileSamples = new WebInspector.TrackingHeapSnapshotProfileType.Samples();
|
| - this._profileSamples.sizes = samples.sizes;
|
| - this._profileSamples.ids = samples.lastAssignedIds;
|
| - this._profileSamples.timestamps = samples.timestamps;
|
| - this._profileSamples.max = samples.sizes;
|
| - this._profileSamples.totalTime = /** @type{number} */(samples.timestamps.peekLast());
|
| - this.update();
|
| - },
|
| -
|
| - /**
|
| - * @param {number} width
|
| - * @param {number} height
|
| - */
|
| - _drawOverviewCanvas: function(width, height)
|
| - {
|
| - if (!this._profileSamples)
|
| - return;
|
| - var profileSamples = this._profileSamples;
|
| - var sizes = profileSamples.sizes;
|
| - var topSizes = profileSamples.max;
|
| - var timestamps = profileSamples.timestamps;
|
| - var startTime = timestamps[0];
|
| - var endTime = timestamps[timestamps.length - 1];
|
| -
|
| - var scaleFactor = this._xScale.nextScale(width / profileSamples.totalTime);
|
| - var maxSize = 0;
|
| - /**
|
| - * @param {!Array.<number>} sizes
|
| - * @param {function(number, number):void} callback
|
| - */
|
| - function aggregateAndCall(sizes, callback)
|
| - {
|
| - var size = 0;
|
| - var currentX = 0;
|
| - for (var i = 1; i < timestamps.length; ++i) {
|
| - var x = Math.floor((timestamps[i] - startTime) * scaleFactor);
|
| - if (x !== currentX) {
|
| - if (size)
|
| - callback(currentX, size);
|
| - size = 0;
|
| - currentX = x;
|
| - }
|
| - size += sizes[i];
|
| - }
|
| + }
|
| +
|
| + dispose() {
|
| + this._onStopTracking();
|
| + }
|
| +
|
| + _onStopTracking() {
|
| + this._profileType.removeEventListener(
|
| + WebInspector.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
|
| + this._profileType.removeEventListener(
|
| + WebInspector.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
|
| + }
|
| +
|
| + _onHeapStatsUpdate(event) {
|
| + this._profileSamples = event.data;
|
| + this._scheduleUpdate();
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.HeapSnapshotCommon.Samples} samples
|
| + */
|
| + _setSamples(samples) {
|
| + if (!samples)
|
| + return;
|
| + console.assert(!this._profileSamples.timestamps.length, 'Should only call this method when loading from file.');
|
| + console.assert(samples.timestamps.length);
|
| + this._profileSamples = new WebInspector.TrackingHeapSnapshotProfileType.Samples();
|
| + this._profileSamples.sizes = samples.sizes;
|
| + this._profileSamples.ids = samples.lastAssignedIds;
|
| + this._profileSamples.timestamps = samples.timestamps;
|
| + this._profileSamples.max = samples.sizes;
|
| + this._profileSamples.totalTime = /** @type{number} */ (samples.timestamps.peekLast());
|
| + this.update();
|
| + }
|
| +
|
| + /**
|
| + * @param {number} width
|
| + * @param {number} height
|
| + */
|
| + _drawOverviewCanvas(width, height) {
|
| + if (!this._profileSamples)
|
| + return;
|
| + var profileSamples = this._profileSamples;
|
| + var sizes = profileSamples.sizes;
|
| + var topSizes = profileSamples.max;
|
| + var timestamps = profileSamples.timestamps;
|
| + var startTime = timestamps[0];
|
| + var endTime = timestamps[timestamps.length - 1];
|
| +
|
| + var scaleFactor = this._xScale.nextScale(width / profileSamples.totalTime);
|
| + var maxSize = 0;
|
| + /**
|
| + * @param {!Array.<number>} sizes
|
| + * @param {function(number, number):void} callback
|
| + */
|
| + function aggregateAndCall(sizes, callback) {
|
| + var size = 0;
|
| + var currentX = 0;
|
| + for (var i = 1; i < timestamps.length; ++i) {
|
| + var x = Math.floor((timestamps[i] - startTime) * scaleFactor);
|
| + if (x !== currentX) {
|
| + if (size)
|
| callback(currentX, size);
|
| + size = 0;
|
| + currentX = x;
|
| }
|
| + size += sizes[i];
|
| + }
|
| + callback(currentX, size);
|
| + }
|
|
|
| - /**
|
| - * @param {number} x
|
| - * @param {number} size
|
| - */
|
| - function maxSizeCallback(x, size)
|
| - {
|
| - maxSize = Math.max(maxSize, size);
|
| - }
|
| -
|
| - aggregateAndCall(sizes, maxSizeCallback);
|
| -
|
| - var yScaleFactor = this._yScale.nextScale(maxSize ? height / (maxSize * 1.1) : 0.0);
|
| -
|
| - this._overviewCanvas.width = width * window.devicePixelRatio;
|
| - this._overviewCanvas.height = height * window.devicePixelRatio;
|
| - this._overviewCanvas.style.width = width + "px";
|
| - this._overviewCanvas.style.height = height + "px";
|
| -
|
| - var context = this._overviewCanvas.getContext("2d");
|
| - context.scale(window.devicePixelRatio, window.devicePixelRatio);
|
| -
|
| - context.beginPath();
|
| - context.lineWidth = 2;
|
| - context.strokeStyle = "rgba(192, 192, 192, 0.6)";
|
| - var currentX = (endTime - startTime) * scaleFactor;
|
| - context.moveTo(currentX, height - 1);
|
| - context.lineTo(currentX, 0);
|
| - context.stroke();
|
| - context.closePath();
|
| -
|
| - var gridY;
|
| - var gridValue;
|
| - var gridLabelHeight = 14;
|
| - if (yScaleFactor) {
|
| - const maxGridValue = (height - gridLabelHeight) / yScaleFactor;
|
| - // The round value calculation is a bit tricky, because
|
| - // it has a form k*10^n*1024^m, where k=[1,5], n=[0..3], m is an integer,
|
| - // e.g. a round value 10KB is 10240 bytes.
|
| - gridValue = Math.pow(1024, Math.floor(Math.log(maxGridValue) / Math.log(1024)));
|
| - gridValue *= Math.pow(10, Math.floor(Math.log(maxGridValue / gridValue) / Math.LN10));
|
| - if (gridValue * 5 <= maxGridValue)
|
| - gridValue *= 5;
|
| - gridY = Math.round(height - gridValue * yScaleFactor - 0.5) + 0.5;
|
| - context.beginPath();
|
| - context.lineWidth = 1;
|
| - context.strokeStyle = "rgba(0, 0, 0, 0.2)";
|
| - context.moveTo(0, gridY);
|
| - context.lineTo(width, gridY);
|
| - context.stroke();
|
| - context.closePath();
|
| - }
|
| + /**
|
| + * @param {number} x
|
| + * @param {number} size
|
| + */
|
| + function maxSizeCallback(x, size) {
|
| + maxSize = Math.max(maxSize, size);
|
| + }
|
|
|
| - /**
|
| - * @param {number} x
|
| - * @param {number} size
|
| - */
|
| - function drawBarCallback(x, size)
|
| - {
|
| - context.moveTo(x, height - 1);
|
| - context.lineTo(x, Math.round(height - size * yScaleFactor - 1));
|
| - }
|
| + aggregateAndCall(sizes, maxSizeCallback);
|
| +
|
| + var yScaleFactor = this._yScale.nextScale(maxSize ? height / (maxSize * 1.1) : 0.0);
|
| +
|
| + this._overviewCanvas.width = width * window.devicePixelRatio;
|
| + this._overviewCanvas.height = height * window.devicePixelRatio;
|
| + this._overviewCanvas.style.width = width + 'px';
|
| + this._overviewCanvas.style.height = height + 'px';
|
| +
|
| + var context = this._overviewCanvas.getContext('2d');
|
| + context.scale(window.devicePixelRatio, window.devicePixelRatio);
|
| +
|
| + context.beginPath();
|
| + context.lineWidth = 2;
|
| + context.strokeStyle = 'rgba(192, 192, 192, 0.6)';
|
| + var currentX = (endTime - startTime) * scaleFactor;
|
| + context.moveTo(currentX, height - 1);
|
| + context.lineTo(currentX, 0);
|
| + context.stroke();
|
| + context.closePath();
|
| +
|
| + var gridY;
|
| + var gridValue;
|
| + var gridLabelHeight = 14;
|
| + if (yScaleFactor) {
|
| + const maxGridValue = (height - gridLabelHeight) / yScaleFactor;
|
| + // The round value calculation is a bit tricky, because
|
| + // it has a form k*10^n*1024^m, where k=[1,5], n=[0..3], m is an integer,
|
| + // e.g. a round value 10KB is 10240 bytes.
|
| + gridValue = Math.pow(1024, Math.floor(Math.log(maxGridValue) / Math.log(1024)));
|
| + gridValue *= Math.pow(10, Math.floor(Math.log(maxGridValue / gridValue) / Math.LN10));
|
| + if (gridValue * 5 <= maxGridValue)
|
| + gridValue *= 5;
|
| + gridY = Math.round(height - gridValue * yScaleFactor - 0.5) + 0.5;
|
| + context.beginPath();
|
| + context.lineWidth = 1;
|
| + context.strokeStyle = 'rgba(0, 0, 0, 0.2)';
|
| + context.moveTo(0, gridY);
|
| + context.lineTo(width, gridY);
|
| + context.stroke();
|
| + context.closePath();
|
| + }
|
|
|
| - context.beginPath();
|
| - context.lineWidth = 2;
|
| - context.strokeStyle = "rgba(192, 192, 192, 0.6)";
|
| - aggregateAndCall(topSizes, drawBarCallback);
|
| - context.stroke();
|
| - context.closePath();
|
| -
|
| - context.beginPath();
|
| - context.lineWidth = 2;
|
| - context.strokeStyle = "rgba(0, 0, 192, 0.8)";
|
| - aggregateAndCall(sizes, drawBarCallback);
|
| - context.stroke();
|
| - context.closePath();
|
| -
|
| - if (gridValue) {
|
| - var label = Number.bytesToString(gridValue);
|
| - var labelPadding = 4;
|
| - var labelX = 0;
|
| - var labelY = gridY - 0.5;
|
| - var labelWidth = 2 * labelPadding + context.measureText(label).width;
|
| - context.beginPath();
|
| - context.textBaseline = "bottom";
|
| - context.font = "10px " + window.getComputedStyle(this.element, null).getPropertyValue("font-family");
|
| - context.fillStyle = "rgba(255, 255, 255, 0.75)";
|
| - context.fillRect(labelX, labelY - gridLabelHeight, labelWidth, gridLabelHeight);
|
| - context.fillStyle = "rgb(64, 64, 64)";
|
| - context.fillText(label, labelX + labelPadding, labelY);
|
| - context.fill();
|
| - context.closePath();
|
| - }
|
| - },
|
| -
|
| - onResize: function()
|
| - {
|
| - this._updateOverviewCanvas = true;
|
| - this._scheduleUpdate();
|
| - },
|
| -
|
| - _onWindowChanged: function()
|
| - {
|
| - if (!this._updateGridTimerId)
|
| - this._updateGridTimerId = setTimeout(this._updateGrid.bind(this), 10);
|
| - },
|
| -
|
| - _scheduleUpdate: function()
|
| - {
|
| - if (this._updateTimerId)
|
| - return;
|
| - this._updateTimerId = setTimeout(this.update.bind(this), 10);
|
| - },
|
| -
|
| - _updateBoundaries: function()
|
| - {
|
| - this._windowLeft = this._overviewGrid.windowLeft();
|
| - this._windowRight = this._overviewGrid.windowRight();
|
| - this._windowWidth = this._windowRight - this._windowLeft;
|
| - },
|
| -
|
| - update: function()
|
| - {
|
| - this._updateTimerId = null;
|
| - if (!this.isShowing())
|
| - return;
|
| - this._updateBoundaries();
|
| - this._overviewCalculator._updateBoundaries(this);
|
| - this._overviewGrid.updateDividers(this._overviewCalculator);
|
| - this._drawOverviewCanvas(this._overviewContainer.clientWidth, this._overviewContainer.clientHeight - 20);
|
| - },
|
| -
|
| - _updateGrid: function()
|
| - {
|
| - this._updateGridTimerId = 0;
|
| - this._updateBoundaries();
|
| - var ids = this._profileSamples.ids;
|
| - var timestamps = this._profileSamples.timestamps;
|
| - var sizes = this._profileSamples.sizes;
|
| - var startTime = timestamps[0];
|
| - var totalTime = this._profileSamples.totalTime;
|
| - var timeLeft = startTime + totalTime * this._windowLeft;
|
| - var timeRight = startTime + totalTime * this._windowRight;
|
| - var minId = 0;
|
| - var maxId = ids[ids.length - 1] + 1;
|
| - var size = 0;
|
| - for (var i = 0; i < timestamps.length; ++i) {
|
| - if (!timestamps[i])
|
| - continue;
|
| - if (timestamps[i] > timeRight)
|
| - break;
|
| - maxId = ids[i];
|
| - if (timestamps[i] < timeLeft) {
|
| - minId = ids[i];
|
| - continue;
|
| - }
|
| - size += sizes[i];
|
| - }
|
| + /**
|
| + * @param {number} x
|
| + * @param {number} size
|
| + */
|
| + function drawBarCallback(x, size) {
|
| + context.moveTo(x, height - 1);
|
| + context.lineTo(x, Math.round(height - size * yScaleFactor - 1));
|
| + }
|
|
|
| - this.dispatchEventToListeners(WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged, {minId: minId, maxId: maxId, size: size});
|
| - },
|
| + context.beginPath();
|
| + context.lineWidth = 2;
|
| + context.strokeStyle = 'rgba(192, 192, 192, 0.6)';
|
| + aggregateAndCall(topSizes, drawBarCallback);
|
| + context.stroke();
|
| + context.closePath();
|
| +
|
| + context.beginPath();
|
| + context.lineWidth = 2;
|
| + context.strokeStyle = 'rgba(0, 0, 192, 0.8)';
|
| + aggregateAndCall(sizes, drawBarCallback);
|
| + context.stroke();
|
| + context.closePath();
|
| +
|
| + if (gridValue) {
|
| + var label = Number.bytesToString(gridValue);
|
| + var labelPadding = 4;
|
| + var labelX = 0;
|
| + var labelY = gridY - 0.5;
|
| + var labelWidth = 2 * labelPadding + context.measureText(label).width;
|
| + context.beginPath();
|
| + context.textBaseline = 'bottom';
|
| + context.font = '10px ' + window.getComputedStyle(this.element, null).getPropertyValue('font-family');
|
| + context.fillStyle = 'rgba(255, 255, 255, 0.75)';
|
| + context.fillRect(labelX, labelY - gridLabelHeight, labelWidth, gridLabelHeight);
|
| + context.fillStyle = 'rgb(64, 64, 64)';
|
| + context.fillText(label, labelX + labelPadding, labelY);
|
| + context.fill();
|
| + context.closePath();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + onResize() {
|
| + this._updateOverviewCanvas = true;
|
| + this._scheduleUpdate();
|
| + }
|
| +
|
| + _onWindowChanged() {
|
| + if (!this._updateGridTimerId)
|
| + this._updateGridTimerId = setTimeout(this._updateGrid.bind(this), 10);
|
| + }
|
| +
|
| + _scheduleUpdate() {
|
| + if (this._updateTimerId)
|
| + return;
|
| + this._updateTimerId = setTimeout(this.update.bind(this), 10);
|
| + }
|
| +
|
| + _updateBoundaries() {
|
| + this._windowLeft = this._overviewGrid.windowLeft();
|
| + this._windowRight = this._overviewGrid.windowRight();
|
| + this._windowWidth = this._windowRight - this._windowLeft;
|
| + }
|
| +
|
| + update() {
|
| + this._updateTimerId = null;
|
| + if (!this.isShowing())
|
| + return;
|
| + this._updateBoundaries();
|
| + this._overviewCalculator._updateBoundaries(this);
|
| + this._overviewGrid.updateDividers(this._overviewCalculator);
|
| + this._drawOverviewCanvas(this._overviewContainer.clientWidth, this._overviewContainer.clientHeight - 20);
|
| + }
|
| +
|
| + _updateGrid() {
|
| + this._updateGridTimerId = 0;
|
| + this._updateBoundaries();
|
| + var ids = this._profileSamples.ids;
|
| + var timestamps = this._profileSamples.timestamps;
|
| + var sizes = this._profileSamples.sizes;
|
| + var startTime = timestamps[0];
|
| + var totalTime = this._profileSamples.totalTime;
|
| + var timeLeft = startTime + totalTime * this._windowLeft;
|
| + var timeRight = startTime + totalTime * this._windowRight;
|
| + var minId = 0;
|
| + var maxId = ids[ids.length - 1] + 1;
|
| + var size = 0;
|
| + for (var i = 0; i < timestamps.length; ++i) {
|
| + if (!timestamps[i])
|
| + continue;
|
| + if (timestamps[i] > timeRight)
|
| + break;
|
| + maxId = ids[i];
|
| + if (timestamps[i] < timeLeft) {
|
| + minId = ids[i];
|
| + continue;
|
| + }
|
| + size += sizes[i];
|
| + }
|
|
|
| - __proto__: WebInspector.VBox.prototype
|
| + this.dispatchEventToListeners(
|
| + WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged, {minId: minId, maxId: maxId, size: size});
|
| + }
|
| };
|
|
|
| +WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged = 'IdsRangeChanged';
|
|
|
| /**
|
| - * @constructor
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapTrackingOverviewGrid.SmoothScale = function()
|
| -{
|
| +WebInspector.HeapTrackingOverviewGrid.SmoothScale = class {
|
| + constructor() {
|
| this._lastUpdate = 0;
|
| this._currentScale = 0.0;
|
| -};
|
| -
|
| -WebInspector.HeapTrackingOverviewGrid.SmoothScale.prototype = {
|
| - /**
|
| - * @param {number} target
|
| - * @return {number}
|
| - */
|
| - nextScale: function(target) {
|
| - target = target || this._currentScale;
|
| - if (this._currentScale) {
|
| - var now = Date.now();
|
| - var timeDeltaMs = now - this._lastUpdate;
|
| - this._lastUpdate = now;
|
| - var maxChangePerSec = 20;
|
| - var maxChangePerDelta = Math.pow(maxChangePerSec, timeDeltaMs / 1000);
|
| - var scaleChange = target / this._currentScale;
|
| - this._currentScale *= Number.constrain(scaleChange, 1 / maxChangePerDelta, maxChangePerDelta);
|
| - } else {
|
| - this._currentScale = target;
|
| - }
|
| - return this._currentScale;
|
| + }
|
| +
|
| + /**
|
| + * @param {number} target
|
| + * @return {number}
|
| + */
|
| + nextScale(target) {
|
| + target = target || this._currentScale;
|
| + if (this._currentScale) {
|
| + var now = Date.now();
|
| + var timeDeltaMs = now - this._lastUpdate;
|
| + this._lastUpdate = now;
|
| + var maxChangePerSec = 20;
|
| + var maxChangePerDelta = Math.pow(maxChangePerSec, timeDeltaMs / 1000);
|
| + var scaleChange = target / this._currentScale;
|
| + this._currentScale *= Number.constrain(scaleChange, 1 / maxChangePerDelta, maxChangePerDelta);
|
| + } else {
|
| + this._currentScale = target;
|
| }
|
| + return this._currentScale;
|
| + }
|
| };
|
|
|
| -
|
| /**
|
| - * @constructor
|
| * @implements {WebInspector.TimelineGrid.Calculator}
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapTrackingOverviewGrid.OverviewCalculator = function()
|
| -{
|
| -};
|
| -
|
| -WebInspector.HeapTrackingOverviewGrid.OverviewCalculator.prototype = {
|
| - /**
|
| - * @override
|
| - * @return {number}
|
| - */
|
| - paddingLeft: function()
|
| - {
|
| - return 0;
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.HeapTrackingOverviewGrid} chart
|
| - */
|
| - _updateBoundaries: function(chart)
|
| - {
|
| - this._minimumBoundaries = 0;
|
| - this._maximumBoundaries = chart._profileSamples.totalTime;
|
| - this._xScaleFactor = chart._overviewContainer.clientWidth / this._maximumBoundaries;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {number} time
|
| - * @return {number}
|
| - */
|
| - computePosition: function(time)
|
| - {
|
| - return (time - this._minimumBoundaries) * this._xScaleFactor;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {number} value
|
| - * @param {number=} precision
|
| - * @return {string}
|
| - */
|
| - formatValue: function(value, precision)
|
| - {
|
| - return Number.secondsToString(value / 1000, !!precision);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {number}
|
| - */
|
| - maximumBoundary: function()
|
| - {
|
| - return this._maximumBoundaries;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {number}
|
| - */
|
| - minimumBoundary: function()
|
| - {
|
| - return this._minimumBoundaries;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {number}
|
| - */
|
| - zeroTime: function()
|
| - {
|
| - return this._minimumBoundaries;
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @return {number}
|
| - */
|
| - boundarySpan: function()
|
| - {
|
| - return this._maximumBoundaries - this._minimumBoundaries;
|
| - }
|
| +WebInspector.HeapTrackingOverviewGrid.OverviewCalculator = class {
|
| + /**
|
| + * @override
|
| + * @return {number}
|
| + */
|
| + paddingLeft() {
|
| + return 0;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.HeapTrackingOverviewGrid} chart
|
| + */
|
| + _updateBoundaries(chart) {
|
| + this._minimumBoundaries = 0;
|
| + this._maximumBoundaries = chart._profileSamples.totalTime;
|
| + this._xScaleFactor = chart._overviewContainer.clientWidth / this._maximumBoundaries;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {number} time
|
| + * @return {number}
|
| + */
|
| + computePosition(time) {
|
| + return (time - this._minimumBoundaries) * this._xScaleFactor;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {number} value
|
| + * @param {number=} precision
|
| + * @return {string}
|
| + */
|
| + formatValue(value, precision) {
|
| + return Number.secondsToString(value / 1000, !!precision);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {number}
|
| + */
|
| + maximumBoundary() {
|
| + return this._maximumBoundaries;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {number}
|
| + */
|
| + minimumBoundary() {
|
| + return this._minimumBoundaries;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {number}
|
| + */
|
| + zeroTime() {
|
| + return this._minimumBoundaries;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {number}
|
| + */
|
| + boundarySpan() {
|
| + return this._maximumBoundaries - this._minimumBoundaries;
|
| + }
|
| };
|
|
|
| -
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.VBox}
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapSnapshotStatisticsView = function()
|
| -{
|
| - WebInspector.VBox.call(this);
|
| +WebInspector.HeapSnapshotStatisticsView = class extends WebInspector.VBox {
|
| + constructor() {
|
| + super();
|
| this.setMinimumSize(50, 25);
|
| this._pieChart = new WebInspector.PieChart(150, WebInspector.HeapSnapshotStatisticsView._valueFormatter, true);
|
| - this._pieChart.element.classList.add("heap-snapshot-stats-pie-chart");
|
| + this._pieChart.element.classList.add('heap-snapshot-stats-pie-chart');
|
| this.element.appendChild(this._pieChart.element);
|
| - this._labels = this.element.createChild("div", "heap-snapshot-stats-legend");
|
| + this._labels = this.element.createChild('div', 'heap-snapshot-stats-legend');
|
| + }
|
| +
|
| + /**
|
| + * @param {number} value
|
| + * @return {string}
|
| + */
|
| + static _valueFormatter(value) {
|
| + return WebInspector.UIString('%s KB', Number.withThousandsSeparator(Math.round(value / 1024)));
|
| + }
|
| +
|
| + /**
|
| + * @param {number} value
|
| + */
|
| + setTotal(value) {
|
| + this._pieChart.setTotal(value);
|
| + }
|
| +
|
| + /**
|
| + * @param {number} value
|
| + * @param {string} name
|
| + * @param {string=} color
|
| + */
|
| + addRecord(value, name, color) {
|
| + if (color)
|
| + this._pieChart.addSlice(value, color);
|
| +
|
| + var node = this._labels.createChild('div');
|
| + var swatchDiv = node.createChild('div', 'heap-snapshot-stats-swatch');
|
| + var nameDiv = node.createChild('div', 'heap-snapshot-stats-name');
|
| + var sizeDiv = node.createChild('div', 'heap-snapshot-stats-size');
|
| + if (color)
|
| + swatchDiv.style.backgroundColor = color;
|
| + else
|
| + swatchDiv.classList.add('heap-snapshot-stats-empty-swatch');
|
| + nameDiv.textContent = name;
|
| + sizeDiv.textContent = WebInspector.HeapSnapshotStatisticsView._valueFormatter(value);
|
| + }
|
| };
|
|
|
| -/**
|
| - * @param {number} value
|
| - * @return {string}
|
| - */
|
| -WebInspector.HeapSnapshotStatisticsView._valueFormatter = function(value)
|
| -{
|
| - return WebInspector.UIString("%s KB", Number.withThousandsSeparator(Math.round(value / 1024)));
|
| -};
|
| -
|
| -WebInspector.HeapSnapshotStatisticsView.prototype = {
|
| - /**
|
| - * @param {number} value
|
| - */
|
| - setTotal: function(value)
|
| - {
|
| - this._pieChart.setTotal(value);
|
| - },
|
| -
|
| - /**
|
| - * @param {number} value
|
| - * @param {string} name
|
| - * @param {string=} color
|
| - */
|
| - addRecord: function(value, name, color)
|
| - {
|
| - if (color)
|
| - this._pieChart.addSlice(value, color);
|
| -
|
| - var node = this._labels.createChild("div");
|
| - var swatchDiv = node.createChild("div", "heap-snapshot-stats-swatch");
|
| - var nameDiv = node.createChild("div", "heap-snapshot-stats-name");
|
| - var sizeDiv = node.createChild("div", "heap-snapshot-stats-size");
|
| - if (color)
|
| - swatchDiv.style.backgroundColor = color;
|
| - else
|
| - swatchDiv.classList.add("heap-snapshot-stats-empty-swatch");
|
| - nameDiv.textContent = name;
|
| - sizeDiv.textContent = WebInspector.HeapSnapshotStatisticsView._valueFormatter(value);
|
| - },
|
| -
|
| - __proto__: WebInspector.VBox.prototype
|
| -};
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.Widget}
|
| - * @param {?WebInspector.Target} target
|
| + * @unrestricted
|
| */
|
| -WebInspector.HeapAllocationStackView = function(target)
|
| -{
|
| - WebInspector.Widget.call(this);
|
| +WebInspector.HeapAllocationStackView = class extends WebInspector.Widget {
|
| + /**
|
| + * @param {?WebInspector.Target} target
|
| + */
|
| + constructor(target) {
|
| + super();
|
| this._target = target;
|
| this._linkifier = new WebInspector.Linkifier();
|
| -};
|
| -
|
| -WebInspector.HeapAllocationStackView.prototype = {
|
| - /**
|
| - * @param {!WebInspector.HeapSnapshotProxy} snapshot
|
| - * @param {number} snapshotNodeIndex
|
| - */
|
| - setAllocatedObject: function(snapshot, snapshotNodeIndex)
|
| - {
|
| - this.clear();
|
| - snapshot.allocationStack(snapshotNodeIndex, this._didReceiveAllocationStack.bind(this));
|
| - },
|
| -
|
| - clear: function()
|
| - {
|
| - this.element.removeChildren();
|
| - this._linkifier.reset();
|
| - },
|
| -
|
| - /**
|
| - * @param {?Array.<!WebInspector.HeapSnapshotCommon.AllocationStackFrame>} frames
|
| - */
|
| - _didReceiveAllocationStack: function(frames)
|
| - {
|
| - if (!frames) {
|
| - var stackDiv = this.element.createChild("div", "no-heap-allocation-stack");
|
| - stackDiv.createTextChild(WebInspector.UIString("Stack was not recorded for this object because it had been allocated before this profile recording started."));
|
| - return;
|
| - }
|
| -
|
| - var stackDiv = this.element.createChild("div", "heap-allocation-stack");
|
| - for (var i = 0; i < frames.length; i++) {
|
| - var frame = frames[i];
|
| - var frameDiv = stackDiv.createChild("div", "stack-frame");
|
| - var name = frameDiv.createChild("div");
|
| - name.textContent = WebInspector.beautifyFunctionName(frame.functionName);
|
| - if (frame.scriptId) {
|
| - var urlElement = this._linkifier.linkifyScriptLocation(this._target, String(frame.scriptId), frame.scriptName, frame.line - 1, frame.column - 1);
|
| - frameDiv.appendChild(urlElement);
|
| - }
|
| - }
|
| - },
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.HeapSnapshotProxy} snapshot
|
| + * @param {number} snapshotNodeIndex
|
| + */
|
| + setAllocatedObject(snapshot, snapshotNodeIndex) {
|
| + this.clear();
|
| + snapshot.allocationStack(snapshotNodeIndex, this._didReceiveAllocationStack.bind(this));
|
| + }
|
| +
|
| + clear() {
|
| + this.element.removeChildren();
|
| + this._linkifier.reset();
|
| + }
|
| +
|
| + /**
|
| + * @param {?Array.<!WebInspector.HeapSnapshotCommon.AllocationStackFrame>} frames
|
| + */
|
| + _didReceiveAllocationStack(frames) {
|
| + if (!frames) {
|
| + var stackDiv = this.element.createChild('div', 'no-heap-allocation-stack');
|
| + stackDiv.createTextChild(WebInspector.UIString(
|
| + 'Stack was not recorded for this object because it had been allocated before this profile recording started.'));
|
| + return;
|
| + }
|
|
|
| - __proto__: WebInspector.Widget.prototype
|
| + var stackDiv = this.element.createChild('div', 'heap-allocation-stack');
|
| + for (var i = 0; i < frames.length; i++) {
|
| + var frame = frames[i];
|
| + var frameDiv = stackDiv.createChild('div', 'stack-frame');
|
| + var name = frameDiv.createChild('div');
|
| + name.textContent = WebInspector.beautifyFunctionName(frame.functionName);
|
| + if (frame.scriptId) {
|
| + var urlElement = this._linkifier.linkifyScriptLocation(
|
| + this._target, String(frame.scriptId), frame.scriptName, frame.line - 1, frame.column - 1);
|
| + frameDiv.appendChild(urlElement);
|
| + }
|
| + }
|
| + }
|
| };
|
|
|