Bug 659907 - Expand console object with a dir method that displays an interactive listing of all the properties of an object.; f=rcampbell r=mihai.sucan,bzbarsky sr=bzbarsky

This commit is contained in:
Panos Astithas 2011-06-09 16:27:30 +03:00
Родитель 4ff31f730a
Коммит ce5fb346f7
7 изменённых файлов: 155 добавлений и 13 удалений

Просмотреть файл

@ -158,6 +158,7 @@ const LEVELS = {
info: SEVERITY_INFO,
log: SEVERITY_LOG,
trace: SEVERITY_LOG,
dir: SEVERITY_LOG
};
// The lowest HTTP response code (inclusive) that is considered an error.
@ -1235,6 +1236,10 @@ function pruneConsoleOutputIfNecessary(aHUDId, aCategory)
}
delete hudRef.cssNodes[desc + location];
}
else if (messageNodes[i].classList.contains("webconsole-msg-inspector")) {
hudRef.pruneConsoleDirNode(messageNodes[i]);
continue;
}
messageNodes[i].parentNode.removeChild(messageNodes[i]);
}
@ -1969,6 +1974,13 @@ HUD_SERVICE.prototype =
clipboardText = clipboardText.trimRight();
break;
case "dir":
body = unwrap(args[0]);
clipboardText = body.toString();
sourceURL = aMessage.filename;
sourceLine = aMessage.lineNumber;
break;
default:
Cu.reportError("Unknown Console API log level: " + level);
return;
@ -1980,7 +1992,8 @@ HUD_SERVICE.prototype =
body,
sourceURL,
sourceLine,
clipboardText);
clipboardText,
level);
// Make the node bring up the property panel, to allow the user to inspect
// the stack trace.
@ -2014,6 +2027,14 @@ HUD_SERVICE.prototype =
}
ConsoleUtils.outputMessageNode(node, aHUDId);
if (level == "dir") {
// Initialize the inspector message node, by setting the PropertyTreeView
// object on the tree view. This has to be done *after* the node is
// shown, because the tree binding must be attached first.
let tree = node.querySelector("tree");
tree.view = node.propertyTreeView;
}
},
/**
@ -3786,6 +3807,24 @@ HeadsUpDisplay.prototype = {
aToolbar.appendChild(clearButton);
},
/**
* Destroy the property inspector message node. This performs the necessary
* cleanup for the tree widget and removes it from the DOM.
*
* @param nsIDOMNode aMessageNode
* The message node that contains the property inspector from a
* console.dir call.
*/
pruneConsoleDirNode: function HUD_pruneConsoleDirNode(aMessageNode)
{
aMessageNode.parentNode.removeChild(aMessageNode);
let tree = aMessageNode.querySelector("tree");
tree.parentNode.removeChild(tree);
aMessageNode.propertyTreeView = null;
tree.view = null;
tree = null;
},
/**
* Create the Web Console UI.
*
@ -4794,8 +4833,15 @@ JSTerm.prototype = {
let hud = HUDService.getHudReferenceById(this.hudId);
hud.cssNodes = {};
while (hud.outputNode.firstChild) {
hud.outputNode.removeChild(hud.outputNode.firstChild);
let node = hud.outputNode;
while (node.firstChild) {
if (node.firstChild.classList &&
node.firstChild.classList.contains("webconsole-msg-inspector")) {
hud.pruneConsoleDirNode(node.firstChild);
}
else {
hud.outputNode.removeChild(node.firstChild);
}
}
hud.HUDBox.lastTimestamp = 0;
@ -5400,6 +5446,8 @@ ConsoleUtils = {
* The text that should be copied to the clipboard when this node is
* copied. If omitted, defaults to the body text. If `aBody` is not
* a string, then the clipboard text must be supplied.
* @param number aLevel [optional]
* The level of the console API message.
* @return nsIDOMNode
* The message node: a XUL richlistitem ready to be inserted into
* the Web Console output node.
@ -5407,7 +5455,7 @@ ConsoleUtils = {
createMessageNode:
function ConsoleUtils_createMessageNode(aDocument, aCategory, aSeverity,
aBody, aSourceURL, aSourceLine,
aClipboardText) {
aClipboardText, aLevel) {
if (aBody instanceof Ci.nsIDOMNode && aClipboardText == null) {
throw new Error("HUDService.createMessageNode(): DOM node supplied " +
"without any clipboard text");
@ -5435,12 +5483,15 @@ ConsoleUtils = {
bodyNode.setAttribute("flex", "1");
bodyNode.classList.add("webconsole-msg-body");
// Store the body text, since it is needed later for the property tree
// case.
let body = aBody;
// If a string was supplied for the body, turn it into a DOM node and an
// associated clipboard string now.
aClipboardText = aClipboardText ||
(aBody + (aSourceURL ? " @ " + aSourceURL : "") +
(aSourceLine ? ":" + aSourceLine : ""));
aBody = aBody instanceof Ci.nsIDOMNode ?
aBody = aBody instanceof Ci.nsIDOMNode && !(aLevel == "dir") ?
aBody : aDocument.createTextNode(aBody);
bodyNode.appendChild(aBody);
@ -5475,12 +5526,47 @@ ConsoleUtils = {
node.timestamp = timestamp;
ConsoleUtils.setMessageType(node, aCategory, aSeverity);
node.appendChild(timestampNode); // childNode[0]
node.appendChild(iconContainer); // childNode[1]
node.appendChild(bodyNode); // childNode[2]
node.appendChild(repeatContainer); // childNode[3]
node.appendChild(timestampNode);
node.appendChild(iconContainer);
// Display the object tree after the message node.
if (aLevel == "dir") {
// Make the body container, which is a vertical box, for grouping the text
// and tree widgets.
let bodyContainer = aDocument.createElement("vbox");
bodyContainer.setAttribute("flex", "1");
bodyContainer.appendChild(bodyNode);
// Create the tree.
let tree = createElement(aDocument, "tree", {
flex: 1,
hidecolumnpicker: "true"
});
let treecols = aDocument.createElement("treecols");
let treecol = createElement(aDocument, "treecol", {
primary: "true",
flex: 1,
hideheader: "true",
ignoreincolumnpicker: "true"
});
treecols.appendChild(treecol);
tree.appendChild(treecols);
tree.appendChild(aDocument.createElement("treechildren"));
bodyContainer.appendChild(tree);
node.appendChild(bodyContainer);
node.classList.add("webconsole-msg-inspector");
// Create the treeView object.
let treeView = node.propertyTreeView = new PropertyTreeView();
treeView.data = body;
tree.setAttribute("rows", treeView.rowCount);
}
else {
node.appendChild(bodyNode);
}
node.appendChild(repeatContainer);
if (locationNode) {
node.appendChild(locationNode); // childNode[4]
node.appendChild(locationNode);
}
node.setAttribute("id", "console-msg-" + HUDService.sequenceId());
@ -5683,7 +5769,7 @@ ConsoleUtils = {
let lastMessage = aOutput.lastChild;
// childNodes[2] is the description element
if (lastMessage &&
if (lastMessage && !aNode.classList.contains("webconsole-msg-inspector") &&
aNode.childNodes[2].textContent ==
lastMessage.childNodes[2].textContent) {
this.mergeFilteredMessageNode(lastMessage, aNode);
@ -5717,7 +5803,7 @@ ConsoleUtils = {
(aNode.classList.contains("webconsole-msg-console") ||
aNode.classList.contains("webconsole-msg-exception") ||
aNode.classList.contains("webconsole-msg-error"))) {
isRepeated = this.filterRepeatedConsole(aNode, outputNode, aHUDId);
isRepeated = this.filterRepeatedConsole(aNode, outputNode);
}
if (!isRepeated) {

Просмотреть файл

@ -142,6 +142,7 @@ _BROWSER_TEST_FILES = \
browser_webconsole_bug_660806_history_nav.js \
browser_webconsole_bug_651501_document_body_autocomplete.js \
browser_webconsole_bug_653531_highlighter_console_helper.js \
browser_webconsole_bug_659907_console_dir.js \
head.js \
$(NULL)

Просмотреть файл

@ -0,0 +1,45 @@
/* 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.dir works as intended.
function test() {
addTab("data:text/html,Web Console test for bug 659907: Expand console " +
"object with a dir method");
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.dir(content.document);
findLogEntry("[object HTMLDocument");
let msg = outputNode.querySelectorAll(".webconsole-msg-inspector");
is(msg.length, 1, "one message node displayed");
let rows = msg[0].propertyTreeView._rows;
let foundQSA = false;
let foundLocation = false;
let foundWrite = false;
for (let i = 0; i < rows.length; i++) {
if (rows[i].display == "querySelectorAll: function querySelectorAll()") {
foundQSA = true;
}
else if (rows[i].display == "location: Object") {
foundLocation = true;
}
else if (rows[i].display == "write: function write()") {
foundWrite = true;
}
}
ok(foundQSA, "found document.querySelectorAll");
ok(foundLocation, "found document.location");
ok(foundWrite, "found document.write");
finishTest();
}

Просмотреть файл

@ -9,7 +9,6 @@
console.exception()
console.assert()
console.clear()
console.dir()
console.dirxml()
console.group()
console.groupCollapsed()

Просмотреть файл

@ -83,6 +83,10 @@ ConsoleAPI.prototype = {
trace: function CA_trace() {
self.notifyObservers(id, "trace", self.getStackTrace());
},
// Displays an interactive listing of all the properties of an object.
dir: function CA_dir() {
self.notifyObservers(id, "dir", arguments);
},
__exposedProps__: {
log: "r",
info: "r",
@ -90,6 +94,7 @@ ConsoleAPI.prototype = {
error: "r",
debug: "r",
trace: "r",
dir: "r"
}
};
@ -107,6 +112,7 @@ ConsoleAPI.prototype = {
error: genPropDesc('error'),
debug: genPropDesc('debug'),
trace: genPropDesc('trace'),
dir: genPropDesc('dir'),
__noSuchMethod__: { enumerable: true, configurable: true, writable: true,
value: function() {} },
__mozillaConsole__: { value: true }

Просмотреть файл

@ -164,6 +164,9 @@ function observeConsoleTest() {
expect("warn", "arg", "extra arg", 1);
win.console.warn("arg", "extra arg", 1);
expect("dir", win.toString());
win.console.dir(win);
expect("error", "arg");
win.console.error("arg");
}
@ -178,6 +181,7 @@ function consoleAPISanityTest() {
ok(win.console.warn, "console.warn is here");
ok(win.console.error, "console.error is here");
ok(win.console.trace, "console.trace is here");
ok(win.console.dir, "console.dir is here");
}
var ConsoleObserver = {

Просмотреть файл

@ -27,6 +27,7 @@ function doTest() {
"error": "function",
"debug": "function",
"trace": "function",
"dir": "function",
"__noSuchMethod__": "function"
};