mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 939783 - console.trace() group traces even if part of trace is different; r=robcee
This commit is contained in:
parent
2c23f853fb
commit
d4f799b2bc
@ -48,7 +48,7 @@ function testFocus(sw, hud) {
|
||||
function onMessage(event, messages) {
|
||||
let msg = [...messages][0];
|
||||
|
||||
var loc = msg.querySelector(".location");
|
||||
var loc = msg.querySelector(".message-location");
|
||||
ok(loc, "location element exists");
|
||||
is(loc.textContent.trim(), sw.Scratchpad.uniqueName + ":1",
|
||||
"location value is correct");
|
||||
|
@ -145,6 +145,18 @@ ConsoleOutput.prototype = {
|
||||
return this.owner.webConsoleClient;
|
||||
},
|
||||
|
||||
/**
|
||||
* Release an actor.
|
||||
*
|
||||
* @private
|
||||
* @param string actorId
|
||||
* The actor ID you want to release.
|
||||
*/
|
||||
_releaseObject: function(actorId)
|
||||
{
|
||||
this.owner._releaseObject(actorId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a message to output.
|
||||
*
|
||||
@ -847,7 +859,7 @@ Messages.Simple.prototype = Heritage.extend(Messages.BaseMessage.prototype,
|
||||
|
||||
let repeatNode = this.document.createElementNS(XHTML_NS, "span");
|
||||
repeatNode.setAttribute("value", "1");
|
||||
repeatNode.className = "repeats";
|
||||
repeatNode.className = "message-repeats";
|
||||
repeatNode.textContent = 1;
|
||||
repeatNode._uid = this.getRepeatID();
|
||||
return repeatNode;
|
||||
@ -1077,6 +1089,134 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
},
|
||||
}); // Messages.ConsoleGeneric.prototype
|
||||
|
||||
/**
|
||||
* The ConsoleTrace message is used for console.trace() calls.
|
||||
*
|
||||
* @constructor
|
||||
* @extends Messages.Simple
|
||||
* @param object packet
|
||||
* The Console API call packet received from the server.
|
||||
*/
|
||||
Messages.ConsoleTrace = function(packet)
|
||||
{
|
||||
let options = {
|
||||
className: "consoleTrace cm-s-mozilla",
|
||||
timestamp: packet.timeStamp,
|
||||
category: "webdev",
|
||||
severity: CONSOLE_API_LEVELS_TO_SEVERITIES[packet.level],
|
||||
private: packet.private,
|
||||
filterDuplicates: true,
|
||||
location: {
|
||||
url: packet.filename,
|
||||
line: packet.lineNumber,
|
||||
},
|
||||
};
|
||||
|
||||
this._renderStack = this._renderStack.bind(this);
|
||||
Messages.Simple.call(this, this._renderStack, options);
|
||||
|
||||
this._repeatID.consoleApiLevel = packet.level;
|
||||
this._stacktrace = this._repeatID.stacktrace = packet.stacktrace;
|
||||
this._arguments = packet.arguments;
|
||||
};
|
||||
|
||||
Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
{
|
||||
/**
|
||||
* Holds the stackframes received from the server.
|
||||
*
|
||||
* @private
|
||||
* @type array
|
||||
*/
|
||||
_stacktrace: null,
|
||||
|
||||
/**
|
||||
* Holds the arguments the content script passed to the console.trace()
|
||||
* method. This array is cleared when the message is initialized, and
|
||||
* associated actors are released.
|
||||
*
|
||||
* @private
|
||||
* @type array
|
||||
*/
|
||||
_arguments: null,
|
||||
|
||||
init: function()
|
||||
{
|
||||
let result = Messages.Simple.prototype.init.apply(this, arguments);
|
||||
|
||||
// We ignore console.trace() arguments. Release object actors.
|
||||
if (Array.isArray(this._arguments)) {
|
||||
for (let arg of this._arguments) {
|
||||
if (WebConsoleUtils.isActorGrip(arg)) {
|
||||
this.output._releaseObject(arg.actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._arguments = null;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the stack frames.
|
||||
*
|
||||
* @private
|
||||
* @return DOMElement
|
||||
*/
|
||||
_renderStack: function()
|
||||
{
|
||||
let cmvar = this.document.createElementNS(XHTML_NS, "span");
|
||||
cmvar.className = "cm-variable";
|
||||
cmvar.textContent = "console";
|
||||
|
||||
let cmprop = this.document.createElementNS(XHTML_NS, "span");
|
||||
cmprop.className = "cm-property";
|
||||
cmprop.textContent = "trace";
|
||||
|
||||
let title = this.document.createElementNS(XHTML_NS, "span");
|
||||
title.className = "title devtools-monospace";
|
||||
title.appendChild(cmvar);
|
||||
title.appendChild(this.document.createTextNode("."));
|
||||
title.appendChild(cmprop);
|
||||
title.appendChild(this.document.createTextNode("():"));
|
||||
|
||||
let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
|
||||
let location = Messages.Simple.prototype._renderLocation.call(this);
|
||||
if (location) {
|
||||
location.target = "jsdebugger";
|
||||
}
|
||||
|
||||
let widget = new Widgets.Stacktrace(this, this._stacktrace).render();
|
||||
|
||||
let body = this.document.createElementNS(XHTML_NS, "div");
|
||||
body.appendChild(title);
|
||||
if (repeatNode) {
|
||||
body.appendChild(repeatNode);
|
||||
}
|
||||
if (location) {
|
||||
body.appendChild(location);
|
||||
}
|
||||
body.appendChild(this.document.createTextNode("\n"));
|
||||
|
||||
let frag = this.document.createDocumentFragment();
|
||||
frag.appendChild(body);
|
||||
frag.appendChild(widget.element);
|
||||
|
||||
return frag;
|
||||
},
|
||||
|
||||
_renderBody: function()
|
||||
{
|
||||
let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
|
||||
body.classList.remove("devtools-monospace");
|
||||
return body;
|
||||
},
|
||||
|
||||
// no-op for the message location and .repeats elements.
|
||||
// |this._renderStack| handles customized message output.
|
||||
_renderLocation: function() { },
|
||||
_renderRepeatNode: function() { },
|
||||
}); // Messages.ConsoleTrace.prototype
|
||||
|
||||
let Widgets = {};
|
||||
|
||||
@ -1354,6 +1494,91 @@ Widgets.LongString.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
}); // Widgets.LongString.prototype
|
||||
|
||||
|
||||
/**
|
||||
* The stacktrace widget.
|
||||
*
|
||||
* @constructor
|
||||
* @extends Widgets.BaseWidget
|
||||
* @param object message
|
||||
* The owning message.
|
||||
* @param array stacktrace
|
||||
* The stacktrace to display, array of frames as supplied by the server,
|
||||
* over the remote protocol.
|
||||
*/
|
||||
Widgets.Stacktrace = function(message, stacktrace)
|
||||
{
|
||||
Widgets.BaseWidget.call(this, message);
|
||||
this.stacktrace = stacktrace;
|
||||
};
|
||||
|
||||
Widgets.Stacktrace.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
{
|
||||
/**
|
||||
* The stackframes received from the server.
|
||||
* @type array
|
||||
*/
|
||||
stacktrace: null,
|
||||
|
||||
render: function()
|
||||
{
|
||||
if (this.element) {
|
||||
return this;
|
||||
}
|
||||
|
||||
let result = this.element = this.document.createElementNS(XHTML_NS, "ul");
|
||||
result.className = "stacktrace devtools-monospace";
|
||||
|
||||
for (let frame of this.stacktrace) {
|
||||
result.appendChild(this._renderFrame(frame));
|
||||
}
|
||||
|
||||
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";
|
||||
if (frame.functionName) {
|
||||
let span = this.document.createElementNS(XHTML_NS, "span");
|
||||
span.className = "cm-variable";
|
||||
span.textContent = frame.functionName;
|
||||
fn.appendChild(span);
|
||||
fn.appendChild(this.document.createTextNode("()"));
|
||||
} else {
|
||||
fn.classList.add("cm-comment");
|
||||
fn.textContent = l10n.getStr("stacktrace.anonymousFunction");
|
||||
}
|
||||
|
||||
let location = this.output.owner.createLocationNode(frame.filename,
|
||||
frame.lineNumber,
|
||||
"jsdebugger");
|
||||
|
||||
// .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
|
||||
|
||||
|
||||
function gSequenceId()
|
||||
{
|
||||
return gSequenceId.n++;
|
||||
|
@ -103,6 +103,7 @@ support-files =
|
||||
test-bug_923281_console_log_filter.html
|
||||
test-bug_923281_test1.js
|
||||
test-bug_923281_test2.js
|
||||
test-bug_939783_console_trace_duplicates.html
|
||||
|
||||
[browser_bug664688_sandbox_update_after_navigation.js]
|
||||
[browser_bug_638949_copy_link_location.js]
|
||||
@ -257,3 +258,4 @@ run-if = os == "mac"
|
||||
[browser_webconsole_output_03.js]
|
||||
[browser_webconsole_output_04.js]
|
||||
[browser_webconsole_output_events.js]
|
||||
[browser_webconsole_console_trace_duplicates.js]
|
||||
|
@ -70,7 +70,7 @@ function test()
|
||||
{
|
||||
let msg = [...results[0].matched][0];
|
||||
ok(msg, "message element found");
|
||||
let locationNode = msg.querySelector(".location");
|
||||
let locationNode = msg.querySelector(".message-location");
|
||||
ok(locationNode, "message location element found");
|
||||
|
||||
let title = locationNode.getAttribute("title");
|
||||
|
@ -61,7 +61,7 @@ function test()
|
||||
|
||||
let msg = [...results[0].matched][0];
|
||||
ok(msg, "message element found for: " + result.text);
|
||||
let locationNode = msg.querySelector(".location");
|
||||
let locationNode = msg.querySelector(".message-location");
|
||||
ok(locationNode, "message location element found");
|
||||
|
||||
EventUtils.synthesizeMouse(locationNode, 2, 2, {}, hud.iframeWindow);
|
||||
|
@ -6,30 +6,30 @@
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-585956-console-trace.html";
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf8,<p>hello");
|
||||
browser.addEventListener("load", tabLoaded, true);
|
||||
Task.spawn(runner).then(finishTest);
|
||||
|
||||
function tabLoaded() {
|
||||
browser.removeEventListener("load", tabLoaded, true);
|
||||
function* runner() {
|
||||
let {tab} = yield loadTab("data:text/html;charset=utf8,<p>hello");
|
||||
let hud = yield openConsole(tab);
|
||||
|
||||
openConsole(null, function(hud) {
|
||||
content.location = TEST_URI;
|
||||
content.location = TEST_URI;
|
||||
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "console.trace output",
|
||||
consoleTrace: {
|
||||
file: "test-bug-585956-console-trace.html",
|
||||
fn: "window.foobar585956c",
|
||||
},
|
||||
}],
|
||||
}).then(performChecks);
|
||||
let [result] = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "console.trace output",
|
||||
consoleTrace: {
|
||||
file: "test-bug-585956-console-trace.html",
|
||||
fn: "window.foobar585956c",
|
||||
},
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
function performChecks(results) {
|
||||
let node = [...results[0].matched][0];
|
||||
let node = [...result.matched][0];
|
||||
ok(node, "found trace log node");
|
||||
|
||||
let obj = node._messageObject;
|
||||
ok(obj, "console.trace message object");
|
||||
|
||||
// The expected stack trace object.
|
||||
let stacktrace = [
|
||||
@ -39,11 +39,8 @@ function test() {
|
||||
{ filename: TEST_URI, lineNumber: 21, functionName: null, language: 2 }
|
||||
];
|
||||
|
||||
ok(node, "found trace log node");
|
||||
ok(node._stacktrace, "found stacktrace object");
|
||||
is(node._stacktrace.toSource(), stacktrace.toSource(), "stacktrace is correct");
|
||||
ok(obj._stacktrace, "found stacktrace object");
|
||||
is(obj._stacktrace.toSource(), stacktrace.toSource(), "stacktrace is correct");
|
||||
isnot(node.textContent.indexOf("bug-585956"), -1, "found file name");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ function testCSSPruning(hudRef) {
|
||||
"repeated nodes pruned from repeatNodes");
|
||||
|
||||
let msg = [...result.matched][0];
|
||||
let repeats = msg.querySelector(".repeats");
|
||||
let repeats = msg.querySelector(".message-repeats");
|
||||
is(repeats.getAttribute("value"), 1,
|
||||
"repeated nodes pruned from repeatNodes (confirmed)");
|
||||
|
||||
|
@ -34,8 +34,8 @@ function test() {
|
||||
|
||||
let exceptionMsg = [...exceptionRule.matched][0];
|
||||
let consoleMsg = [...consoleRule.matched][0];
|
||||
let nodes = [exceptionMsg.querySelector(".location"),
|
||||
consoleMsg.querySelector(".location")];
|
||||
let nodes = [exceptionMsg.querySelector(".message-location"),
|
||||
consoleMsg.querySelector(".message-location")];
|
||||
ok(nodes[0], ".location node for the exception message");
|
||||
ok(nodes[1], ".location node for the console message");
|
||||
|
||||
|
@ -41,10 +41,10 @@ function testViewSource(aHud)
|
||||
}).then(([error1Rule, error2Rule]) => {
|
||||
let error1Msg = [...error1Rule.matched][0];
|
||||
let error2Msg = [...error2Rule.matched][0];
|
||||
nodes = [error1Msg.querySelector(".location"),
|
||||
error2Msg.querySelector(".location")];
|
||||
ok(nodes[0], ".location node for the first error");
|
||||
ok(nodes[1], ".location node for the second error");
|
||||
nodes = [error1Msg.querySelector(".message-location"),
|
||||
error2Msg.querySelector(".message-location")];
|
||||
ok(nodes[0], ".message-location node for the first error");
|
||||
ok(nodes[1], ".message-location node for the second error");
|
||||
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
@ -0,0 +1,36 @@
|
||||
/* 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/. */
|
||||
|
||||
function test() {
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug_939783_console_trace_duplicates.html";
|
||||
|
||||
Task.spawn(runner).then(finishTest);
|
||||
|
||||
function* runner() {
|
||||
const {tab} = yield loadTab("data:text/html;charset=utf8,<p>hello");
|
||||
const hud = yield openConsole(tab);
|
||||
|
||||
content.location = TEST_URI;
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "console.trace output for foo1()",
|
||||
text: "foo1()",
|
||||
repeats: 2,
|
||||
consoleTrace: {
|
||||
file: "test-bug_939783_console_trace_duplicates.html",
|
||||
fn: "foo3()",
|
||||
},
|
||||
}, {
|
||||
name: "console.trace output for foo1b()",
|
||||
text: "foo1b()",
|
||||
consoleTrace: {
|
||||
file: "test-bug_939783_console_trace_duplicates.html",
|
||||
fn: "foo3()",
|
||||
},
|
||||
}],
|
||||
});
|
||||
}
|
||||
}
|
@ -53,7 +53,7 @@ function runTests(aToolbox)
|
||||
|
||||
let [matched] = [...messages[0].matched];
|
||||
ok(matched, "Found logged message from Scratchpad");
|
||||
let anchor = matched.querySelector("a.location");
|
||||
let anchor = matched.querySelector("a.message-location");
|
||||
|
||||
aToolbox.on("scratchpad-selected", function selected() {
|
||||
aToolbox.off("scratchpad-selected", selected);
|
||||
|
@ -47,7 +47,7 @@ function testViewSource(hud) {
|
||||
function onMessage([result]) {
|
||||
let msg = [...result.matched][0];
|
||||
ok(msg, "error message");
|
||||
let locationNode = msg.querySelector(".location");
|
||||
let locationNode = msg.querySelector(".message-location");
|
||||
ok(locationNode, "location node");
|
||||
|
||||
Services.ww.registerNotification(observer);
|
||||
|
@ -3,19 +3,15 @@
|
||||
* 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/. */
|
||||
|
||||
let WebConsoleUtils, TargetFactory, require;
|
||||
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/commonjs/sdk/core/promise.js", {});
|
||||
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let {require, TargetFactory} = devtools;
|
||||
let {Utils: WebConsoleUtils} = require("devtools/toolkit/webconsole/utils");
|
||||
let {Messages} = require("devtools/webconsole/console-output");
|
||||
|
||||
(() => {
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let utils = devtools.require("devtools/toolkit/webconsole/utils");
|
||||
TargetFactory = devtools.TargetFactory;
|
||||
WebConsoleUtils = utils.Utils;
|
||||
require = devtools.require;
|
||||
})();
|
||||
// promise._reportErrors = true; // please never leave me.
|
||||
|
||||
let gPendingOutputTest = 0;
|
||||
@ -283,7 +279,7 @@ function dumpConsoles()
|
||||
function dumpMessageElement(aMessage)
|
||||
{
|
||||
let text = aMessage.textContent;
|
||||
let repeats = aMessage.querySelector(".repeats");
|
||||
let repeats = aMessage.querySelector(".message-repeats");
|
||||
if (repeats) {
|
||||
repeats = repeats.getAttribute("value");
|
||||
}
|
||||
@ -932,44 +928,44 @@ function waitForMessages(aOptions)
|
||||
let elemText = aElement.textContent;
|
||||
let trace = aRule.consoleTrace;
|
||||
|
||||
if (!checkText("Stack trace from ", elemText)) {
|
||||
if (!checkText("console.trace():", elemText)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let clickable = aElement.querySelector(".body a");
|
||||
if (!clickable) {
|
||||
ok(false, "console.trace() message is missing .hud-clickable");
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
aRule.clickableElements = [clickable];
|
||||
|
||||
if (trace.file &&
|
||||
!checkText("from " + trace.file + ", ", elemText)) {
|
||||
ok(false, "console.trace() message is missing the file name: " +
|
||||
trace.file);
|
||||
displayErrorContext(aRule, aElement);
|
||||
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 &&
|
||||
!checkText(", function " + trace.fn + ", ", elemText)) {
|
||||
ok(false, "console.trace() message is missing the function name: " +
|
||||
trace.fn);
|
||||
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 &&
|
||||
!checkText(", line " + trace.line + ".", elemText)) {
|
||||
ok(false, "console.trace() message is missing the line number: " +
|
||||
trace.line);
|
||||
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;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1038,7 +1034,7 @@ function waitForMessages(aOptions)
|
||||
|
||||
function checkSource(aRule, aElement)
|
||||
{
|
||||
let location = aElement.querySelector(".location");
|
||||
let location = aElement.querySelector(".message-location");
|
||||
if (!location) {
|
||||
return false;
|
||||
}
|
||||
@ -1090,16 +1086,23 @@ function waitForMessages(aOptions)
|
||||
return false;
|
||||
}
|
||||
|
||||
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
|
||||
aRule.consoleTimeEnd);
|
||||
|
||||
// The rule tries to match the newer types of messages, based on their
|
||||
// object constructor.
|
||||
if (aRule.type && (!aElement._messageObject ||
|
||||
!(aElement._messageObject instanceof aRule.type))) {
|
||||
return false;
|
||||
if (aRule.type) {
|
||||
if (!aElement._messageObject ||
|
||||
!(aElement._messageObject instanceof aRule.type)) {
|
||||
if (partialMatch) {
|
||||
ok(false, "message type for rule: " + displayRule(aRule));
|
||||
displayErrorContext(aRule, aElement);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
partialMatch = true;
|
||||
}
|
||||
|
||||
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
|
||||
aRule.consoleTimeEnd || aRule.type);
|
||||
|
||||
if ("category" in aRule && aElement.category != aRule.category) {
|
||||
if (partialMatch) {
|
||||
is(aElement.category, aRule.category,
|
||||
@ -1124,7 +1127,7 @@ function waitForMessages(aOptions)
|
||||
}
|
||||
|
||||
if ("repeats" in aRule) {
|
||||
let repeats = aElement.querySelector(".repeats");
|
||||
let repeats = aElement.querySelector(".message-repeats");
|
||||
if (!repeats || repeats.getAttribute("value") != aRule.repeats) {
|
||||
return false;
|
||||
}
|
||||
@ -1180,7 +1183,7 @@ function waitForMessages(aOptions)
|
||||
function onMessagesAdded(aEvent, aNewElements)
|
||||
{
|
||||
for (let elem of aNewElements) {
|
||||
let location = elem.querySelector(".location");
|
||||
let location = elem.querySelector(".message-location");
|
||||
if (location) {
|
||||
let url = location.title;
|
||||
// Prevent recursion with the browser console and any potential
|
||||
|
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Web Console test for bug 939783 - different console.trace() calls
|
||||
wrongly filtered as duplicates</title>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<script type="application/javascript">
|
||||
function foo1() {
|
||||
foo2();
|
||||
}
|
||||
|
||||
function foo1b() {
|
||||
foo2();
|
||||
}
|
||||
|
||||
function foo2() {
|
||||
foo3();
|
||||
}
|
||||
|
||||
function foo3() {
|
||||
console.trace();
|
||||
}
|
||||
|
||||
foo1(); foo1();
|
||||
foo1b();
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p>Web Console test for bug 939783 - different console.trace() calls
|
||||
wrongly filtered as duplicates</p>
|
||||
</body>
|
||||
</html>
|
@ -1056,7 +1056,7 @@ WebConsoleFrame.prototype = {
|
||||
mergeFilteredMessageNode:
|
||||
function WCF_mergeFilteredMessageNode(aOriginal, aFiltered)
|
||||
{
|
||||
let repeatNode = aOriginal.getElementsByClassName("repeats")[0];
|
||||
let repeatNode = aOriginal.getElementsByClassName("message-repeats")[0];
|
||||
if (!repeatNode) {
|
||||
return; // no repeat node, return early.
|
||||
}
|
||||
@ -1081,7 +1081,7 @@ WebConsoleFrame.prototype = {
|
||||
*/
|
||||
_filterRepeatedMessage: function WCF__filterRepeatedMessage(aNode)
|
||||
{
|
||||
let repeatNode = aNode.getElementsByClassName("repeats")[0];
|
||||
let repeatNode = aNode.getElementsByClassName("message-repeats")[0];
|
||||
if (!repeatNode) {
|
||||
return null;
|
||||
}
|
||||
@ -1105,7 +1105,7 @@ WebConsoleFrame.prototype = {
|
||||
return null;
|
||||
}
|
||||
|
||||
let lastRepeatNode = lastMessage.getElementsByClassName("repeats")[0];
|
||||
let lastRepeatNode = lastMessage.getElementsByClassName("message-repeats")[0];
|
||||
if (lastRepeatNode && lastRepeatNode._uid == uid) {
|
||||
dupeNode = lastMessage;
|
||||
}
|
||||
@ -1191,6 +1191,11 @@ WebConsoleFrame.prototype = {
|
||||
node = msg.init(this.output).render().element;
|
||||
break;
|
||||
}
|
||||
case "trace": {
|
||||
let msg = new Messages.ConsoleTrace(aMessage);
|
||||
node = msg.init(this.output).render().element;
|
||||
break;
|
||||
}
|
||||
case "dir": {
|
||||
body = { arguments: args };
|
||||
let clipboardArray = [];
|
||||
@ -1201,38 +1206,6 @@ WebConsoleFrame.prototype = {
|
||||
break;
|
||||
}
|
||||
|
||||
case "trace": {
|
||||
let filename = WebConsoleUtils.abbreviateSourceURL(aMessage.filename);
|
||||
let functionName = aMessage.functionName ||
|
||||
l10n.getStr("stacktrace.anonymousFunction");
|
||||
|
||||
body = this.document.createElementNS(XHTML_NS, "a");
|
||||
body.setAttribute("aria-haspopup", true);
|
||||
body.href = "#";
|
||||
body.draggable = false;
|
||||
body.textContent = l10n.getFormatStr("stacktrace.outputMessage",
|
||||
[filename, functionName,
|
||||
sourceLine]);
|
||||
|
||||
this._addMessageLinkCallback(body, () => {
|
||||
this.jsterm.openVariablesView({
|
||||
rawObject: aMessage.stacktrace,
|
||||
autofocus: true,
|
||||
});
|
||||
});
|
||||
|
||||
clipboardText = body.textContent + "\n";
|
||||
|
||||
aMessage.stacktrace.forEach(function(aFrame) {
|
||||
clipboardText += aFrame.filename + " :: " +
|
||||
aFrame.functionName + " :: " +
|
||||
aFrame.lineNumber + "\n";
|
||||
});
|
||||
|
||||
clipboardText = clipboardText.trimRight();
|
||||
break;
|
||||
}
|
||||
|
||||
case "group":
|
||||
case "groupCollapsed":
|
||||
clipboardText = body = aMessage.groupName;
|
||||
@ -1281,7 +1254,6 @@ WebConsoleFrame.prototype = {
|
||||
case "group":
|
||||
case "groupCollapsed":
|
||||
case "groupEnd":
|
||||
case "trace":
|
||||
case "time":
|
||||
case "timeEnd":
|
||||
for (let actor of objectActors) {
|
||||
@ -1307,15 +1279,11 @@ WebConsoleFrame.prototype = {
|
||||
node._objectActors = objectActors;
|
||||
|
||||
if (!node._messageObject) {
|
||||
let repeatNode = node.getElementsByClassName("repeats")[0];
|
||||
let repeatNode = node.getElementsByClassName("message-repeats")[0];
|
||||
repeatNode._uid += [...objectActors].join("-");
|
||||
}
|
||||
}
|
||||
|
||||
if (level == "trace") {
|
||||
node._stacktrace = aMessage.stacktrace;
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
@ -2388,7 +2356,7 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
if (aNode.category == CATEGORY_CSS ||
|
||||
aNode.category == CATEGORY_SECURITY) {
|
||||
let repeatNode = aNode.getElementsByClassName("repeats")[0];
|
||||
let repeatNode = aNode.getElementsByClassName("message-repeats")[0];
|
||||
if (repeatNode && repeatNode._uid) {
|
||||
delete this._repeatNodes[repeatNode._uid];
|
||||
}
|
||||
@ -2501,7 +2469,7 @@ WebConsoleFrame.prototype = {
|
||||
!(aCategory == CATEGORY_CSS && aSeverity == SEVERITY_LOG)) {
|
||||
repeatNode = this.document.createElementNS(XHTML_NS, "span");
|
||||
repeatNode.setAttribute("value", "1");
|
||||
repeatNode.className = "repeats";
|
||||
repeatNode.className = "message-repeats";
|
||||
repeatNode.textContent = 1;
|
||||
repeatNode._uid = [bodyNode.textContent, aCategory, aSeverity, aLevel,
|
||||
aSourceURL, aSourceLine].join(":");
|
||||
@ -2567,11 +2535,18 @@ WebConsoleFrame.prototype = {
|
||||
* @param number aSourceLine [optional]
|
||||
* The line number on which the error occurred. If zero or omitted,
|
||||
* there is no line number associated with this message.
|
||||
* @param string aTarget [optional]
|
||||
* Tells which tool to open the link with, on click. Supported tools:
|
||||
* jsdebugger, styleeditor, scratchpad.
|
||||
* @return nsIDOMNode
|
||||
* The new anchor element, ready to be added to the message node.
|
||||
*/
|
||||
createLocationNode: function WCF_createLocationNode(aSourceURL, aSourceLine)
|
||||
createLocationNode:
|
||||
function WCF_createLocationNode(aSourceURL, aSourceLine, aTarget)
|
||||
{
|
||||
if (!aSourceURL) {
|
||||
aSourceURL = "";
|
||||
}
|
||||
let locationNode = this.document.createElementNS(XHTML_NS, "a");
|
||||
let filenameNode = this.document.createElementNS(XHTML_NS, "span");
|
||||
|
||||
@ -2592,30 +2567,39 @@ WebConsoleFrame.prototype = {
|
||||
}
|
||||
|
||||
filenameNode.className = "filename";
|
||||
filenameNode.textContent = " " + filename;
|
||||
filenameNode.textContent = " " + (filename || l10n.getStr("unknownLocation"));
|
||||
locationNode.appendChild(filenameNode);
|
||||
|
||||
locationNode.href = isScratchpad ? "#" : fullURL;
|
||||
locationNode.href = isScratchpad || !fullURL ? "#" : fullURL;
|
||||
locationNode.draggable = false;
|
||||
locationNode.target = aTarget;
|
||||
locationNode.setAttribute("title", aSourceURL);
|
||||
locationNode.className = "location theme-link devtools-monospace";
|
||||
locationNode.className = "message-location theme-link devtools-monospace";
|
||||
|
||||
// Make the location clickable.
|
||||
this._addMessageLinkCallback(locationNode, () => {
|
||||
if (isScratchpad) {
|
||||
let onClick = () => {
|
||||
let target = locationNode.target;
|
||||
if (target == "scratchpad" || isScratchpad) {
|
||||
this.owner.viewSourceInScratchpad(aSourceURL);
|
||||
return;
|
||||
}
|
||||
else if (locationNode.parentNode.category == CATEGORY_CSS) {
|
||||
|
||||
let category = locationNode.parentNode.category;
|
||||
if (target == "styleeditor" || category == CATEGORY_CSS) {
|
||||
this.owner.viewSourceInStyleEditor(fullURL, aSourceLine);
|
||||
}
|
||||
else if (locationNode.parentNode.category == CATEGORY_JS ||
|
||||
locationNode.parentNode.category == CATEGORY_WEBDEV) {
|
||||
else if (target == "jsdebugger" ||
|
||||
category == CATEGORY_JS || category == CATEGORY_WEBDEV) {
|
||||
this.owner.viewSourceInDebugger(fullURL, aSourceLine);
|
||||
}
|
||||
else {
|
||||
this.owner.viewSource(fullURL, aSourceLine);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (fullURL) {
|
||||
this._addMessageLinkCallback(locationNode, onClick);
|
||||
}
|
||||
|
||||
if (aSourceLine) {
|
||||
let lineNumberNode = this.document.createElementNS(XHTML_NS, "span");
|
||||
|
@ -102,15 +102,13 @@ reflow.messageLinkText=function %1$S, %2$S line %3$S
|
||||
|
||||
# LOCALIZATION NOTE (stacktrace.anonymousFunction): this string is used to
|
||||
# display JavaScript functions that have no given name - they are said to be
|
||||
# anonymous. See also stacktrace.outputMessage.
|
||||
# anonymous. Test console.trace() in the webconsole.
|
||||
stacktrace.anonymousFunction=<anonymous>
|
||||
|
||||
# LOCALIZATION NOTE (stacktrace.outputMessage): this string is used in the Web
|
||||
# Console output to identify a web developer call to console.trace(). The
|
||||
# stack trace of JavaScript function calls is displayed. In this minimal
|
||||
# message we only show the last call. Parameters: %1$S is the file name, %2$S
|
||||
# is the function name, %3$S is the line number.
|
||||
stacktrace.outputMessage=Stack trace from %1$S, function %2$S, line %3$S.
|
||||
# LOCALIZATION NOTE (unknownLocation): this string is used to
|
||||
# display messages with sources that have an unknown location, eg. from
|
||||
# console.trace() calls.
|
||||
unknownLocation=<unknown>
|
||||
|
||||
# LOCALIZATION NOTE (timerStarted): this string is used to display the result
|
||||
# of the console.time() call. Parameters: %S is the name of the timer.
|
||||
|
@ -46,7 +46,7 @@ a {
|
||||
}
|
||||
|
||||
/* The red bubble that shows the number of times a message is repeated */
|
||||
.message > .repeats {
|
||||
.message-repeats {
|
||||
-moz-user-select: none;
|
||||
flex: 0 0 auto;
|
||||
margin: 2px 6px;
|
||||
@ -60,11 +60,11 @@ a {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.message > .repeats[value="1"] {
|
||||
.message-repeats[value="1"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message > .location {
|
||||
.message-location {
|
||||
-moz-margin-start: 6px;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
@ -74,21 +74,21 @@ a {
|
||||
margin-top: 4px;
|
||||
color: -moz-nativehyperlinktext;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.message > .location:hover,
|
||||
.message > .location:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.message > .location > .filename {
|
||||
text-overflow: ellipsis;
|
||||
text-align: end;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.message > .location > .line-number {
|
||||
.message-location:hover,
|
||||
.message-location:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.message-location > .filename {
|
||||
text-overflow: ellipsis;
|
||||
text-align: end;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.message-location > .line-number {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
@ -336,6 +336,37 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.consoleTrace .body > div {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.consoleTrace .title {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.stacktrace {
|
||||
list-style: none;
|
||||
padding: 0 1em 0 1.5em;
|
||||
margin: 0;
|
||||
max-height: 10em;
|
||||
overflow-y: auto;
|
||||
|
||||
border: 1px solid rgba(128, 128, 128, .5);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.stacktrace li {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.stacktrace .function {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
/* Replace these values with CSS variables as available */
|
||||
.theme-dark .jsterm-input-container {
|
||||
background-color: #252c33; /* tabToolbarBackgroundColor */
|
||||
@ -358,6 +389,10 @@ a {
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
.theme-dark .stacktrace {
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
.theme-light .jsterm-input-container {
|
||||
background-color: #fff; /* mainBackgroundColor */
|
||||
border-color: ThreeDShadow;
|
||||
@ -379,6 +414,10 @@ a {
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.theme-light .stacktrace {
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.message > .timestamp {
|
||||
display: none;
|
||||
|
Loading…
Reference in New Issue
Block a user