Bug 664131 - Expand console object with group methods that indent future console messages in order to create separate blocks of visually combined output; r=gavin

This commit is contained in:
Panos Astithas 2011-06-14 14:38:11 +03:00
parent 11751e1cb0
commit 43aa7edc0f
9 changed files with 177 additions and 15 deletions

View File

@ -165,7 +165,10 @@ const LEVELS = {
info: SEVERITY_INFO,
log: SEVERITY_LOG,
trace: SEVERITY_LOG,
dir: SEVERITY_LOG
dir: SEVERITY_LOG,
group: SEVERITY_LOG,
groupCollapsed: SEVERITY_LOG,
groupEnd: SEVERITY_LOG
};
// The lowest HTTP response code (inclusive) that is considered an error.
@ -252,6 +255,9 @@ const ERRORS = { LOG_MESSAGE_MISSING_ARGS:
LOG_OUTPUT_FAILED: "Log Failure: Could not append messageNode to outputNode",
};
// The indent of a console group in pixels.
const GROUP_INDENT = 12;
/**
* Implements the nsIStreamListener and nsIRequestObserver interface. Used
* within the HS_httpObserverFactory function to get the response body of
@ -2005,6 +2011,20 @@ HUD_SERVICE.prototype =
sourceLine = aMessage.lineNumber;
break;
case "group":
case "groupCollapsed":
clipboardText = body = formatResult(args);
sourceURL = aMessage.filename;
sourceLine = aMessage.lineNumber;
hud.groupDepth++;
break;
case "groupEnd":
if (hud.groupDepth > 0) {
hud.groupDepth--;
}
return;
default:
Cu.reportError("Unknown Console API log level: " + level);
return;
@ -2014,6 +2034,7 @@ HUD_SERVICE.prototype =
CATEGORY_WEBDEV,
LEVELS[level],
body,
aHUDId,
sourceURL,
sourceLine,
clipboardText,
@ -2076,7 +2097,8 @@ HUD_SERVICE.prototype =
let chromeDocument = hud.HUDBox.ownerDocument;
let message = stringBundle.GetStringFromName("ConsoleAPIDisabled");
let node = ConsoleUtils.createMessageNode(chromeDocument, CATEGORY_JS,
SEVERITY_WARNING, message);
SEVERITY_WARNING, message,
aHUDId);
ConsoleUtils.outputMessageNode(node, aHUDId);
},
@ -2116,6 +2138,7 @@ HUD_SERVICE.prototype =
aCategory,
severity,
aScriptError.errorMessage,
hudId,
aScriptError.sourceName,
aScriptError.lineNumber);
@ -2576,6 +2599,7 @@ HUD_SERVICE.prototype =
CATEGORY_NETWORK,
SEVERITY_LOG,
msgNode,
hudId,
null,
null,
clipboardText);
@ -3081,6 +3105,11 @@ HeadsUpDisplay.prototype = {
consolePanel: null,
/**
* The nesting depth of the currently active console group.
*/
groupDepth: 0,
get mainPopupSet()
{
return this.chromeDocument.getElementById("mainPopupSet");
@ -4752,7 +4781,8 @@ JSTerm.prototype = {
let node = ConsoleUtils.createMessageNode(this.parentNode.ownerDocument,
CATEGORY_OUTPUT,
SEVERITY_LOG,
aOutputString);
aOutputString,
this.hudId);
let linkNode = node.querySelector(".webconsole-msg-body");
@ -4799,7 +4829,7 @@ JSTerm.prototype = {
{
let node = ConsoleUtils.createMessageNode(this.parentNode.ownerDocument,
aCategory, aSeverity,
aOutputMessage);
aOutputMessage, this.hudId);
ConsoleUtils.outputMessageNode(node, this.hudId);
},
@ -5540,6 +5570,8 @@ ConsoleUtils = {
* The severity of the message: one of the SEVERITY_* constants;
* @param string|nsIDOMNode aBody
* The body of the message, either a simple string or a DOM node.
* @param number aHUDId
* The HeadsUpDisplay ID.
* @param string aSourceURL [optional]
* The URL of the source file that emitted the error.
* @param number aSourceLine [optional]
@ -5557,8 +5589,8 @@ ConsoleUtils = {
*/
createMessageNode:
function ConsoleUtils_createMessageNode(aDocument, aCategory, aSeverity,
aBody, aSourceURL, aSourceLine,
aClipboardText, aLevel) {
aBody, aHUDId, aSourceURL,
aSourceLine, aClipboardText, aLevel) {
if (aBody instanceof Ci.nsIDOMNode && aClipboardText == null) {
throw new Error("HUDService.createMessageNode(): DOM node supplied " +
"without any clipboard text");
@ -5569,6 +5601,9 @@ ConsoleUtils = {
// long multi-line messages.
let iconContainer = aDocument.createElementNS(XUL_NS, "vbox");
iconContainer.classList.add("webconsole-msg-icon-container");
// Apply the curent group by indenting appropriately.
let hud = HUDService.getHudReferenceById(aHUDId);
iconContainer.style.marginLeft = hud.groupDepth * GROUP_INDENT + "px";
// Make the icon node. It's sprited and the actual region of the image is
// determined by CSS rules.
@ -6669,6 +6704,7 @@ ConsoleProgressListener.prototype = {
CATEGORY_NETWORK,
SEVERITY_LOG,
msgNode,
this.hudId,
null,
null,
uri.spec);

View File

@ -145,6 +145,7 @@ _BROWSER_TEST_FILES = \
browser_webconsole_bug_653531_highlighter_console_helper.js \
browser_webconsole_bug_659907_console_dir.js \
browser_webconsole_bug_678816.js \
browser_webconsole_bug_664131_console_group.js \
head.js \
$(NULL)

View File

@ -25,7 +25,8 @@ function populateConsoleRepeats(aHudRef) {
let node = ConsoleUtils.createMessageNode(hud.ownerDocument,
CATEGORY_CSS,
SEVERITY_WARNING,
"css log x");
"css log x",
aHudRef.hudId);
ConsoleUtils.outputMessageNode(node, aHudRef.hudId);
}
}
@ -38,7 +39,8 @@ function populateConsole(aHudRef) {
let node = ConsoleUtils.createMessageNode(hud.ownerDocument,
CATEGORY_CSS,
SEVERITY_WARNING,
"css log " + i);
"css log " + i,
aHudRef.hudId);
ConsoleUtils.outputMessageNode(node, aHudRef.hudId);
}
}

View File

@ -0,0 +1,48 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that console.group/groupEnd works as intended.
const GROUP_INDENT = 12;
function test() {
addTab("data:text/html,Web Console test for bug 664131: Expand console " +
"object with group methods");
browser.addEventListener("load", onLoad, true);
}
function onLoad(aEvent) {
browser.removeEventListener(aEvent.type, arguments.callee, true);
openConsole();
let hudId = HUDService.getHudIdByWindow(content);
let hud = HUDService.hudReferences[hudId];
outputNode = hud.outputNode;
content.console.group("a");
findLogEntry("a");
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
is(msg.length, 1, "one message node displayed");
is(msg[0].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
content.console.log("inside");
findLogEntry("inside");
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
is(msg.length, 2, "two message nodes displayed");
is(msg[1].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
content.console.groupEnd("a");
content.console.log("outside");
findLogEntry("outside");
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
is(msg.length, 3, "three message nodes displayed");
is(msg[2].style.marginLeft, "0px", "correct group indent found");
content.console.groupCollapsed("b");
findLogEntry("b");
let msg = outputNode.querySelectorAll(".webconsole-msg-icon-container");
is(msg.length, 4, "four message nodes displayed");
is(msg[3].style.marginLeft, GROUP_INDENT + "px", "correct group indent found");
finishTest();
}

View File

@ -10,9 +10,6 @@
console.assert()
console.clear()
console.dirxml()
console.group()
console.groupCollapsed()
console.groupEnd()
console.profile()
console.profileEnd()
console.count()

View File

@ -94,6 +94,15 @@ ConsoleAPI.prototype = {
dir: function CA_dir() {
self.notifyObservers(outerID, innerID, "dir", arguments);
},
group: function CA_group() {
self.notifyObservers(outerID, innerID, "group", self.beginGroup(arguments));
},
groupCollapsed: function CA_groupCollapsed() {
self.notifyObservers(outerID, innerID, "groupCollapsed", self.beginGroup(arguments));
},
groupEnd: function CA_groupEnd() {
self.notifyObservers(outerID, innerID, "groupEnd", arguments);
},
__exposedProps__: {
log: "r",
info: "r",
@ -101,7 +110,10 @@ ConsoleAPI.prototype = {
error: "r",
debug: "r",
trace: "r",
dir: "r"
dir: "r",
group: "r",
groupCollapsed: "r",
groupEnd: "r"
}
};
@ -120,6 +132,9 @@ ConsoleAPI.prototype = {
debug: genPropDesc('debug'),
trace: genPropDesc('trace'),
dir: genPropDesc('dir'),
group: genPropDesc('group'),
groupCollapsed: genPropDesc('groupCollapsed'),
groupEnd: genPropDesc('groupEnd'),
__noSuchMethod__: { enumerable: true, configurable: true, writable: true,
value: function() {} },
__mozillaConsole__: { value: true }
@ -229,6 +244,13 @@ ConsoleAPI.prototype = {
}
return stack;
},
/**
* Begin a new group for logging output together.
**/
beginGroup: function CA_beginGroup() {
return Array.prototype.join.call(arguments[0], " ");
}
};

View File

@ -108,9 +108,52 @@ function testLocationData(aMessageObject) {
is(aMessageObject.arguments[i], a, "correct arg " + i);
});
// Test finished
ConsoleObserver.destroy();
finish();
startGroupTest();
}
function startGroupTest() {
// Reset the observer function to cope with the fabricated test data.
ConsoleObserver.observe = function CO_observe(aSubject, aTopic, aData) {
try {
testConsoleGroup(aSubject.wrappedJSObject);
} catch (ex) {
// XXX Exceptions in this function currently aren't reported, because of
// some XPConnect weirdness, so report them manually
ok(false, "Exception thrown in CO_observe: " + ex);
}
};
let button = gWindow.document.getElementById("test-groups");
ok(button, "found #test-groups button");
EventUtils.synthesizeMouse(button, 2, 2, {}, gWindow);
}
function testConsoleGroup(aMessageObject) {
let messageWindow = getWindowByWindowId(aMessageObject.ID);
is(messageWindow, gWindow, "found correct window by window ID");
ok(aMessageObject.level == "group" ||
aMessageObject.level == "groupCollapsed" ||
aMessageObject.level == "groupEnd",
"expected level received");
is(aMessageObject.functionName, "testGroups", "functionName matches");
ok(aMessageObject.lineNumber >= 32 && aMessageObject.lineNumber <= 34,
"lineNumber matches");
if (aMessageObject.level == "groupCollapsed") {
ok(aMessageObject.arguments == "a group", "groupCollapsed arguments matches");
}
else if (aMessageObject.level == "group") {
ok(aMessageObject.arguments == "b group", "group arguments matches");
}
else if (aMessageObject.level == "groupEnd") {
ok(Array.prototype.join.call(aMessageObject.arguments, " ") == "b group", "groupEnd arguments matches");
}
if (aMessageObject.level == "groupEnd") {
// Test finished
ConsoleObserver.destroy();
finish();
}
}
function startTraceTest() {
@ -195,6 +238,9 @@ function consoleAPISanityTest() {
ok(win.console.error, "console.error is here");
ok(win.console.trace, "console.trace is here");
ok(win.console.dir, "console.dir is here");
ok(win.console.group, "console.group is here");
ok(win.console.groupCollapsed, "console.groupCollapsed is here");
ok(win.console.groupEnd, "console.groupEnd is here");
}
var ConsoleObserver = {

View File

@ -27,6 +27,12 @@
console.warn(str);
console.error(str);
}
function testGroups() {
console.groupCollapsed("a", "group");
console.group("b", "group");
console.groupEnd("b", "group");
}
</script>
</head>
<body>
@ -34,5 +40,6 @@
<button onclick="test();">Log stuff</button>
<button id="test-trace" onclick="foobar585956a('omg');">Test trace</button>
<button id="test-location" onclick="foobar646025('omg');">Test location</button>
<button id="test-groups" onclick="testGroups();">Test groups</button>
</body>
</html>

View File

@ -27,6 +27,9 @@ function doTest() {
"debug": "function",
"trace": "function",
"dir": "function",
"group": "function",
"groupCollapsed": "function",
"groupEnd": "function",
"__noSuchMethod__": "function"
};