mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-23 18:26:15 +00:00
Bug 611795 - Repeated messages in the Web Console should be collapsed into one; f=mihai.sucan r=sdwilsh,dao a=beltzner
This commit is contained in:
parent
a9faf09c6b
commit
1863b39a87
@ -1201,11 +1201,17 @@ function pruneConsoleOutputIfNecessary(aConsoleNode)
|
||||
let scrollBox = aConsoleNode.scrollBoxObject.element;
|
||||
let oldScrollHeight = scrollBox.scrollHeight;
|
||||
let scrolledToBottom = ConsoleUtils.isOutputScrolledToBottom(aConsoleNode);
|
||||
let hudRef = HUDService.getHudReferenceForOutputNode(aConsoleNode);
|
||||
|
||||
// Prune the nodes.
|
||||
let messageNodes = aConsoleNode.querySelectorAll(".hud-msg-node");
|
||||
let removeNodes = messageNodes.length - logLimit;
|
||||
for (let i = 0; i < removeNodes; i++) {
|
||||
if (messageNodes[i].classList.contains("webconsole-msg-cssparser")) {
|
||||
let desc = messageNodes[i].childNodes[2].textContent;
|
||||
let location = messageNodes[i].childNodes[4].getAttribute("title");
|
||||
delete hudRef.cssNodes[desc + location];
|
||||
}
|
||||
messageNodes[i].parentNode.removeChild(messageNodes[i]);
|
||||
}
|
||||
|
||||
@ -1458,6 +1464,12 @@ HUD_SERVICE.prototype =
|
||||
aHUD = this.getOutputNodeById(aHUD);
|
||||
}
|
||||
|
||||
let hudRef = HUDService.getHudReferenceForOutputNode(aHUD);
|
||||
|
||||
if (hudRef) {
|
||||
hudRef.cssNodes = {};
|
||||
}
|
||||
|
||||
var outputNode = aHUD.querySelector(".hud-output-node");
|
||||
|
||||
while (outputNode.firstChild) {
|
||||
@ -1734,6 +1746,9 @@ HUD_SERVICE.prototype =
|
||||
parent.removeChild(outputNode);
|
||||
|
||||
// remove the HeadsUpDisplay object from memory
|
||||
if ("cssNodes" in this.hudReferences[id]) {
|
||||
delete this.hudReferences[id].cssNodes;
|
||||
}
|
||||
delete this.hudReferences[id];
|
||||
// remove the related storage object
|
||||
this.storage.removeDisplay(id);
|
||||
@ -1827,6 +1842,39 @@ HUD_SERVICE.prototype =
|
||||
return this.getHudIdByWindowId(windowId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the hudReference for a given output node.
|
||||
*
|
||||
* @param nsIDOMNode aNode
|
||||
* an output node (as returned by getOutputNodeById()).
|
||||
* @returns a HUD | null
|
||||
*/
|
||||
getHudReferenceForOutputNode: function HS_getHudReferenceForOutputNode(aNode)
|
||||
{
|
||||
let node = aNode;
|
||||
while (!node.classList.contains("hudbox-animated")) {
|
||||
if (node.parent) {
|
||||
node = node.parent;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
let id = node.id;
|
||||
return id in this.hudReferences ? this.hudReferences[id] : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the hudReference for a given id.
|
||||
*
|
||||
* @param string aId
|
||||
* @returns Object
|
||||
*/
|
||||
getHudReferenceById: function HS_getHudReferenceById(aId)
|
||||
{
|
||||
return aId in this.hudReferences ? this.hudReferences[aId] : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Web Console DOM node, the .hud-box.
|
||||
*
|
||||
@ -1872,7 +1920,7 @@ HUD_SERVICE.prototype =
|
||||
},
|
||||
|
||||
/**
|
||||
* get the current filter string for the HeadsUpDisplay
|
||||
* Get the current filter string for the HeadsUpDisplay
|
||||
*
|
||||
* @param string aHUDId
|
||||
* @returns string
|
||||
@ -2987,6 +3035,9 @@ function HeadsUpDisplay(aConfig)
|
||||
catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
// A cache for tracking repeated CSS Nodes.
|
||||
this.cssNodes = {};
|
||||
}
|
||||
|
||||
HeadsUpDisplay.prototype = {
|
||||
@ -4329,6 +4380,11 @@ JSTerm.prototype = {
|
||||
clearOutput: function JST_clearOutput()
|
||||
{
|
||||
let outputNode = this.outputNode;
|
||||
let hudRef = HUDService.getHudReferenceForOutputNode(outputNode);
|
||||
|
||||
if (hudRef) {
|
||||
hudRef.cssNodes = {};
|
||||
}
|
||||
|
||||
while (outputNode.firstChild) {
|
||||
outputNode.removeChild(outputNode.firstChild);
|
||||
@ -4943,6 +4999,10 @@ ConsoleUtils = {
|
||||
|
||||
bodyNode.appendChild(aBody);
|
||||
|
||||
let repeatNode = aDocument.createElementNS(XUL_NS, "xul:label");
|
||||
repeatNode.setAttribute("value", "1");
|
||||
repeatNode.classList.add("webconsole-msg-repeat");
|
||||
|
||||
// Create the timestamp.
|
||||
let timestampNode = aDocument.createElementNS(XUL_NS, "xul:label");
|
||||
timestampNode.classList.add("webconsole-timestamp");
|
||||
@ -4966,11 +5026,12 @@ ConsoleUtils = {
|
||||
node.timestamp = timestamp;
|
||||
ConsoleUtils.setMessageType(node, aCategory, aSeverity);
|
||||
|
||||
node.appendChild(timestampNode);
|
||||
node.appendChild(iconContainer);
|
||||
node.appendChild(bodyNode);
|
||||
node.appendChild(timestampNode); // childNode[0]
|
||||
node.appendChild(iconContainer); // childNode[1]
|
||||
node.appendChild(bodyNode); // childNode[2]
|
||||
node.appendChild(repeatNode); // childNode[3]
|
||||
if (locationNode) {
|
||||
node.appendChild(locationNode);
|
||||
node.appendChild(locationNode); // childNode[4]
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -5065,7 +5126,7 @@ ConsoleUtils = {
|
||||
* @param string aHUDId
|
||||
* The ID of the HUD which this node is to be inserted into.
|
||||
*/
|
||||
filterMessageNode: function(aNode, aHUDId) {
|
||||
filterMessageNode: function ConsoleUtils_filterMessageNode(aNode, aHUDId) {
|
||||
// Filter by the message type.
|
||||
let prefKey = MESSAGE_PREFERENCE_KEYS[aNode.category][aNode.severity];
|
||||
if (prefKey && !HUDService.getFilterState(aHUDId, prefKey)) {
|
||||
@ -5084,7 +5145,95 @@ ConsoleUtils = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters a node appropriately, then sends it to the output, regrouping and
|
||||
* Merge the attributes of the two nodes that are about to be filtered.
|
||||
* Increment the number of repeats of aOriginal.
|
||||
*
|
||||
* @param nsIDOMNode aOriginal
|
||||
* The Original Node. The one being merged into.
|
||||
* @param nsIDOMNode aFiltered
|
||||
* The node being filtered out because it is repeated.
|
||||
*/
|
||||
mergeFilteredMessageNode:
|
||||
function ConsoleUtils_mergeFilteredMessageNode(aOriginal, aFiltered) {
|
||||
// childNodes[3] is the node containing the number of repetitions of a node.
|
||||
let repeatNode = aOriginal.childNodes[3];
|
||||
if (!repeatNode) {
|
||||
return aOriginal; // no repeat node, return early.
|
||||
}
|
||||
|
||||
let occurrences = parseInt(repeatNode.getAttribute("value")) + 1;
|
||||
repeatNode.setAttribute("value", occurrences);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter the css node from the output node if it is a repeat. CSS messages
|
||||
* are merged with previous messages if they occurred in the past.
|
||||
*
|
||||
* @param nsIDOMNode aNode
|
||||
* The message node to be filtered or not.
|
||||
* @param nsIDOMNode aOutput
|
||||
* The outputNode of the HUD.
|
||||
* @returns boolean
|
||||
* true if the message is filtered, false otherwise.
|
||||
*/
|
||||
filterRepeatedCSS:
|
||||
function ConsoleUtils_filterRepeatedCSS(aNode, aOutput, aHUDId) {
|
||||
let hud = HUDService.getHudReferenceById(aHUDId);
|
||||
|
||||
// childNodes[2] is the description node containing the text of the message.
|
||||
let description = aNode.childNodes[2].textContent;
|
||||
let location;
|
||||
|
||||
// childNodes[4] represents the location (source URL) of the error message.
|
||||
// The full source URL is stored in the title attribute.
|
||||
if (aNode.childNodes[4]) {
|
||||
// browser_webconsole_bug_595934_message_categories.js
|
||||
location = aNode.childNodes[4].getAttribute("title");
|
||||
}
|
||||
else {
|
||||
location = "";
|
||||
}
|
||||
|
||||
let dupe = hud.cssNodes[description + location];
|
||||
if (!dupe) {
|
||||
// no matching nodes
|
||||
hud.cssNodes[description + location] = aNode;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.mergeFilteredMessageNode(dupe, aNode);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter the console node from the output node if it is a repeat. Console
|
||||
* messages are filtered from the output if and only if they match the
|
||||
* immediately preceding message. The output node's last occurrence should
|
||||
* have its timestamp updated.
|
||||
*
|
||||
* @param nsIDOMNode aNode
|
||||
* The message node to be filtered or not.
|
||||
* @param nsIDOMNode aOutput
|
||||
* The outputNode of the HUD.
|
||||
* @return boolean
|
||||
* true if the message is filtered, false otherwise.
|
||||
*/
|
||||
filterRepeatedConsole:
|
||||
function ConsoleUtils_filterRepeatedConsole(aNode, aOutput) {
|
||||
let lastMessage = aOutput.lastChild;
|
||||
|
||||
// childNodes[2] is the xul:description element
|
||||
if (lastMessage &&
|
||||
aNode.childNodes[2].textContent ==
|
||||
lastMessage.childNodes[2].textContent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/** * Filters a node appropriately, then sends it to the output, regrouping and
|
||||
* pruning output as necessary.
|
||||
*
|
||||
* @param nsIDOMNode aNode
|
||||
@ -5099,7 +5248,22 @@ ConsoleUtils = {
|
||||
|
||||
let scrolledToBottom = ConsoleUtils.isOutputScrolledToBottom(outputNode);
|
||||
|
||||
outputNode.appendChild(aNode);
|
||||
let isRepeated = false;
|
||||
if (aNode.classList.contains("webconsole-msg-cssparser")) {
|
||||
isRepeated = this.filterRepeatedCSS(aNode, outputNode, aHUDId);
|
||||
}
|
||||
|
||||
if (!isRepeated &&
|
||||
(aNode.classList.contains("webconsole-msg-console") ||
|
||||
aNode.classList.contains("webconsole-msg-exception") ||
|
||||
aNode.classList.contains("webconsole-msg-error"))) {
|
||||
isRepeated = this.filterRepeatedConsole(aNode, outputNode, aHUDId);
|
||||
}
|
||||
|
||||
if (!isRepeated) {
|
||||
outputNode.appendChild(aNode);
|
||||
}
|
||||
|
||||
HUDService.regroupOutput(outputNode);
|
||||
|
||||
if (pruneConsoleOutputIfNecessary(outputNode) == 0) {
|
||||
@ -5116,7 +5280,7 @@ ConsoleUtils = {
|
||||
// Scroll to the new node if it is not filtered, and if the output node is
|
||||
// scrolled at the bottom or if the new node is a jsterm input/output
|
||||
// message.
|
||||
if (!isFiltered && (scrolledToBottom || isInputOutput)) {
|
||||
if (!isFiltered && !isRepeated && (scrolledToBottom || isInputOutput)) {
|
||||
ConsoleUtils.scrollToVisible(aNode);
|
||||
}
|
||||
},
|
||||
|
@ -32,8 +32,9 @@ function testLineLimit() {
|
||||
prefBranch.setIntPref("loglimit", 20);
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
console.log("foo");
|
||||
console.log("foo #" + i); // must change message to prevent repeats
|
||||
}
|
||||
|
||||
is(countMessageNodes(), 20, "there are 20 message nodes in the output " +
|
||||
"when the log limit is set to 20");
|
||||
|
||||
@ -43,8 +44,9 @@ function testLineLimit() {
|
||||
|
||||
prefBranch.setIntPref("loglimit", 30);
|
||||
for (let i = 0; i < 20; i++) {
|
||||
console.log("boo");
|
||||
console.log("boo #" + i); // must change message to prevent repeats
|
||||
}
|
||||
|
||||
is(countMessageNodes(), 30, "there are 30 message nodes in the output " +
|
||||
"when the log limit is set to 30");
|
||||
|
||||
|
@ -0,0 +1,50 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TEST_URI = 'data:text/html,<div style="-moz-opacity:0;">test repeated' +
|
||||
' css warnings</div><p style="-moz-opacity:0">hi</p>';
|
||||
|
||||
function onContentLoaded()
|
||||
{
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
hudId = HUDService.displaysIndex()[0];
|
||||
HUD = HUDService.hudReferences[hudId].HUDBox;
|
||||
jsterm = HUDService.hudReferences[hudId].jsterm;
|
||||
let filterBox = HUD.querySelector(".hud-filter-box");
|
||||
let outputNode = HUD.querySelector(".hud-output-node");
|
||||
|
||||
let msg = "The unknown CSS property warning is displayed only once";
|
||||
let node = outputNode.firstChild;
|
||||
|
||||
is (node.childNodes[2].textContent, "Unknown property '-moz-opacity'. Declaration dropped.", "correct node")
|
||||
is(node.childNodes[3].getAttribute("value"), 2, msg);
|
||||
|
||||
jsterm.clearOutput();
|
||||
|
||||
jsterm.setInputValue("for (let i = 0; i < 10; ++i) console.log('hi');");
|
||||
jsterm.execute();
|
||||
|
||||
msg = "The console output is repeated 10 times";
|
||||
let node = outputNode.querySelector(".webconsole-msg-console");
|
||||
is(node.childNodes[3].getAttribute("value"), 10, msg);
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit test for bug 611795:
|
||||
* Repeated CSS messages get collapsed into one.
|
||||
*/
|
||||
function test()
|
||||
{
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function() {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
openConsole();
|
||||
browser.addEventListener("load", onContentLoaded, true);
|
||||
content.location.reload();
|
||||
}, true);
|
||||
}
|
@ -84,14 +84,14 @@ function testConsoleLoggingAPI(aMethod) {
|
||||
setStringFilter(hudId, "");
|
||||
HUDService.setFilterState(hudId, aMethod, false);
|
||||
console[aMethod]("foo-bar-baz");
|
||||
nodes = outputNode.querySelectorAll("label");
|
||||
nodes = outputNode.querySelectorAll("description");
|
||||
|
||||
is(nodes.length, 1, aMethod + " logging turned off, 1 message hidden");
|
||||
|
||||
HUDService.clearDisplay(hudId);
|
||||
HUDService.setFilterState(hudId, aMethod, true);
|
||||
console[aMethod]("foo-bar-baz");
|
||||
nodes = outputNode.querySelectorAll("label");
|
||||
nodes = outputNode.querySelectorAll("description");
|
||||
|
||||
is(nodes.length, 1, aMethod + " logging turned on, 1 message shown");
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
* David Dahl <ddahl@mozilla.com>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Rob Campbell <rcampbell@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -96,6 +97,25 @@
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
/* Repeated messages */
|
||||
.webconsole-msg-repeat {
|
||||
margin: 2px 0;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
width: 1em;
|
||||
color: white;
|
||||
background-color: red;
|
||||
border-radius: 40px;
|
||||
font: message-box;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* TODO move this and other functional rules to content - bug 635359 */
|
||||
.webconsole-msg-repeat[value="1"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.webconsole-location {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
@ -21,7 +21,8 @@
|
||||
* Contributor(s):
|
||||
* David Dahl <ddahl@mozilla.com>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
|
||||
* Rob Campbell <rcampbell@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
@ -99,6 +100,25 @@
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
/* Repeated messages */
|
||||
.webconsole-msg-repeat {
|
||||
margin: 2px 0;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
width: 1em;
|
||||
color: white;
|
||||
background-color: red;
|
||||
border-radius: 40px;
|
||||
font: message-box;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* TODO move this and other functional rules to content - bug 635359 */
|
||||
.webconsole-msg-repeat[value="1"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.webconsole-location {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
@ -21,7 +21,8 @@
|
||||
* Contributor(s):
|
||||
* David Dahl <ddahl@mozilla.com>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
|
||||
* Rob Campbell <rcampbell@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
@ -95,6 +96,25 @@
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
/* Repeated messages */
|
||||
.webconsole-msg-repeat {
|
||||
margin: 2px 0;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
width: 1em;
|
||||
color: white;
|
||||
background-color: red;
|
||||
border-radius: 40px;
|
||||
font: message-box;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* TODO move this and other functional rules to content - bug 635359 */
|
||||
.webconsole-msg-repeat[value="1"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.webconsole-location {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
Loading…
Reference in New Issue
Block a user