diff options
Diffstat (limited to 'devtools/client/performance/views/details-memory-call-tree.js')
-rw-r--r-- | devtools/client/performance/views/details-memory-call-tree.js | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/devtools/client/performance/views/details-memory-call-tree.js b/devtools/client/performance/views/details-memory-call-tree.js new file mode 100644 index 000000000..883d92e63 --- /dev/null +++ b/devtools/client/performance/views/details-memory-call-tree.js @@ -0,0 +1,130 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* import-globals-from ../performance-controller.js */ +/* import-globals-from ../performance-view.js */ +/* globals DetailsSubview */ +"use strict"; + +/** + * CallTree view containing memory allocation sites, controlled by DetailsView. + */ +var MemoryCallTreeView = Heritage.extend(DetailsSubview, { + + rerenderPrefs: [ + "invert-call-tree" + ], + + // Units are in milliseconds. + rangeChangeDebounceTime: 100, + + /** + * Sets up the view with event binding. + */ + initialize: function () { + DetailsSubview.initialize.call(this); + + this._onLink = this._onLink.bind(this); + + this.container = $("#memory-calltree-view > .call-tree-cells-container"); + }, + + /** + * Unbinds events. + */ + destroy: function () { + DetailsSubview.destroy.call(this); + }, + + /** + * Method for handling all the set up for rendering a new call tree. + * + * @param object interval [optional] + * The { startTime, endTime }, in milliseconds. + */ + render: function (interval = {}) { + let options = { + invertTree: PerformanceController.getOption("invert-call-tree") + }; + let recording = PerformanceController.getCurrentRecording(); + let allocations = recording.getAllocations(); + let threadNode = this._prepareCallTree(allocations, interval, options); + this._populateCallTree(threadNode, options); + this.emit(EVENTS.UI_MEMORY_CALL_TREE_RENDERED); + }, + + /** + * Fired on the "link" event for the call tree in this container. + */ + _onLink: function (_, treeItem) { + let { url, line } = treeItem.frame.getInfo(); + gToolbox.viewSourceInDebugger(url, line).then(success => { + if (success) { + this.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER); + } else { + this.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER); + } + }); + }, + + /** + * Called when the recording is stopped and prepares data to + * populate the call tree. + */ + _prepareCallTree: function (allocations, { startTime, endTime }, options) { + let thread = RecordingUtils.getProfileThreadFromAllocations(allocations); + let { invertTree } = options; + + return new ThreadNode(thread, { startTime, endTime, invertTree }); + }, + + /** + * Renders the call tree. + */ + _populateCallTree: function (frameNode, options = {}) { + // If we have an empty profile (no samples), then don't invert the tree, as + // it would hide the root node and a completely blank call tree space can be + // mis-interpreted as an error. + let inverted = options.invertTree && frameNode.samples > 0; + + let root = new CallView({ + frame: frameNode, + inverted: inverted, + // Root nodes are hidden in inverted call trees. + hidden: inverted, + // Call trees should only auto-expand when not inverted. Passing undefined + // will default to the CALL_TREE_AUTO_EXPAND depth. + autoExpandDepth: inverted ? 0 : undefined, + // Some cells like the time duration and cost percentage don't make sense + // for a memory allocations call tree. + visibleCells: { + selfCount: true, + count: true, + selfSize: true, + size: true, + selfCountPercentage: true, + countPercentage: true, + selfSizePercentage: true, + sizePercentage: true, + function: true + } + }); + + // Bind events. + root.on("link", this._onLink); + + // Pipe "focus" events to the view, mostly for tests + root.on("focus", () => this.emit("focus")); + + // Clear out other call trees. + this.container.innerHTML = ""; + root.attachTo(this.container); + + // Memory allocation samples don't contain cateogry labels. + root.toggleCategories(false); + }, + + toString: () => "[object MemoryCallTreeView]" +}); + +EventEmitter.decorate(MemoryCallTreeView); |