From f26a3af98aa700e841f607e884d9cacadeb3efea Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Wed, 11 Jan 2012 12:51:49 +0200 Subject: [PATCH] Bug 611032 - Errors from before the Web Console is opened do not show. r=gavin.sharp,rcampbell f=rcampbell --HG-- rename : browser/devtools/webconsole/test/browser_ConsoleAPICachedMessages.js => browser/devtools/webconsole/test/browser_cached_messages.js --- browser/devtools/webconsole/HUDService.jsm | 161 +++++++++++------- browser/devtools/webconsole/test/Makefile.in | 3 +- ...Messages.js => browser_cached_messages.js} | 33 ++-- .../test/browser_webconsole_bug_611795.js | 3 + .../test/test-webconsole-error-observer.html | 24 +++ dom/base/ConsoleAPI.js | 3 +- dom/base/ConsoleAPIStorage.jsm | 2 +- 7 files changed, 148 insertions(+), 81 deletions(-) rename browser/devtools/webconsole/test/{browser_ConsoleAPICachedMessages.js => browser_cached_messages.js} (74%) create mode 100644 browser/devtools/webconsole/test/test-webconsole-error-observer.html diff --git a/browser/devtools/webconsole/HUDService.jsm b/browser/devtools/webconsole/HUDService.jsm index 632bfd8e2d9..c2db89f06f7 100644 --- a/browser/devtools/webconsole/HUDService.jsm +++ b/browser/devtools/webconsole/HUDService.jsm @@ -2159,7 +2159,8 @@ HUD_SERVICE.prototype = sourceURL, sourceLine, clipboardText, - level); + level, + aMessage.timeStamp); // Make the node bring up the property panel, to allow the user to inspect // the stack trace. @@ -2226,18 +2227,38 @@ HUD_SERVICE.prototype = /** * Reports an error in the page source, either JavaScript or CSS. * - * @param number aCategory - * The category of the message; either CATEGORY_CSS or CATEGORY_JS. * @param nsIScriptError aScriptError * The error message to report. * @return void */ - reportPageError: function HS_reportPageError(aCategory, aScriptError) + reportPageError: function HS_reportPageError(aScriptError) { - if (aCategory != CATEGORY_CSS && aCategory != CATEGORY_JS) { - throw Components.Exception("Unsupported category (must be one of CSS " + - "or JS)", Cr.NS_ERROR_INVALID_ARG, - Components.stack.caller); + if (!aScriptError.outerWindowID) { + return; + } + + let category; + + switch (aScriptError.category) { + // We ignore chrome-originating errors as we only care about content. + case "XPConnect JavaScript": + case "component javascript": + case "chrome javascript": + case "chrome registration": + case "XBL": + case "XBL Prototype Handler": + case "XBL Content Sink": + case "xbl javascript": + return; + + case "CSS Parser": + case "CSS Loader": + category = CATEGORY_CSS; + break; + + default: + category = CATEGORY_JS; + break; } // Warnings and legacy strict errors become warnings; other types become @@ -2256,12 +2277,14 @@ HUD_SERVICE.prototype = let chromeDocument = outputNode.ownerDocument; let node = ConsoleUtils.createMessageNode(chromeDocument, - aCategory, + category, severity, aScriptError.errorMessage, hudId, aScriptError.sourceName, - aScriptError.lineNumber); + aScriptError.lineNumber, + null, null, + aScriptError.timeStamp); ConsoleUtils.outputMessageNode(node, hudId); } @@ -3600,23 +3623,46 @@ HeadsUpDisplay.prototype = { */ displayCachedConsoleMessages: function HUD_displayCachedConsoleMessages() { - // Get the messages from the ConsoleStorageService. - let windowId = HUDService.getInnerWindowId(this.contentWindow); + let innerWindowId = HUDService.getInnerWindowId(this.contentWindow); - let messages = gConsoleStorage.getEvents(windowId); + let messages = gConsoleStorage.getEvents(innerWindowId); + + let errors = {}; + Services.console.getMessageArray(errors, {}); + + // Filter the errors to find only those we should display. + let filteredErrors = (errors.value || []).filter(function(aError) { + return aError instanceof Ci.nsIScriptError && + aError.innerWindowID == innerWindowId; + }, this); + + messages.push.apply(messages, filteredErrors); + messages.sort(function(a, b) { return a.timeStamp - b.timeStamp; }); // Turn off scrolling for the moment. ConsoleUtils.scroll = false; + this.outputNode.hidden = true; + // Display all messages. messages.forEach(function(aMessage) { - HUDService.logConsoleAPIMessage(this.hudId, aMessage); + if (aMessage instanceof Ci.nsIScriptError) { + HUDService.reportPageError(aMessage); + } + else { + // In this case the cached message is a console message generated + // by the ConsoleAPI, not an nsIScriptError + HUDService.logConsoleAPIMessage(this.hudId, aMessage); + } }, this); + this.outputNode.hidden = false; ConsoleUtils.scroll = true; // Scroll to bottom. let numChildren = this.outputNode.childNodes.length; - if (numChildren) { + if (numChildren && this.outputNode.clientHeight) { + // We also check the clientHeight to force a reflow, otherwise + // ensureIndexIsVisible() does not work after outputNode.hidden = false. this.outputNode.ensureIndexIsVisible(numChildren - 1); } }, @@ -4053,7 +4099,7 @@ HeadsUpDisplay.prototype = { function HUD_clearButton_onCommand() { let hud = HUDService.getHudReferenceById(hudId); if (hud.jsterm) { - hud.jsterm.clearOutput(); + hud.jsterm.clearOutput(true); } if (hud.gcliterm) { hud.gcliterm.clearOutput(); @@ -4571,7 +4617,7 @@ function JSTermHelper(aJSTerm) aJSTerm.sandbox.clear = function JSTH_clear() { aJSTerm.helperEvaluated = true; - aJSTerm.clearOutput(); + aJSTerm.clearOutput(true); }; /** @@ -5163,7 +5209,14 @@ JSTerm.prototype = { return type.toLowerCase(); }, - clearOutput: function JST_clearOutput() + /** + * Clear the Web Console output. + * + * @param boolean aClearStorage + * True if you want to clear the console messages storage associated to + * this Web Console. + */ + clearOutput: function JST_clearOutput(aClearStorage) { let hud = HUDService.getHudReferenceById(this.hudId); hud.cssNodes = {}; @@ -5181,6 +5234,11 @@ JSTerm.prototype = { hud.HUDBox.lastTimestamp = 0; hud.groupDepth = 0; + + if (aClearStorage) { + let windowId = HUDService.getInnerWindowId(hud.contentWindow); + gConsoleStorage.clearEvents(windowId); + } }, /** @@ -5800,6 +5858,9 @@ ConsoleUtils = { * a string, then the clipboard text must be supplied. * @param number aLevel [optional] * The level of the console API message. + * @param number aTimeStamp [optional] + * The timestamp to use for this message node. If omitted, the current + * date and time is used. * @return nsIDOMNode * The message node: a XUL richlistitem ready to be inserted into * the Web Console output node. @@ -5807,7 +5868,8 @@ ConsoleUtils = { createMessageNode: function ConsoleUtils_createMessageNode(aDocument, aCategory, aSeverity, aBody, aHUDId, aSourceURL, - aSourceLine, aClipboardText, aLevel) { + aSourceLine, aClipboardText, aLevel, + aTimeStamp) { if (typeof aBody != "string" && aClipboardText == null && aBody.innerText) { aClipboardText = aBody.innerText; } @@ -5867,7 +5929,7 @@ ConsoleUtils = { // Create the timestamp. let timestampNode = aDocument.createElementNS(XUL_NS, "label"); timestampNode.classList.add("webconsole-timestamp"); - let timestamp = ConsoleUtils.timestamp(); + let timestamp = aTimeStamp || ConsoleUtils.timestamp(); let timestampString = ConsoleUtils.timestampString(timestamp); timestampNode.setAttribute("value", timestampString); @@ -6573,48 +6635,22 @@ HUDConsoleObserver = { init: function HCO_init() { Services.console.registerListener(this); - Services.obs.addObserver(this, "xpcom-shutdown", false); + Services.obs.addObserver(this, "quit-application-granted", false); }, uninit: function HCO_uninit() { Services.console.unregisterListener(this); - Services.obs.removeObserver(this, "xpcom-shutdown"); + Services.obs.removeObserver(this, "quit-application-granted"); }, observe: function HCO_observe(aSubject, aTopic, aData) { - if (aTopic == "xpcom-shutdown") { + if (aTopic == "quit-application-granted") { this.uninit(); - return; } - - if (!(aSubject instanceof Ci.nsIScriptError) || - !aSubject.outerWindowID) { - return; - } - - switch (aSubject.category) { - // We ignore chrome-originating errors as we only - // care about content. - case "XPConnect JavaScript": - case "component javascript": - case "chrome javascript": - case "chrome registration": - case "XBL": - case "XBL Prototype Handler": - case "XBL Content Sink": - case "xbl javascript": - return; - - case "CSS Parser": - case "CSS Loader": - HUDService.reportPageError(CATEGORY_CSS, aSubject); - return; - - default: - HUDService.reportPageError(CATEGORY_JS, aSubject); - return; + else if (aSubject instanceof Ci.nsIScriptError) { + HUDService.reportPageError(aSubject); } } }; @@ -6729,21 +6765,14 @@ function appName() throw new Error("appName: UNSUPPORTED APPLICATION UUID"); } -/////////////////////////////////////////////////////////////////////////// -// HUDService (exported symbol) -/////////////////////////////////////////////////////////////////////////// - -try { - // start the HUDService - // This is in a try block because we want to kill everything if - // *any* of this fails - var HUDService = new HUD_SERVICE(); -} -catch (ex) { - Cu.reportError("HUDService failed initialization.\n" + ex); - // TODO: kill anything that may have started up - // see bug 568665 -} +XPCOMUtils.defineLazyGetter(this, "HUDService", function () { + try { + return new HUD_SERVICE(); + } + catch (ex) { + Cu.reportError(ex); + } +}); /////////////////////////////////////////////////////////////////////////// // GcliTerm diff --git a/browser/devtools/webconsole/test/Makefile.in b/browser/devtools/webconsole/test/Makefile.in index 05d89cdbe51..8592d9e4df6 100644 --- a/browser/devtools/webconsole/test/Makefile.in +++ b/browser/devtools/webconsole/test/Makefile.in @@ -150,7 +150,7 @@ _BROWSER_TEST_FILES = \ browser_webconsole_bug_658368_time_methods.js \ browser_webconsole_bug_622303_persistent_filters.js \ browser_webconsole_window_zombie.js \ - browser_ConsoleAPICachedMessages.js \ + browser_cached_messages.js \ head.js \ $(NULL) @@ -223,6 +223,7 @@ _BROWSER_TEST_PAGES = \ test-file-location.js \ browser_gcli_inspect.html \ test-bug-658368-time-methods.html \ + test-webconsole-error-observer.html \ $(NULL) libs:: $(_BROWSER_TEST_FILES) diff --git a/browser/devtools/webconsole/test/browser_ConsoleAPICachedMessages.js b/browser/devtools/webconsole/test/browser_cached_messages.js similarity index 74% rename from browser/devtools/webconsole/test/browser_ConsoleAPICachedMessages.js rename to browser/devtools/webconsole/test/browser_cached_messages.js index 523e9d0eff8..da283813b69 100644 --- a/browser/devtools/webconsole/test/browser_ConsoleAPICachedMessages.js +++ b/browser/devtools/webconsole/test/browser_cached_messages.js @@ -36,30 +36,27 @@ * * ***** END LICENSE BLOCK ***** */ -const TEST_URI = "data:text/html,

Web Console test for bug 609890"; +const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-webconsole-error-observer.html"; function test() { waitForExplicitFinish(); + expectUncaughtException(); + gBrowser.selectedTab = gBrowser.addTab(TEST_URI); - gBrowser.selectedBrowser.addEventListener("load", testOpenUI, true); + gBrowser.selectedBrowser.addEventListener("load", function onLoad() { + gBrowser.selectedBrowser.removeEventListener("load", onLoad, true); + testOpenUI(true); + }, true); } -function testOpenUI() +function testOpenUI(aTestReopen) { - gBrowser.selectedBrowser.removeEventListener("load", testOpenUI, true); - // test to see if the messages are // displayed when the console UI is opened - let console = content.wrappedJSObject.console; - console.log("log Bazzle"); - console.info("info Bazzle"); - console.warn("warn Bazzle"); - console.error("error Bazzle"); - HUDService.activateHUDForContext(gBrowser.selectedTab); let hudId = HUDService.getHudIdByWindow(content); let hud = HUDService.getHudReferenceById(hudId); @@ -68,7 +65,19 @@ function testOpenUI() "Find a console log entry from before console UI is opened", false, null); + testLogEntry(hud.outputNode, "error Bazzle", + "Find a console error entry from before console UI is opened", + false, null); + + testLogEntry(hud.outputNode, "bazBug611032", "Found the JavaScript error"); + testLogEntry(hud.outputNode, "cssColorBug611032", "Found the CSS error"); + HUDService.deactivateHUDForContext(gBrowser.selectedTab); - executeSoon(finish); + if (aTestReopen) { + HUDService.deactivateHUDForContext(gBrowser.selectedTab); + executeSoon(testOpenUI); + } else { + executeSoon(finish); + } } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js index 42ee1a6e0d9..8f1ee20c1db 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js @@ -48,6 +48,9 @@ function test() browser.removeEventListener("load", arguments.callee, true); openConsole(); + // Clear cached messages that are shown once the Web Console opens. + HUDService.getHudByWindow(content).jsterm.clearOutput(true); + browser.addEventListener("load", onContentLoaded, true); content.location.reload(); }, true); diff --git a/browser/devtools/webconsole/test/test-webconsole-error-observer.html b/browser/devtools/webconsole/test/test-webconsole-error-observer.html new file mode 100644 index 00000000000..cc08b97bacf --- /dev/null +++ b/browser/devtools/webconsole/test/test-webconsole-error-observer.html @@ -0,0 +1,24 @@ + + + + WebConsoleErrorObserver test - bug 611032 + + + + + +

WebConsoleErrorObserver test

+ + + diff --git a/dom/base/ConsoleAPI.js b/dom/base/ConsoleAPI.js index a2239eab951..6c7799b8513 100644 --- a/dom/base/ConsoleAPI.js +++ b/dom/base/ConsoleAPI.js @@ -202,7 +202,8 @@ ConsoleAPI.prototype = { filename: frame.filename, lineNumber: frame.lineNumber, functionName: frame.functionName, - arguments: aArguments + arguments: aArguments, + timeStamp: Date.now(), }; consoleEvent.wrappedJSObject = consoleEvent; diff --git a/dom/base/ConsoleAPIStorage.jsm b/dom/base/ConsoleAPIStorage.jsm index 4706a888d49..4c57a75dcd6 100644 --- a/dom/base/ConsoleAPIStorage.jsm +++ b/dom/base/ConsoleAPIStorage.jsm @@ -121,7 +121,7 @@ var ConsoleAPIStorage = { */ getEvents: function CS_getEvents(aId) { - return _consoleStorage[aId] || []; + return (_consoleStorage[aId] || []).slice(0); }, /**