diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /devtools/client/performance/modules/marker-dom-utils.js | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'devtools/client/performance/modules/marker-dom-utils.js')
-rw-r--r-- | devtools/client/performance/modules/marker-dom-utils.js | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/devtools/client/performance/modules/marker-dom-utils.js b/devtools/client/performance/modules/marker-dom-utils.js new file mode 100644 index 000000000..006b13171 --- /dev/null +++ b/devtools/client/performance/modules/marker-dom-utils.js @@ -0,0 +1,257 @@ +/* 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/. */ +"use strict"; + +/** + * This file contains utilities for creating DOM nodes for markers + * to be displayed in the UI. + */ + +const { L10N, PREFS } = require("devtools/client/performance/modules/global"); +const { MarkerBlueprintUtils } = require("devtools/client/performance/modules/marker-blueprint-utils"); +const { getSourceNames } = require("devtools/client/shared/source-utils"); + +/** + * Utilites for creating elements for markers. + */ +exports.MarkerDOMUtils = { + /** + * Builds all the fields possible for the given marker. Returns an + * array of elements to be appended to a parent element. + * + * @param document doc + * @param object marker + * @return array<nsIDOMNode> + */ + buildFields: function (doc, marker) { + let fields = MarkerBlueprintUtils.getMarkerFields(marker); + return fields.map(({ label, value }) => this.buildNameValueLabel(doc, label, value)); + }, + + /** + * Builds the label representing the marker's type. + * + * @param document doc + * @param object marker + * @return nsIDOMNode + */ + buildTitle: function (doc, marker) { + let blueprint = MarkerBlueprintUtils.getBlueprintFor(marker); + + let hbox = doc.createElement("hbox"); + hbox.setAttribute("align", "center"); + + let bullet = doc.createElement("hbox"); + bullet.className = `marker-details-bullet marker-color-${blueprint.colorName}`; + + let title = MarkerBlueprintUtils.getMarkerLabel(marker); + let label = doc.createElement("label"); + label.className = "marker-details-type"; + label.setAttribute("value", title); + + hbox.appendChild(bullet); + hbox.appendChild(label); + + return hbox; + }, + + /** + * Builds the label representing the marker's duration. + * + * @param document doc + * @param object marker + * @return nsIDOMNode + */ + buildDuration: function (doc, marker) { + let label = L10N.getStr("marker.field.duration"); + let start = L10N.getFormatStrWithNumbers("timeline.tick", marker.start); + let end = L10N.getFormatStrWithNumbers("timeline.tick", marker.end); + let duration = L10N.getFormatStrWithNumbers("timeline.tick", + marker.end - marker.start); + + let el = this.buildNameValueLabel(doc, label, duration); + el.classList.add("marker-details-duration"); + el.setAttribute("tooltiptext", `${start} → ${end}`); + + return el; + }, + + /** + * Builds labels for name:value pairs. + * E.g. "Start: 100ms", "Duration: 200ms", ... + * + * @param document doc + * @param string field + * @param string value + * @return nsIDOMNode + */ + buildNameValueLabel: function (doc, field, value) { + let hbox = doc.createElement("hbox"); + hbox.className = "marker-details-labelcontainer"; + + let nameLabel = doc.createElement("label"); + nameLabel.className = "plain marker-details-name-label"; + nameLabel.setAttribute("value", field); + hbox.appendChild(nameLabel); + + let valueLabel = doc.createElement("label"); + valueLabel.className = "plain marker-details-value-label"; + valueLabel.setAttribute("value", value); + hbox.appendChild(valueLabel); + + return hbox; + }, + + /** + * Builds a stack trace in an element. + * + * @param document doc + * @param object params + * An options object with the following members: + * - string type: string identifier for type of stack ("stack", "startStack" + or "endStack" + * - number frameIndex: the index of the topmost stack frame + * - array frames: array of stack frames + */ + buildStackTrace: function (doc, { type, frameIndex, frames }) { + let container = doc.createElement("vbox"); + container.className = "marker-details-stack"; + container.setAttribute("type", type); + + let nameLabel = doc.createElement("label"); + nameLabel.className = "plain marker-details-name-label"; + nameLabel.setAttribute("value", L10N.getStr(`marker.field.${type}`)); + container.appendChild(nameLabel); + + // Workaround for profiles that have looping stack traces. See + // bug 1246555. + let wasAsyncParent = false; + let seen = new Set(); + + while (frameIndex > 0) { + if (seen.has(frameIndex)) { + break; + } + seen.add(frameIndex); + + let frame = frames[frameIndex]; + let url = frame.source; + let displayName = frame.functionDisplayName; + let line = frame.line; + + // If the previous frame had an async parent, then the async + // cause is in this frame and should be displayed. + if (wasAsyncParent) { + let asyncStr = L10N.getFormatStr("marker.field.asyncStack", frame.asyncCause); + let asyncBox = doc.createElement("hbox"); + let asyncLabel = doc.createElement("label"); + asyncLabel.className = "devtools-monospace"; + asyncLabel.setAttribute("value", asyncStr); + asyncBox.appendChild(asyncLabel); + container.appendChild(asyncBox); + wasAsyncParent = false; + } + + let hbox = doc.createElement("hbox"); + + if (displayName) { + let functionLabel = doc.createElement("label"); + functionLabel.className = "devtools-monospace"; + functionLabel.setAttribute("value", displayName); + hbox.appendChild(functionLabel); + } + + if (url) { + let linkNode = doc.createElement("a"); + linkNode.className = "waterfall-marker-location devtools-source-link"; + linkNode.href = url; + linkNode.draggable = false; + linkNode.setAttribute("title", url); + + let urlLabel = doc.createElement("label"); + urlLabel.className = "filename"; + urlLabel.setAttribute("value", getSourceNames(url).short); + linkNode.appendChild(urlLabel); + + let lineLabel = doc.createElement("label"); + lineLabel.className = "line-number"; + lineLabel.setAttribute("value", `:${line}`); + linkNode.appendChild(lineLabel); + + hbox.appendChild(linkNode); + + // Clicking here will bubble up to the parent, + // which handles the view source. + linkNode.setAttribute("data-action", JSON.stringify({ + url: url, + line: line, + action: "view-source" + })); + } + + if (!displayName && !url) { + let unknownLabel = doc.createElement("label"); + unknownLabel.setAttribute("value", L10N.getStr("marker.value.unknownFrame")); + hbox.appendChild(unknownLabel); + } + + container.appendChild(hbox); + + if (frame.asyncParent) { + frameIndex = frame.asyncParent; + wasAsyncParent = true; + } else { + frameIndex = frame.parent; + } + } + + return container; + }, + + /** + * Builds any custom fields specific to the marker. + * + * @param document doc + * @param object marker + * @param object options + * @return array<nsIDOMNode> + */ + buildCustom: function (doc, marker, options) { + let elements = []; + + if (options.allocations && shouldShowAllocationsTrigger(marker)) { + let hbox = doc.createElement("hbox"); + hbox.className = "marker-details-customcontainer"; + + let label = doc.createElement("label"); + label.className = "custom-button devtools-button"; + label.setAttribute("value", "Show allocation triggers"); + label.setAttribute("type", "show-allocations"); + label.setAttribute("data-action", JSON.stringify({ + endTime: marker.start, + action: "show-allocations" + })); + + hbox.appendChild(label); + elements.push(hbox); + } + + return elements; + }, +}; + +/** + * Takes a marker and determines if this marker should display + * the allocations trigger button. + * + * @param object marker + * @return boolean + */ +function shouldShowAllocationsTrigger(marker) { + if (marker.name == "GarbageCollection") { + let showTriggers = PREFS["show-triggers-for-gc-types"]; + return showTriggers.split(" ").indexOf(marker.causeName) !== -1; + } + return false; +} |