Bug 1281732 - Part 6: Use StackTrace React component in webconsole, cleanup message-location r=linclark

This commit is contained in:
Jarda Snajdr 2016-06-29 04:06:00 +02:00
parent 2eeeda64b7
commit d095253488
3 changed files with 52 additions and 112 deletions

View File

@ -24,7 +24,6 @@ a {
.message {
display: flex;
flex: none;
padding: 0 7px;
width: 100%;
box-sizing: border-box;
@ -79,7 +78,8 @@ a {
}
.message > .message-body-wrapper {
flex: 1 1 100%;
flex: auto;
min-width: 0px;
margin: 3px;
}
@ -107,29 +107,22 @@ a {
}
.message-location {
display: flex;
flex: none;
align-self: flex-start;
justify-content: flex-end;
width: 10em;
margin-top: 3px;
color: -moz-nativehyperlinktext;
text-decoration: none;
max-width: 40%;
}
.stack-trace .frame-link-source,
.message-location .frame-link-source {
direction: rtl;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* More space for the location data for location URL */
.theme-firebug .message-location {
width: 13em;
}
.message-location:hover,
.message-location:focus {
text-decoration: underline;
}
.message-location > .frame-link .frame-link-source {
width: 10em;
.stack-trace .frame-link-function-display-name {
max-width: 50%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.message-flex-body {
@ -143,12 +136,7 @@ a {
.message-flex-body > .message-body {
display: block;
flex: 1 1 auto;
vertical-align: middle;
}
.message-flex-body > .message-location {
margin-top: 0;
flex: auto;
}
#output-wrapper {
@ -499,10 +487,8 @@ a {
.stacktrace {
display: none;
list-style: none;
padding: 0 1em 0 1.5em;
padding: 5px 10px;
margin: 5px 0 0 0;
max-height: 10em;
overflow-y: auto;
border: 1px solid var(--theme-splitter-color);
border-radius: 3px;
@ -531,16 +517,6 @@ a {
flex-shrink: 0;
}
.stacktrace li {
display: flex;
margin: 0;
}
.stacktrace .function {
display: block;
flex: 1 1 auto;
}
.cm-s-mozilla a[class] {
font-style: italic;
text-decoration: none;

View File

@ -3609,8 +3609,7 @@ Widgets.LongString.prototype = extend(Widgets.BaseWidget.prototype, {
* The stacktrace to display, array of frames as supplied by the server,
* over the remote protocol.
*/
Widgets.Stacktrace = function (message, stacktrace)
{
Widgets.Stacktrace = function (message, stacktrace) {
Widgets.BaseWidget.call(this, message);
this.stacktrace = stacktrace;
};
@ -3622,72 +3621,31 @@ Widgets.Stacktrace.prototype = extend(Widgets.BaseWidget.prototype, {
*/
stacktrace: null,
render: function ()
{
onViewSourceInDebugger(frame) {
this.output.openLocationInDebugger({
url: frame.source,
line: frame.line
});
},
render() {
if (this.element) {
return this;
}
let result = this.element = this.document.createElementNS(XHTML_NS, "ul");
let result = this.element = this.document.createElementNS(XHTML_NS, "div");
result.className = "stacktrace devtools-monospace";
if (this.stacktrace) {
for (let frame of this.stacktrace) {
result.appendChild(this._renderFrame(frame));
}
this.output.owner.ReactDOM.render(this.output.owner.StackTraceView({
stacktrace: this.stacktrace,
onViewSourceInDebugger: frame => this.onViewSourceInDebugger(frame)
}), result);
}
return this;
},
/**
* Render a frame object received from the server.
*
* @param object frame
* The stack frame to display. This object should have the following
* properties: functionName, filename and lineNumber.
* @return DOMElement
* The DOM element to display for the given frame.
*/
_renderFrame: function (frame)
{
let fn = this.document.createElementNS(XHTML_NS, "span");
fn.className = "function";
let asyncCause = "";
if (frame.asyncCause) {
asyncCause =
l10n.getFormatStr("stacktrace.asyncStack", [frame.asyncCause]) + " ";
}
if (frame.functionName) {
let span = this.document.createElementNS(XHTML_NS, "span");
span.className = "cm-variable";
span.textContent = asyncCause + frame.functionName;
fn.appendChild(span);
fn.appendChild(this.document.createTextNode("()"));
} else {
fn.classList.add("cm-comment");
fn.textContent = asyncCause + l10n.getStr("stacktrace.anonymousFunction");
}
let location = this.output.owner.createLocationNode({url: frame.filename,
line: frame.lineNumber});
// .devtools-monospace sets font-size to 80%, however .body already has
// .devtools-monospace. If we keep it here, the location would be rendered
// smaller.
location.classList.remove("devtools-monospace");
let elem = this.document.createElementNS(XHTML_NS, "li");
elem.appendChild(fn);
elem.appendChild(location);
elem.appendChild(this.document.createTextNode("\n"));
return elem;
},
}); // Widgets.Stacktrace.prototype
}
});
/**
* The table widget.

View File

@ -235,6 +235,7 @@ function WebConsoleFrame(webConsoleOwner) {
this.React = require("devtools/client/shared/vendor/react");
this.ReactDOM = require("devtools/client/shared/vendor/react-dom");
this.FrameView = this.React.createFactory(require("devtools/client/shared/components/frame"));
this.StackTraceView = this.React.createFactory(require("devtools/client/shared/components/stack-trace"));
this._telemetry = new Telemetry();
@ -2290,11 +2291,17 @@ WebConsoleFrame.prototype = {
* The message node you want to clean up.
*/
unmountMessage(node) {
// Select all `.message-location` within this node to ensure we get
// messages of stacktraces, which contain multiple location nodes.
for (let locationNode of node.querySelectorAll(".message-location")) {
// Unmount the Frame component with the message location
let locationNode = node.querySelector(".message-location");
if (locationNode) {
this.ReactDOM.unmountComponentAtNode(locationNode);
}
// Unmount the StackTrace component if present in the message
let stacktraceNode = node.querySelector(".stacktrace");
if (stacktraceNode) {
this.ReactDOM.unmountComponentAtNode(stacktraceNode);
}
},
/**
@ -2514,26 +2521,25 @@ WebConsoleFrame.prototype = {
* The new anchor element, ready to be added to the message node.
*/
createLocationNode: function ({url, line, column}) {
let locationNode = this.document.createElementNS(XHTML_NS, "div");
locationNode.className = "message-location devtools-monospace";
if (!url) {
url = "";
}
let fullURL = url.split(" -> ").pop();
let locationNode = this.document.createElementNS(XHTML_NS, "a");
locationNode.draggable = false;
locationNode.className = "message-location devtools-monospace";
// Make the location clickable.
let onClick = () => {
let category = locationNode.parentNode.category;
let category = locationNode.closest(".message").category;
let target = null;
if (category === CATEGORY_CSS) {
if (/^Scratchpad\/\d+$/.test(url)) {
target = "scratchpad";
} else if (category === CATEGORY_CSS) {
target = "styleeditor";
} else if (category === CATEGORY_JS || category === CATEGORY_WEBDEV) {
target = "jsdebugger";
} else if (/^Scratchpad\/\d+$/.test(url)) {
target = "scratchpad";
} else if (/\.js$/.test(fullURL)) {
// If it ends in .js, let's attempt to open in debugger
// anyway, as this falls back to normal view-source.
@ -2559,9 +2565,9 @@ WebConsoleFrame.prototype = {
frame: {
source: fullURL,
line,
column,
showEmptyPathAsHost: true,
column
},
showEmptyPathAsHost: true,
onClick,
}), locationNode);