mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 920116 - Show full stack traces for console logged messages; r=robcee
This commit is contained in:
parent
51ed54dbb0
commit
c286e981b0
@ -870,7 +870,7 @@ Messages.Simple.prototype = Heritage.extend(Messages.BaseMessage.prototype,
|
||||
_renderBody: function()
|
||||
{
|
||||
let body = this.document.createElementNS(XHTML_NS, "span");
|
||||
body.className = "body devtools-monospace";
|
||||
body.className = "message-body-wrapper message-body devtools-monospace";
|
||||
|
||||
let anchor, container = body;
|
||||
if (this._link || this._linkCallback) {
|
||||
@ -1223,6 +1223,7 @@ Messages.ConsoleGeneric = function(packet)
|
||||
line: packet.lineNumber,
|
||||
},
|
||||
};
|
||||
|
||||
switch (packet.level) {
|
||||
case "count": {
|
||||
let counter = packet.counter, label = counter.label;
|
||||
@ -1239,12 +1240,30 @@ Messages.ConsoleGeneric = function(packet)
|
||||
|
||||
this._repeatID.consoleApiLevel = packet.level;
|
||||
this._repeatID.styles = packet.styles;
|
||||
this._stacktrace = this._repeatID.stacktrace = packet.stacktrace;
|
||||
this._styles = packet.styles || [];
|
||||
|
||||
this._onClickCollapsible = this._onClickCollapsible.bind(this);
|
||||
};
|
||||
|
||||
Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
{
|
||||
_styles: null,
|
||||
_stacktrace: null,
|
||||
|
||||
/**
|
||||
* Tells if the message can be expanded/collapsed.
|
||||
* @type boolean
|
||||
*/
|
||||
collapsible: false,
|
||||
|
||||
/**
|
||||
* Getter that tells if this message is collapsed - no details are shown.
|
||||
* @type boolean
|
||||
*/
|
||||
get collapsed() {
|
||||
return this.collapsible && this.element && !this.element.hasAttribute("open");
|
||||
},
|
||||
|
||||
_renderBodyPieceSeparator: function()
|
||||
{
|
||||
@ -1253,13 +1272,84 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
|
||||
render: function()
|
||||
{
|
||||
let lastStyle = null;
|
||||
let msg = this.document.createElementNS(XHTML_NS, "span");
|
||||
msg.className = "message-body devtools-monospace";
|
||||
|
||||
this._renderBodyPieces(msg);
|
||||
|
||||
let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
|
||||
let location = Messages.Simple.prototype._renderLocation.call(this);
|
||||
if (location) {
|
||||
location.target = "jsdebugger";
|
||||
}
|
||||
|
||||
let stack = null;
|
||||
let twisty = null;
|
||||
if (this._stacktrace && this._stacktrace.length > 0) {
|
||||
stack = new Widgets.Stacktrace(this, this._stacktrace).render().element;
|
||||
|
||||
twisty = this.document.createElementNS(XHTML_NS, "a");
|
||||
twisty.className = "theme-twisty";
|
||||
twisty.href = "#";
|
||||
twisty.title = l10n.getStr("messageToggleDetails");
|
||||
twisty.addEventListener("click", this._onClickCollapsible);
|
||||
}
|
||||
|
||||
let flex = this.document.createElementNS(XHTML_NS, "span");
|
||||
flex.className = "message-flex-body";
|
||||
|
||||
if (twisty) {
|
||||
flex.appendChild(twisty);
|
||||
}
|
||||
|
||||
flex.appendChild(msg);
|
||||
|
||||
if (repeatNode) {
|
||||
flex.appendChild(repeatNode);
|
||||
}
|
||||
if (location) {
|
||||
flex.appendChild(location);
|
||||
}
|
||||
|
||||
let result = this.document.createDocumentFragment();
|
||||
result.appendChild(flex);
|
||||
|
||||
if (stack) {
|
||||
result.appendChild(this.document.createTextNode("\n"));
|
||||
result.appendChild(stack);
|
||||
}
|
||||
|
||||
this._message = result;
|
||||
this._stacktrace = null;
|
||||
|
||||
Messages.Simple.prototype.render.call(this);
|
||||
|
||||
if (stack) {
|
||||
this.collapsible = true;
|
||||
this.element.setAttribute("collapsible", true);
|
||||
|
||||
let icon = this.element.querySelector(".icon");
|
||||
icon.addEventListener("click", this._onClickCollapsible);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_renderBody: function()
|
||||
{
|
||||
let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
|
||||
body.classList.remove("devtools-monospace", "message-body");
|
||||
return body;
|
||||
},
|
||||
|
||||
_renderBodyPieces: function(container)
|
||||
{
|
||||
let lastStyle = null;
|
||||
|
||||
for (let i = 0; i < this._messagePieces.length; i++) {
|
||||
let separator = i > 0 ? this._renderBodyPieceSeparator() : null;
|
||||
if (separator) {
|
||||
result.appendChild(separator);
|
||||
container.appendChild(separator);
|
||||
}
|
||||
|
||||
let piece = this._messagePieces[i];
|
||||
@ -1270,13 +1360,11 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
lastStyle = this.cleanupStyle(style);
|
||||
}
|
||||
|
||||
result.appendChild(this._renderBodyPiece(piece, lastStyle));
|
||||
container.appendChild(this._renderBodyPiece(piece, lastStyle));
|
||||
}
|
||||
|
||||
this._message = result;
|
||||
this._messagePieces = null;
|
||||
this._styles = null;
|
||||
return Messages.Simple.prototype.render.call(this);
|
||||
},
|
||||
|
||||
_renderBodyPiece: function(piece, style)
|
||||
@ -1298,6 +1386,41 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
return result;
|
||||
},
|
||||
|
||||
// no-op for the message location and .repeats elements.
|
||||
// |this.render()| handles customized message output.
|
||||
_renderLocation: function() { },
|
||||
_renderRepeatNode: function() { },
|
||||
|
||||
/**
|
||||
* Expand/collapse message details.
|
||||
*/
|
||||
toggleDetails: function()
|
||||
{
|
||||
let twisty = this.element.querySelector(".theme-twisty");
|
||||
if (this.element.hasAttribute("open")) {
|
||||
this.element.removeAttribute("open");
|
||||
twisty.removeAttribute("open");
|
||||
} else {
|
||||
this.element.setAttribute("open", true);
|
||||
twisty.setAttribute("open", true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The click event handler for the message expander arrow element. This method
|
||||
* toggles the display of message details.
|
||||
*
|
||||
* @private
|
||||
* @param nsIDOMEvent ev
|
||||
* The DOM event object.
|
||||
* @see this.toggleDetails()
|
||||
*/
|
||||
_onClickCollapsible: function(ev)
|
||||
{
|
||||
ev.preventDefault();
|
||||
this.toggleDetails();
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a style attribute value, return a cleaned up version of the string
|
||||
* such that:
|
||||
@ -1355,7 +1478,7 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
Messages.ConsoleTrace = function(packet)
|
||||
{
|
||||
let options = {
|
||||
className: "consoleTrace cm-s-mozilla",
|
||||
className: "cm-s-mozilla",
|
||||
timestamp: packet.timeStamp,
|
||||
category: "webdev",
|
||||
severity: CONSOLE_API_LEVELS_TO_SEVERITIES[packet.level],
|
||||
@ -1412,6 +1535,13 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function()
|
||||
{
|
||||
Messages.Simple.prototype.render.apply(this, arguments);
|
||||
this.element.setAttribute("open", true);
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the stack frames.
|
||||
*
|
||||
@ -1429,7 +1559,7 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
cmprop.textContent = "trace";
|
||||
|
||||
let title = this.document.createElementNS(XHTML_NS, "span");
|
||||
title.className = "title devtools-monospace";
|
||||
title.className = "message-body devtools-monospace";
|
||||
title.appendChild(cmvar);
|
||||
title.appendChild(this.document.createTextNode("."));
|
||||
title.appendChild(cmprop);
|
||||
@ -1443,7 +1573,8 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
|
||||
let widget = new Widgets.Stacktrace(this, this._stacktrace).render();
|
||||
|
||||
let body = this.document.createElementNS(XHTML_NS, "div");
|
||||
let body = this.document.createElementNS(XHTML_NS, "span");
|
||||
body.className = "message-flex-body";
|
||||
body.appendChild(title);
|
||||
if (repeatNode) {
|
||||
body.appendChild(repeatNode);
|
||||
@ -1463,7 +1594,7 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
_renderBody: function()
|
||||
{
|
||||
let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
|
||||
body.classList.remove("devtools-monospace");
|
||||
body.classList.remove("devtools-monospace", "message-body");
|
||||
return body;
|
||||
},
|
||||
|
||||
@ -2722,7 +2853,6 @@ Widgets.Stacktrace.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
|
||||
return elem;
|
||||
},
|
||||
|
||||
}); // Widgets.Stacktrace.prototype
|
||||
|
||||
|
||||
|
@ -113,6 +113,7 @@ support-files =
|
||||
test-bug-609872-cd-iframe-parent.html
|
||||
test-bug-609872-cd-iframe-child.html
|
||||
test-bug-989025-iframe-parent.html
|
||||
test-console-api-stackframe.html
|
||||
|
||||
[browser_bug664688_sandbox_update_after_navigation.js]
|
||||
[browser_bug_638949_copy_link_location.js]
|
||||
@ -283,3 +284,4 @@ run-if = os == "mac"
|
||||
[browser_webconsole_cd_iframe.js]
|
||||
[browser_webconsole_autocomplete_crossdomain_iframe.js]
|
||||
[browser_webconsole_console_custom_styles.js]
|
||||
[browser_webconsole_console_api_stackframe.js]
|
||||
|
@ -67,6 +67,7 @@ function onConsoleMessage(aResults) {
|
||||
|
||||
// Test that the "Copy Link Location" menu item is hidden for non-network
|
||||
// messages.
|
||||
message.scrollIntoView();
|
||||
waitForContextMenu(menu, message, () => {
|
||||
let isHidden = menu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isHidden, CONTEXT_MENU_ID + " is hidden");
|
||||
@ -107,6 +108,7 @@ function onNetworkMessage(aResults) {
|
||||
function testMenuWithNetActivity() {
|
||||
// Test that the "Copy Link Location" menu item is visible for network-related
|
||||
// messages.
|
||||
message.scrollIntoView();
|
||||
waitForContextMenu(menu, message, () => {
|
||||
let isVisible = !menu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isVisible, CONTEXT_MENU_ID + " is visible");
|
||||
|
@ -53,7 +53,7 @@ function checkMessages([result])
|
||||
if (msg) {
|
||||
ok(msg, "message element #" + m);
|
||||
|
||||
let clickable = msg.querySelector(".body a");
|
||||
let clickable = msg.querySelector(".message-body a");
|
||||
ok(clickable, "clickable object #" + m);
|
||||
|
||||
msg.scrollIntoView(false);
|
||||
|
@ -23,7 +23,7 @@ function test()
|
||||
ok(msg, "output message found");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
let body = msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(anchor, "object anchor");
|
||||
ok(body, "message body");
|
||||
ok(body.textContent.contains('testProp: "testValue"'), "message text check");
|
||||
@ -59,7 +59,7 @@ function test()
|
||||
msg = yield execute("window.location");
|
||||
ok(msg, "output message found");
|
||||
|
||||
body = msg.querySelector(".body");
|
||||
body = msg.querySelector(".message-body");
|
||||
ok(body, "message body");
|
||||
anchor = msg.querySelector("a");
|
||||
ok(anchor, "object anchor");
|
||||
|
@ -47,7 +47,7 @@ function onConsoleMessage(aResults)
|
||||
let msg = [...aResults[0].matched][0];
|
||||
ok(msg, "message element");
|
||||
|
||||
let body = msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(body, "message body");
|
||||
|
||||
let clickable = aResults[0].clickableElements[0];
|
||||
|
@ -25,7 +25,7 @@ function testInputFocus() {
|
||||
}],
|
||||
}).then(([result]) => {
|
||||
let msg = [...result.matched][0];
|
||||
let outputItem = msg.querySelector(".body");
|
||||
let outputItem = msg.querySelector(".message-body");
|
||||
ok(outputItem, "found a logged message");
|
||||
let inputNode = hud.jsterm.inputNode;
|
||||
ok(inputNode.getAttribute("focused"), "input node is focused, first");
|
||||
|
@ -34,7 +34,7 @@ function performTest(hud)
|
||||
}).then(([result]) => {
|
||||
let msg = [...result.matched][0];
|
||||
ok(msg, "message element");
|
||||
let body = msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(body, "message body");
|
||||
let clickable = result.clickableElements[0];
|
||||
ok(clickable, "the console.log() object anchor was found");
|
||||
|
@ -36,7 +36,7 @@ function tabLoad2(aEvent) {
|
||||
}],
|
||||
}).then(([result]) => {
|
||||
let msg = [...result.matched][0];
|
||||
outputItem = msg.querySelector(".body .url");
|
||||
outputItem = msg.querySelector(".message-body .url");
|
||||
ok(outputItem, "found a network message");
|
||||
document.addEventListener("popupshown", networkPanelShown, false);
|
||||
|
||||
@ -102,7 +102,7 @@ function networkPanelHidden(aEvent) {
|
||||
info("jsterm execute 'document' callback");
|
||||
|
||||
HUD.jsterm.once("variablesview-open", onVariablesViewOpen);
|
||||
let outputItem = msg.querySelector(".body a");
|
||||
let outputItem = msg.querySelector(".message-body a");
|
||||
ok(outputItem, "jsterm output message found");
|
||||
|
||||
// Send the mousedown and click events such that the property panel opens.
|
||||
|
@ -66,7 +66,7 @@ function consoleOpened(HUD) {
|
||||
|
||||
jsterm.execute("window._container", (msg) => {
|
||||
jsterm.once("variablesview-fetched", testVariablesView.bind(null, HUD));
|
||||
let anchor = msg.querySelector(".body a");
|
||||
let anchor = msg.querySelector(".message-body a");
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, HUD.iframeWindow);
|
||||
});
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ function testPropertyPanel()
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("document", (msg) => {
|
||||
jsterm.once("variablesview-fetched", onVariablesViewReady);
|
||||
let anchor = msg.querySelector(".body a");
|
||||
let anchor = msg.querySelector(".message-body a");
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, gHUD.iframeWindow);
|
||||
});
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ function onConsoleMessage(aResults) {
|
||||
let isDisabled = !controller || !controller.isCommandEnabled(COMMAND_NAME);
|
||||
ok(isDisabled, COMMAND_NAME + " should be disabled.");
|
||||
|
||||
outputNode.selectedItem.scrollIntoView();
|
||||
waitForContextMenu(contextMenu, outputNode.selectedItem, () => {
|
||||
let isHidden = contextMenu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isHidden, CONTEXT_MENU_ID + " should be hidden.");
|
||||
@ -117,6 +118,7 @@ function testOnNetActivity_contextmenu(msg) {
|
||||
outputNode.focus();
|
||||
HUD.ui.output.selectMessage(msg);
|
||||
|
||||
msg.scrollIntoView();
|
||||
waitForContextMenu(contextMenu, msg, () => {
|
||||
let isShown = !contextMenu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isShown, CONTEXT_MENU_ID + " should be shown.");
|
||||
|
@ -1,8 +1,12 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
*/
|
||||
|
||||
// Test that message source links for js errors and console API calls open in
|
||||
// the jsdebugger when clicked.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test" +
|
||||
"/test-bug-766001-js-console-links.html";
|
||||
@ -61,10 +65,8 @@ function test() {
|
||||
EventUtils.sendMouseEvent({ type: "click" }, node);
|
||||
});
|
||||
|
||||
yield hud.ui.once("source-in-debugger-opened", checkLine.bind(null, url, line));
|
||||
}
|
||||
yield hud.ui.once("source-in-debugger-opened");
|
||||
|
||||
function* checkLine(url, line) {
|
||||
let toolbox = yield gDevTools.getToolbox(hud.target);
|
||||
let {panelWin: { DebuggerView: view }} = toolbox.getPanel("jsdebugger");
|
||||
is(view.Sources.selectedValue, url, "expected source url");
|
||||
|
@ -0,0 +1,81 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the console API messages for console.error()/exception()/assert()
|
||||
// include a stackframe. See bug 920116.
|
||||
|
||||
function test() {
|
||||
let hud;
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-api-stackframe.html";
|
||||
const TEST_FILE = TEST_URI.substr(TEST_URI.lastIndexOf("/"));
|
||||
|
||||
Task.spawn(runner).then(finishTest);
|
||||
|
||||
function* runner() {
|
||||
const {tab} = yield loadTab(TEST_URI);
|
||||
hud = yield openConsole(tab);
|
||||
|
||||
const stack = [{
|
||||
file: TEST_FILE,
|
||||
fn: "thirdCall",
|
||||
line: /\b2[123]\b/, // 21,22,23
|
||||
}, {
|
||||
file: TEST_FILE,
|
||||
fn: "secondCall",
|
||||
line: 16,
|
||||
}, {
|
||||
file: TEST_FILE,
|
||||
fn: "firstCall",
|
||||
line: 12,
|
||||
}];
|
||||
|
||||
let results = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "foo-log",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
collapsible: false,
|
||||
}, {
|
||||
text: "foo-error",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
collapsible: true,
|
||||
stacktrace: stack,
|
||||
}, {
|
||||
text: "foo-exception",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
collapsible: true,
|
||||
stacktrace: stack,
|
||||
}, {
|
||||
text: "foo-assert",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
collapsible: true,
|
||||
stacktrace: stack,
|
||||
}],
|
||||
});
|
||||
|
||||
let elem = [...results[1].matched][0];
|
||||
ok(elem, "message element");
|
||||
|
||||
let msg = elem._messageObject;
|
||||
ok(msg, "message object");
|
||||
|
||||
ok(msg.collapsed, "message is collapsed");
|
||||
|
||||
msg.toggleDetails();
|
||||
|
||||
ok(!msg.collapsed, "message is not collapsed");
|
||||
|
||||
msg.toggleDetails();
|
||||
|
||||
ok(msg.collapsed, "message is collapsed");
|
||||
|
||||
yield closeConsole(tab);
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ function test() {
|
||||
let msg = [...result.matched][0];
|
||||
ok(msg, "message element");
|
||||
|
||||
let span = msg.querySelector(".body span[style]");
|
||||
let span = msg.querySelector(".message-body span[style]");
|
||||
ok(span, "span element");
|
||||
|
||||
info("span textContent is: " + span.textContent);
|
||||
|
@ -30,7 +30,7 @@ function checkResult(msg, desc) {
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
}).then(([result]) => {
|
||||
let node = [...result.matched][0].querySelector(".body");
|
||||
let node = [...result.matched][0].querySelector(".message-body");
|
||||
if (typeof msg == "string") {
|
||||
is(node.textContent.trim(), msg,
|
||||
"correct message shown for " + desc);
|
||||
|
@ -3,6 +3,8 @@
|
||||
* 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";
|
||||
|
||||
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
@ -882,6 +884,8 @@ function openDebugger(aOptions = {})
|
||||
* message.
|
||||
* - longString: boolean, set to |true} to match long strings in the
|
||||
* message.
|
||||
* - collapsible: boolean, set to |true| to match messages that can
|
||||
* be collapsed/expanded.
|
||||
* - type: match messages that are instances of the given object. For
|
||||
* example, you can point to Messages.NavigationMarker to match any
|
||||
* such message.
|
||||
@ -890,6 +894,8 @@ function openDebugger(aOptions = {})
|
||||
* - source: object of the shape { url, line }. This is used to
|
||||
* match the source URL and line number of the error message or
|
||||
* console API call.
|
||||
* - stacktrace: array of objects of the form { file, fn, line } that
|
||||
* can match frames in the stacktrace associated with the message.
|
||||
* - groupDepth: number used to check the depth of the message in
|
||||
* a group.
|
||||
* - url: URL to match for network requests.
|
||||
@ -918,7 +924,7 @@ function waitForMessages(aOptions)
|
||||
|
||||
function checkText(aRule, aText)
|
||||
{
|
||||
let result;
|
||||
let result = false;
|
||||
if (Array.isArray(aRule)) {
|
||||
result = aRule.every((s) => checkText(s, aText));
|
||||
}
|
||||
@ -928,6 +934,9 @@ function waitForMessages(aOptions)
|
||||
else if (aRule instanceof RegExp) {
|
||||
result = aRule.test(aText);
|
||||
}
|
||||
else {
|
||||
result = aRule == aText;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -940,41 +949,18 @@ function waitForMessages(aOptions)
|
||||
return false;
|
||||
}
|
||||
|
||||
let frame = aElement.querySelector(".stacktrace li:first-child");
|
||||
if (trace.file) {
|
||||
let file = frame.querySelector(".message-location").title;
|
||||
if (!checkText(trace.file, file)) {
|
||||
ok(false, "console.trace() message is missing the file name: " +
|
||||
trace.file);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (trace.fn) {
|
||||
let fn = frame.querySelector(".function").textContent;
|
||||
if (!checkText(trace.fn, fn)) {
|
||||
ok(false, "console.trace() message is missing the function name: " +
|
||||
trace.fn);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (trace.line) {
|
||||
let line = frame.querySelector(".message-location").sourceLine;
|
||||
if (!checkText(trace.line, line)) {
|
||||
ok(false, "console.trace() message is missing the line number: " +
|
||||
trace.line);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
aRule.category = CATEGORY_WEBDEV;
|
||||
aRule.severity = SEVERITY_LOG;
|
||||
aRule.type = Messages.ConsoleTrace;
|
||||
|
||||
if (!aRule.stacktrace && typeof trace == "object" && trace !== true) {
|
||||
if (Array.isArray(trace)) {
|
||||
aRule.stacktrace = trace;
|
||||
} else {
|
||||
aRule.stacktrace = [trace];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1058,6 +1044,66 @@ function waitForMessages(aOptions)
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkCollapsible(aRule, aElement)
|
||||
{
|
||||
let msg = aElement._messageObject;
|
||||
if (!msg || !!msg.collapsible != aRule.collapsible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkStacktrace(aRule, aElement)
|
||||
{
|
||||
let stack = aRule.stacktrace;
|
||||
let frames = aElement.querySelectorAll(".stacktrace > li");
|
||||
if (!frames.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
let frame = frames[i];
|
||||
let expected = stack[i];
|
||||
if (!frame) {
|
||||
ok(false, "expected frame #" + i + " but didnt find it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expected.file) {
|
||||
let file = frame.querySelector(".message-location").title;
|
||||
if (!checkText(expected.file, file)) {
|
||||
ok(false, "frame #" + i + " does not match file name: " +
|
||||
expected.file);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected.fn) {
|
||||
let fn = frame.querySelector(".function").textContent;
|
||||
if (!checkText(expected.fn, fn)) {
|
||||
ok(false, "frame #" + i + " does not match the function name: " +
|
||||
expected.fn);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected.line) {
|
||||
let line = frame.querySelector(".message-location").sourceLine;
|
||||
if (!checkText(expected.line, line)) {
|
||||
ok(false, "frame #" + i + " does not match the line number: " +
|
||||
expected.line);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkMessage(aRule, aElement)
|
||||
{
|
||||
let elemText = aElement.textContent;
|
||||
@ -1094,6 +1140,10 @@ function waitForMessages(aOptions)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("collapsible" in aRule && !checkCollapsible(aRule, aElement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
|
||||
aRule.consoleTimeEnd);
|
||||
|
||||
@ -1129,6 +1179,18 @@ function waitForMessages(aOptions)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aRule.text) {
|
||||
partialMatch = true;
|
||||
}
|
||||
|
||||
if (aRule.stacktrace && !checkStacktrace(aRule, aElement)) {
|
||||
if (partialMatch) {
|
||||
ok(false, "failed to match stacktrace for rule: " + displayRule(aRule));
|
||||
displayErrorContext(aRule, aElement);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aRule.category == CATEGORY_NETWORK && "url" in aRule &&
|
||||
!checkText(aRule.url, aElement.url)) {
|
||||
return false;
|
||||
@ -1166,7 +1228,7 @@ function waitForMessages(aOptions)
|
||||
}
|
||||
|
||||
if ("objects" in aRule) {
|
||||
let clickables = aElement.querySelectorAll(".body a");
|
||||
let clickables = aElement.querySelectorAll(".message-body a");
|
||||
if (aRule.objects != !!clickables[0]) {
|
||||
if (partialMatch) {
|
||||
is(!!clickables[0], aRule.objects,
|
||||
@ -1410,7 +1472,8 @@ function checkOutputForInputs(hud, inputTests)
|
||||
|
||||
function checkObjectClick(entry, msg)
|
||||
{
|
||||
let body = msg.querySelector(".body a") || msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body a") ||
|
||||
msg.querySelector(".message-body");
|
||||
ok(body, "the message body");
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
@ -3,6 +3,8 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
function onLoad123() {
|
||||
console.log("Blah Blah");
|
||||
}, false);
|
||||
}
|
||||
|
||||
window.addEventListener("load", onLoad123, false);
|
||||
|
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<!--
|
||||
- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<title>Test for bug 920116 - stacktraces for console API messages</title>
|
||||
<script>
|
||||
function firstCall() {
|
||||
secondCall();
|
||||
}
|
||||
|
||||
function secondCall() {
|
||||
thirdCall();
|
||||
}
|
||||
|
||||
function thirdCall() {
|
||||
console.log("foo-log");
|
||||
console.error("foo-error");
|
||||
console.exception("foo-exception");
|
||||
console.assert("red" == "blue", "foo-assert");
|
||||
}
|
||||
|
||||
window.onload = firstCall;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p>Hello world!</p>
|
||||
</body>
|
||||
</html>
|
@ -1373,7 +1373,7 @@ WebConsoleFrame.prototype = {
|
||||
aScriptError.timeStamp);
|
||||
|
||||
// Select the body of the message node that is displayed in the console
|
||||
let msgBody = node.getElementsByClassName("body")[0];
|
||||
let msgBody = node.getElementsByClassName("message-body")[0];
|
||||
// Add the more info link node to messages that belong to certain categories
|
||||
this.addMoreInfoLink(msgBody, aScriptError);
|
||||
|
||||
@ -2461,7 +2461,7 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
// Create the message body, which contains the actual text of the message.
|
||||
let bodyNode = this.document.createElementNS(XHTML_NS, "span");
|
||||
bodyNode.className = "body devtools-monospace";
|
||||
bodyNode.className = "message-body-wrapper message-body devtools-monospace";
|
||||
|
||||
// Store the body text, since it is needed later for the variables view.
|
||||
let body = aBody;
|
||||
@ -2608,7 +2608,9 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
locationNode.href = isScratchpad || !fullURL ? "#" : fullURL;
|
||||
locationNode.draggable = false;
|
||||
locationNode.target = aTarget;
|
||||
if (aTarget) {
|
||||
locationNode.target = aTarget;
|
||||
}
|
||||
locationNode.setAttribute("title", aSourceURL);
|
||||
locationNode.className = "message-location theme-link devtools-monospace";
|
||||
|
||||
|
@ -222,3 +222,8 @@ openNodeInInspector=Click to select the node in the inspector
|
||||
# LOCALIZATION NOTE (cdFunctionInvalidArgument): the text that is displayed when
|
||||
# cd() is invoked with an invalid argument.
|
||||
cdFunctionInvalidArgument=Cannot cd() to the given window. Invalid argument.
|
||||
|
||||
# LOCALIZATION NOTE (messageToggleDetails): the text that is displayed when
|
||||
# you hover the arrow for expanding/collapsing the message details. For
|
||||
# console.error() and other messages we show the stacktrace.
|
||||
messageToggleDetails=Show/hide message details.
|
||||
|
@ -38,10 +38,8 @@ a {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.message > .body {
|
||||
.message > .message-body-wrapper {
|
||||
flex: 1 1 100%;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
@ -71,7 +69,7 @@ a {
|
||||
align-self: flex-start;
|
||||
justify-content: flex-end;
|
||||
width: 10em;
|
||||
margin-top: 4px;
|
||||
margin: 3px 0;
|
||||
color: -moz-nativehyperlinktext;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
@ -92,6 +90,20 @@ a {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.message-flex-body {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.message-body {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.message-flex-body > .message-body {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.jsterm-input-container {
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
@ -153,6 +165,14 @@ a {
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
.theme-light .message[severity=error] {
|
||||
background-color: rgba(255, 150, 150, 0.3);
|
||||
}
|
||||
|
||||
.theme-dark .message[severity=error] {
|
||||
background-color: rgba(255, 100, 100, 0.3);
|
||||
}
|
||||
|
||||
.message[category=network] > .icon {
|
||||
-moz-border-start: solid #000 6px;
|
||||
}
|
||||
@ -161,7 +181,7 @@ a {
|
||||
background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 0, 16, 8, 8);
|
||||
}
|
||||
|
||||
.message[category=network] > .body {
|
||||
.message[category=network] > .message-body {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@ -284,7 +304,7 @@ a {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.inlined-variables-view .body {
|
||||
.inlined-variables-view .message-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@ -340,27 +360,35 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.consoleTrace .body > div {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.consoleTrace .title {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.stacktrace {
|
||||
display: none;
|
||||
list-style: none;
|
||||
padding: 0 1em 0 1.5em;
|
||||
margin: 0;
|
||||
margin: 5px 0 0 0;
|
||||
max-height: 10em;
|
||||
overflow-y: auto;
|
||||
|
||||
border: 1px solid rgba(128, 128, 128, .5);
|
||||
border: 1px solid rgb(200,200,200);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.theme-light .message[severity=error] .stacktrace {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.theme-dark .message[severity=error] .stacktrace {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.message[open] .stacktrace {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message .theme-twisty {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 2px 3px 0 0;
|
||||
}
|
||||
|
||||
.stacktrace li {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
|
Loading…
Reference in New Issue
Block a user