зеркало из https://github.com/mozilla/gecko-dev.git
Revert "Bug 1167006 - Refactor marker details to not handle stack traces explicitly, and move logic into marker utils. Separate out some source link styles. r=vp"
This reverts commit 411adbfe0ea2
This commit is contained in:
Родитель
531ac71b86
Коммит
2912d55a1d
|
@ -181,95 +181,4 @@ const DOM = exports.DOM = {
|
|||
hbox.appendChild(labelValue);
|
||||
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")
|
||||
* integer frameIndex - The index of the topmost stack frame.
|
||||
* array frames - Array of stack frames.
|
||||
* @return {Element}
|
||||
*/
|
||||
buildStackTrace: function (doc, { type, frameIndex, frames }) {
|
||||
let container = doc.createElement("vbox");
|
||||
let labelName = doc.createElement("label");
|
||||
labelName.className = "plain marker-details-labelname";
|
||||
labelName.setAttribute("value", L10N.getStr(`timeline.markerDetail.${type}`));
|
||||
container.appendChild(labelName);
|
||||
|
||||
let wasAsyncParent = false;
|
||||
while (frameIndex > 0) {
|
||||
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 asyncBox = doc.createElement("hbox");
|
||||
let asyncLabel = doc.createElement("label");
|
||||
asyncLabel.className = "devtools-monospace";
|
||||
asyncLabel.setAttribute("value", L10N.getFormatStr("timeline.markerDetail.asyncStack",
|
||||
frame.asyncCause));
|
||||
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 aNode = doc.createElement("a");
|
||||
aNode.className = "waterfall-marker-location devtools-source-link";
|
||||
aNode.href = url;
|
||||
aNode.draggable = false;
|
||||
aNode.setAttribute("title", url);
|
||||
|
||||
let urlNode = doc.createElement("label");
|
||||
urlNode.className = "filename";
|
||||
urlNode.setAttribute("value", WebConsoleUtils.Utils.abbreviateSourceURL(url));
|
||||
let lineNode = doc.createElement("label");
|
||||
lineNode.className = "line-number";
|
||||
lineNode.setAttribute("value", `:${line}`);
|
||||
|
||||
aNode.appendChild(urlNode);
|
||||
aNode.appendChild(lineNode);
|
||||
hbox.appendChild(aNode);
|
||||
|
||||
// Clicking here will bubble up to the parent,
|
||||
// which handles the view source
|
||||
aNode.setAttribute("data-action", JSON.stringify({
|
||||
url, line, action: "view-source"
|
||||
}));
|
||||
}
|
||||
|
||||
if (!displayName && !url) {
|
||||
let label = doc.createElement("label");
|
||||
label.setAttribute("value", L10N.getStr("timeline.markerDetail.unknownFrame"));
|
||||
hbox.appendChild(label);
|
||||
}
|
||||
|
||||
container.appendChild(hbox);
|
||||
|
||||
if (frame.asyncParent) {
|
||||
frameIndex = frame.asyncParent;
|
||||
wasAsyncParent = true;
|
||||
} else {
|
||||
frameIndex = frame.parent;
|
||||
}
|
||||
}
|
||||
|
||||
return container;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
let { Ci } = require("chrome");
|
||||
let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
|
||||
|
||||
/**
|
||||
* This file contains the rendering code for the marker sidebar.
|
||||
*/
|
||||
|
@ -29,12 +32,10 @@ loader.lazyRequireGetter(this, "MarkerUtils",
|
|||
*/
|
||||
function MarkerDetails(parent, splitter) {
|
||||
EventEmitter.decorate(this);
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this._document = parent.ownerDocument;
|
||||
this._parent = parent;
|
||||
this._splitter = splitter;
|
||||
this._splitter.addEventListener("mouseup", () => this.emit("resize"));
|
||||
this._parent.addEventListener("click", this._onClick);
|
||||
}
|
||||
|
||||
MarkerDetails.prototype = {
|
||||
|
@ -59,72 +60,121 @@ MarkerDetails.prototype = {
|
|||
*
|
||||
* @param object params
|
||||
* An options object holding:
|
||||
* toolbox - The toolbox.
|
||||
* marker - The marker to display.
|
||||
* frames - Array of stack frame information; see stack.js.
|
||||
*/
|
||||
render: function({ marker, frames }) {
|
||||
render: function({toolbox: toolbox, marker: marker, frames: frames}) {
|
||||
this.empty();
|
||||
|
||||
let elements = [];
|
||||
elements.push(MarkerUtils.DOM.buildTitle(this._document, marker));
|
||||
elements.push(MarkerUtils.DOM.buildDuration(this._document, marker));
|
||||
MarkerUtils.DOM.buildFields(this._document, marker).forEach(field => elements.push(field));
|
||||
// UI for any marker
|
||||
|
||||
let title = MarkerUtils.DOM.buildTitle(this._document, marker);
|
||||
let duration = MarkerUtils.DOM.buildDuration(this._document, marker);
|
||||
let fields = MarkerUtils.DOM.buildFields(this._document, marker);
|
||||
|
||||
this._parent.appendChild(title);
|
||||
this._parent.appendChild(duration);
|
||||
fields.forEach(field => this._parent.appendChild(field));
|
||||
|
||||
// Build a stack element -- and use the "startStack" label if
|
||||
// we have both a start and endStack.
|
||||
if (marker.stack) {
|
||||
let type = marker.endStack ? "startStack" : "stack";
|
||||
elements.push(MarkerUtils.DOM.buildStackTrace(this._document, {
|
||||
frameIndex: marker.stack, frames, type
|
||||
}));
|
||||
let property = "timeline.markerDetail.stack";
|
||||
if (marker.endStack) {
|
||||
property = "timeline.markerDetail.startStack";
|
||||
}
|
||||
this.renderStackTrace({toolbox: toolbox, parent: this._parent, property: property,
|
||||
frameIndex: marker.stack, frames: frames});
|
||||
}
|
||||
|
||||
if (marker.endStack) {
|
||||
elements.push(MarkerUtils.DOM.buildStackTrace(this._document, {
|
||||
frameIndex: marker.endStack, frames, type: "endStack"
|
||||
}));
|
||||
this.renderStackTrace({toolbox: toolbox, parent: this._parent, property: "timeline.markerDetail.endStack",
|
||||
frameIndex: marker.endStack, frames: frames});
|
||||
}
|
||||
|
||||
elements.forEach(el => this._parent.appendChild(el));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles clicking in the marker details view. Based on the target,
|
||||
* can handle different actions -- only supporting view source links
|
||||
* for the moment.
|
||||
* Render a stack trace.
|
||||
*
|
||||
* @param object params
|
||||
* An options object with the following members:
|
||||
* object toolbox - The toolbox.
|
||||
* nsIDOMNode parent - The parent node holding the view.
|
||||
* string property - String identifier for label's name.
|
||||
* integer frameIndex - The index of the topmost stack frame.
|
||||
* array frames - Array of stack frames.
|
||||
*/
|
||||
_onClick: function (e) {
|
||||
let data = findActionFromEvent(e.target);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
renderStackTrace: function({toolbox: toolbox, parent: parent,
|
||||
property: property, frameIndex: frameIndex,
|
||||
frames: frames}) {
|
||||
let labelName = this._document.createElement("label");
|
||||
labelName.className = "plain marker-details-labelname";
|
||||
labelName.setAttribute("value", L10N.getStr(property));
|
||||
parent.appendChild(labelName);
|
||||
|
||||
if (data.action === "view-source") {
|
||||
this.emit("view-source", data.url, data.line);
|
||||
let wasAsyncParent = false;
|
||||
while (frameIndex > 0) {
|
||||
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 asyncBox = this._document.createElement("hbox");
|
||||
let asyncLabel = this._document.createElement("label");
|
||||
asyncLabel.className = "devtools-monospace";
|
||||
asyncLabel.setAttribute("value", L10N.getFormatStr("timeline.markerDetail.asyncStack",
|
||||
frame.asyncCause));
|
||||
asyncBox.appendChild(asyncLabel);
|
||||
parent.appendChild(asyncBox);
|
||||
wasAsyncParent = false;
|
||||
}
|
||||
|
||||
let hbox = this._document.createElement("hbox");
|
||||
|
||||
if (displayName) {
|
||||
let functionLabel = this._document.createElement("label");
|
||||
functionLabel.className = "devtools-monospace";
|
||||
functionLabel.setAttribute("value", displayName);
|
||||
hbox.appendChild(functionLabel);
|
||||
}
|
||||
|
||||
if (url) {
|
||||
let aNode = this._document.createElement("a");
|
||||
aNode.className = "waterfall-marker-location theme-link devtools-monospace";
|
||||
aNode.href = url;
|
||||
aNode.draggable = false;
|
||||
aNode.setAttribute("title", url);
|
||||
|
||||
let text = WebConsoleUtils.abbreviateSourceURL(url) + ":" + line;
|
||||
let label = this._document.createElement("label");
|
||||
label.setAttribute("value", text);
|
||||
aNode.appendChild(label);
|
||||
hbox.appendChild(aNode);
|
||||
|
||||
aNode.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
this.emit("view-source", url, line);
|
||||
});
|
||||
}
|
||||
|
||||
if (!displayName && !url) {
|
||||
let label = this._document.createElement("label");
|
||||
label.setAttribute("value", L10N.getStr("timeline.markerDetail.unknownFrame"));
|
||||
hbox.appendChild(label);
|
||||
}
|
||||
|
||||
parent.appendChild(hbox);
|
||||
|
||||
if (frame.asyncParent) {
|
||||
frameIndex = frame.asyncParent;
|
||||
wasAsyncParent = true;
|
||||
} else {
|
||||
frameIndex = frame.parent;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Take an element from an event `target`, and ascend through
|
||||
* the DOM, looking for an element with a `data-action` attribute. Return
|
||||
* the parsed `data-action` value found, or null if none found before
|
||||
* reaching the parent `container`.
|
||||
*
|
||||
* @param {Element} target
|
||||
* @param {Element} container
|
||||
* @return {object?}
|
||||
*/
|
||||
function findActionFromEvent (target, container) {
|
||||
let el = target;
|
||||
let action;
|
||||
while (el !== container) {
|
||||
if (action = el.getAttribute("data-action")) {
|
||||
return JSON.parse(action);
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
exports.MarkerDetails = MarkerDetails;
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const MARKER_DETAILS_WIDTH = 300;
|
||||
|
||||
/**
|
||||
* Waterfall view containing the timeline markers, controlled by DetailsView.
|
||||
*/
|
||||
|
@ -26,9 +24,6 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
|||
initialize: function () {
|
||||
DetailsSubview.initialize.call(this);
|
||||
|
||||
// TODO bug 1167093 save the previously set width, and ensure minimum width
|
||||
$("#waterfall-details").setAttribute("width", MARKER_DETAILS_WIDTH);
|
||||
|
||||
this.waterfall = new Waterfall($("#waterfall-breakdown"), $("#waterfall-view"));
|
||||
this.details = new MarkerDetails($("#waterfall-details"), $("#waterfall-view > splitter"));
|
||||
|
||||
|
|
|
@ -6,17 +6,16 @@
|
|||
|
||||
:root {
|
||||
font: message-box;
|
||||
%ifdef XP_MACOSX
|
||||
--monospace-font-family: Menlo, monospace;
|
||||
%elifdef XP_WIN
|
||||
--monospace-font-family: Consolas, monospace;
|
||||
%else
|
||||
--monospace-font-family: monospace;
|
||||
%endif
|
||||
}
|
||||
|
||||
.devtools-monospace {
|
||||
font-family: var(--monospace-font-family);
|
||||
%ifdef XP_MACOSX
|
||||
font-family: Menlo, monospace;
|
||||
%elifdef XP_WIN
|
||||
font-family: Consolas, monospace;
|
||||
%else
|
||||
font-family: monospace;
|
||||
%endif
|
||||
%if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
|
||||
font-size: 80%;
|
||||
%endif
|
||||
|
@ -248,37 +247,3 @@
|
|||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Links to source code, like displaying `myfile.js:45` */
|
||||
|
||||
.devtools-source-link {
|
||||
font-family: var(--monospace-font-family);
|
||||
color: var(--theme-highlight-blue);
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-self: flex-start;
|
||||
text-decoration: none;
|
||||
font-size: 11px;
|
||||
width: 12em; /* probably should be changed for each tool */
|
||||
}
|
||||
|
||||
.devtools-source-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.devtools-source-link > .filename {
|
||||
text-overflow: ellipsis;
|
||||
text-align: end;
|
||||
overflow: hidden;
|
||||
margin: 2px 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.devtools-source-link > .line-number {
|
||||
flex: none;
|
||||
margin: 2px 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
%include toolbars.inc.css
|
||||
|
|
|
@ -457,6 +457,15 @@
|
|||
color: var(--theme-selection-color);
|
||||
}
|
||||
|
||||
.waterfall-marker-location {
|
||||
color: -moz-nativehyperlinktext;
|
||||
}
|
||||
|
||||
.waterfall-marker-location:hover,
|
||||
.waterfall-marker-location:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#waterfall-details {
|
||||
-moz-padding-start: 8px;
|
||||
-moz-padding-end: 8px;
|
||||
|
|
Загрузка…
Ссылка в новой задаче