author | Tim Taubert <tim.taubert@gmx.de> |
Fri, 13 Jan 2012 11:40:59 +0100 | |
changeset 84395 | 9b5f1ccdb02163d837e0141de5ccb6e12a07ddf8 |
parent 84381 | 8d4638feec54d4a48e62ba0339cf33080fd77367 (current diff) |
parent 84394 | ed19305f89e68a735422c82dd81ff7c10ec3687d (diff) |
child 84396 | 742d5f9f284db15da07f0cac485fef9f9606fb64 |
child 84544 | ab192fefef70fd024349c01801d4fca70b80597c |
push id | 21843 |
push user | tim.taubert@gmx.de |
push date | Fri, 13 Jan 2012 10:45:53 +0000 |
treeherder | mozilla-central@9b5f1ccdb021 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 12.0a1 |
first release with | nightly win64
9b5f1ccdb021
/
12.0a1
/
20120113031050
/
files
nightly linux32
nightly linux64
nightly mac
nightly win32
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly win64
12.0a1
/
20120113031050
/
pushlog to previous
|
browser/base/content/browser.js | file | annotate | diff | comparison | revisions | |
toolkit/mozapps/update/updater/updater.cpp | file | annotate | diff | comparison | revisions |
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -867,17 +867,17 @@ pref("browser.zoom.siteSpecific", true); // Whether or not to update background tabs to the current zoom level. pref("browser.zoom.updateBackgroundTabs", true); // The breakpad report server to link to in about:crashes pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/"); // base URL for web-based support pages -pref("app.support.baseURL", "http://support.mozilla.com/1/firefox/%VERSION%/%OS%/%LOCALE%/"); +pref("app.support.baseURL", "http://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/"); // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror) pref("security.alternate_certificate_error_page", "certerror"); // Whether to start the private browsing mode at application startup pref("browser.privatebrowsing.autostart", false); // Whether we should skip prompting before starting the private browsing mode
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3930,23 +3930,20 @@ var FullScreen = { this._shouldAnimate = !document.mozFullScreen; this.mouseoverToggle(false); // Autohide prefs gPrefService.addObserver("browser.fullscreen", this, false); } else { // The user may quit fullscreen during an animation - window.mozCancelAnimationFrame(this._animationHandle); - this._animationHandle = 0; - clearTimeout(this._animationTimeout); + this._cancelAnimation(); gNavToolbox.style.marginTop = ""; if (this._isChromeCollapsed) this.mouseoverToggle(true); - this._isAnimating = false; // This is needed if they use the context menu to quit fullscreen this._isPopupOpen = false; this.cleanup(); } }, exitDomFullScreen : function(e) { @@ -3997,20 +3994,17 @@ var FullScreen = { gBrowser.tabContainer.addEventListener("TabClose", this.exitDomFullScreen); gBrowser.tabContainer.addEventListener("TabSelect", this.exitDomFullScreen); // Exit DOM full-screen mode when the browser window loses focus (ALT+TAB, etc). window.addEventListener("deactivate", this.exitDomFullScreen, true); // Cancel any "hide the toolbar" animation which is in progress, and make // the toolbar hide immediately. - clearInterval(this._animationInterval); - clearTimeout(this._animationTimeout); - this._isAnimating = false; - this._shouldAnimate = false; + this._cancelAnimation(); this.mouseoverToggle(false); // If there's a full-screen toggler, remove its listeners, so that mouseover // the top of the screen will not cause the toolbar to re-appear. let fullScrToggler = document.getElementById("fullscr-toggler"); if (fullScrToggler) { fullScrToggler.removeEventListener("mouseover", this._expandCallback, false); fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); @@ -4145,29 +4139,34 @@ var FullScreen = { sample: function (timeStamp) { const duration = 1500; const timePassed = timeStamp - this._animateStartTime; const pos = timePassed >= duration ? 1 : 1 - Math.pow(1 - timePassed / duration, 4); if (pos >= 1) { // We've animated enough - window.mozCancelAnimationFrame(this._animationHandle); + this._cancelAnimation(); gNavToolbox.style.marginTop = ""; - this._animationHandle = 0; - this._isAnimating = false; - this._shouldAnimate = false; // Just to make sure this.mouseoverToggle(false); return; } gNavToolbox.style.marginTop = (gNavToolbox.boxObject.height * pos * -1) + "px"; this._animationHandle = window.mozRequestAnimationFrame(this); }, + _cancelAnimation: function() { + window.mozCancelAnimationFrame(this._animationHandle); + this._animationHandle = 0; + clearTimeout(this._animationTimeout); + this._isAnimating = false; + this._shouldAnimate = false; + }, + cancelWarning: function(event) { if (!this.warningBox) { return; } if (this.onWarningHidden) { this.warningBox.removeEventListener("transitionend", this.onWarningHidden, false); this.onWarningHidden = null; }
--- a/browser/devtools/webconsole/HUDService.jsm +++ b/browser/devtools/webconsole/HUDService.jsm @@ -114,22 +114,39 @@ XPCOMUtils.defineLazyGetter(this, "Autoc Cu.import("resource:///modules/AutocompletePopup.jsm", obj); } catch (err) { Cu.reportError(err); } return obj.AutocompletePopup; }); +XPCOMUtils.defineLazyGetter(this, "ScratchpadManager", function () { + var obj = {}; + try { + Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", obj); + } + catch (err) { + Cu.reportError(err); + } + return obj.ScratchpadManager; +}); + XPCOMUtils.defineLazyGetter(this, "namesAndValuesOf", function () { var obj = {}; Cu.import("resource:///modules/PropertyPanel.jsm", obj); return obj.namesAndValuesOf; }); +XPCOMUtils.defineLazyGetter(this, "gConsoleStorage", function () { + let obj = {}; + Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", obj); + return obj.ConsoleAPIStorage; +}); + function LogFactory(aMessagePrefix) { function log(aMessage) { var _msg = aMessagePrefix + " " + aMessage + "\n"; dump(_msg); } return log; } @@ -1410,16 +1427,28 @@ HUD_SERVICE.prototype = * @returns integer */ getWindowId: function HS_getWindowId(aWindow) { return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID; }, /** + * Gets the ID of the inner window of this DOM window + * + * @param nsIDOMWindow aWindow + * @returns integer + */ + getInnerWindowId: function HS_getInnerWindowId(aWindow) + { + return aWindow.QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; + }, + + /** * Gets the top level content window that has an outer window with * the given ID or returns null if no such content window exists * * @param integer aId * @returns nsIDOMWindow */ getWindowByWindowId: function HS_getWindowByWindowId(aId) { @@ -2140,17 +2169,18 @@ HUD_SERVICE.prototype = let node = ConsoleUtils.createMessageNode(hud.outputNode.ownerDocument, CATEGORY_WEBDEV, LEVELS[level], body, aHUDId, sourceURL, sourceLine, clipboardText, - level); + level, + aMessage.timeStamp); // Make the node bring up the property panel, to allow the user to inspect // the stack trace. if (level == "trace") { node._stacktrace = args; let linkNode = node.querySelector(".webconsole-msg-body"); linkNode.classList.add("hud-clickable"); @@ -2207,28 +2237,48 @@ HUD_SERVICE.prototype = SEVERITY_WARNING, message, aHUDId); ConsoleUtils.outputMessageNode(node, aHUDId); }, /** * 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) - { - 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); + reportPageError: function HS_reportPageError(aScriptError) + { + 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 // errors. let severity = SEVERITY_ERROR; if ((aScriptError.flags & aScriptError.warningFlag) || (aScriptError.flags & aScriptError.strictFlag)) { severity = SEVERITY_WARNING; @@ -2237,22 +2287,24 @@ HUD_SERVICE.prototype = let window = HUDService.getWindowByWindowId(aScriptError.outerWindowID); if (window) { let hudId = HUDService.getHudIdByWindow(window.top); if (hudId) { let outputNode = this.hudReferences[hudId].outputNode; 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); } } }, /** * Register a Gecko app's specialized ApplicationHooks object @@ -2890,29 +2942,31 @@ HUD_SERVICE.prototype = } } let hud; // If there is no HUD for this tab create a new one. if (!hudNode) { // get nBox object and call new HUD let config = { parentNode: nBox, - contentWindow: aContentWindow + contentWindow: aContentWindow.top }; hud = new HeadsUpDisplay(config); HUDService.registerHUDReference(hud); let windowId = this.getWindowId(aContentWindow.top); this.windowIds[windowId] = hudId; hud.progressListener = new ConsoleProgressListener(hudId); _browser.webProgress.addProgressListener(hud.progressListener, Ci.nsIWebProgress.NOTIFY_STATE_ALL); + + hud.displayCachedConsoleMessages(); } else { hud = this.hudReferences[hudId]; if (aContentWindow == aContentWindow.top) { // TODO: name change?? doesn't actually re-attach the console hud.reattachConsole(aContentWindow); } } @@ -3572,16 +3626,68 @@ HeadsUpDisplay.prototype = { } } else { throw new Error("Unsupported Gecko Application"); } }, /** + * Display cached messages that may have been collected before the UI is + * displayed. + * + * @returns void + */ + displayCachedConsoleMessages: function HUD_displayCachedConsoleMessages() + { + let innerWindowId = HUDService.getInnerWindowId(this.contentWindow); + + 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) { + 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 && 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); + } + }, + + /** * Re-attaches a console when the contentWindow is recreated * * @param nsIDOMWindow aContentWindow * @returns void */ reattachConsole: function HUD_reattachConsole(aContentWindow) { this.contentWindow = aContentWindow; @@ -4003,17 +4109,17 @@ HeadsUpDisplay.prototype = { * @return void */ makeClearConsoleButton: function HUD_makeClearConsoleButton(aToolbar) { let hudId = this.hudId; 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(); } } let clearButton = this.makeXULNode("toolbarbutton"); clearButton.setAttribute("label", this.getStr("btnClear")); @@ -4521,17 +4627,17 @@ function JSTermHelper(aJSTerm) }); /** * Clears the output of the JSTerm. */ aJSTerm.sandbox.clear = function JSTH_clear() { aJSTerm.helperEvaluated = true; - aJSTerm.clearOutput(); + aJSTerm.clearOutput(true); }; /** * Returns the result of Object.keys(aObject). * * @param object aObject * Object to return the property names from. * @returns array of string @@ -5113,17 +5219,24 @@ JSTerm.prototype = { let type = aResult === null ? "null" : typeof aResult; if (type == "object" && aResult.constructor && aResult.constructor.name) { type = aResult.constructor.name; } 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 = {}; let node = hud.outputNode; while (node.firstChild) { if (node.firstChild.classList && node.firstChild.classList.contains("webconsole-msg-inspector")) { @@ -5131,16 +5244,21 @@ JSTerm.prototype = { } else { hud.outputNode.removeChild(node.firstChild); } } hud.HUDBox.lastTimestamp = 0; hud.groupDepth = 0; + + if (aClearStorage) { + let windowId = HUDService.getInnerWindowId(hud.contentWindow); + gConsoleStorage.clearEvents(windowId); + } }, /** * Updates the size of the input field (command line) to fit its contents. * * @returns void */ resizeInput: function JST_resizeInput() @@ -5661,16 +5779,21 @@ FirefoxApplicationHooks.prototype = { ////////////////////////////////////////////////////////////////////////////// /** * ConsoleUtils: a collection of globally used functions * */ ConsoleUtils = { + /** + * Flag to turn on and off scrolling. + */ + scroll: true, + supString: function ConsoleUtils_supString(aString) { let str = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); str.data = aString; return str; }, @@ -5704,16 +5827,20 @@ ConsoleUtils = { * Scrolls a node so that it's visible in its containing XUL "scrollbox" * element. * * @param nsIDOMNode aNode * The node to make visible. * @returns void */ scrollToVisible: function ConsoleUtils_scrollToVisible(aNode) { + if (!this.scroll) { + return; + } + // Find the enclosing richlistbox node. let richListBoxNode = aNode.parentNode; while (richListBoxNode.tagName != "richlistbox") { richListBoxNode = richListBoxNode.parentNode; } // Use the scroll box object interface to ensure the element is visible. let boxObject = richListBoxNode.scrollBoxObject; @@ -5741,24 +5868,28 @@ ConsoleUtils = { * The line number on which the error occurred. If zero or omitted, * there is no line number associated with this message. * @param string aClipboardText [optional] * 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. + * @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. */ 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; } // Make the icon container, which is a vertical box. Its purpose is to // ensure that the icon stays anchored at the top of the message even for // long multi-line messages. let iconContainer = aDocument.createElementNS(XUL_NS, "vbox"); @@ -5808,17 +5939,17 @@ ConsoleUtils = { let repeatNode = aDocument.createElementNS(XUL_NS, "label"); repeatNode.setAttribute("value", "1"); repeatNode.classList.add("webconsole-msg-repeat"); repeatContainer.appendChild(repeatNode); // 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); // Create the source location (e.g. www.example.com:6) that sits on the // right side of the message, if applicable. let locationNode; if (aSourceURL) { locationNode = this.createLocationNode(aDocument, aSourceURL, @@ -6514,58 +6645,32 @@ CommandController.prototype = { HUDConsoleObserver = { QueryInterface: XPCOMUtils.generateQI( [Ci.nsIObserver] ), 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); } } }; /** * A WebProgressListener that listens for location changes, to update HUDService * state information on page navigation. * @@ -6670,31 +6775,24 @@ function appName() let name = APP_ID_TABLE[APP_ID]; if (name){ return name; } 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 /////////////////////////////////////////////////////////////////////////// /** * Some commands need customization - this is how we get at them. */ @@ -6727,29 +6825,44 @@ function GcliTerm(aContentWindow, aHudId this.hintNode = aHintNode; this.createUI(); this.createSandbox(); this.show = this.show.bind(this); this.hide = this.hide.bind(this); + // Allow GCLI:Inputter to decide how and when to open a scratchpad window + let scratchpad = { + shouldActivate: function Scratchpad_shouldActivate(aEvent) { + return aEvent.shiftKey && + aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN; + }, + activate: function Scratchpad_activate(aValue) { + aValue = aValue.replace(/^\s*{\s*/, ''); + ScratchpadManager.openScratchpad({ text: aValue }); + return true; + }, + linkText: stringBundle.GetStringFromName('scratchpad.linkText') + }; + this.opts = { environment: { hudId: this.hudId }, chromeDocument: this.document, contentDocument: aContentWindow.document, jsEnvironment: { globalObject: unwrap(aContentWindow), evalFunction: this.evalInSandbox.bind(this) }, inputElement: this.inputNode, completeElement: this.completeNode, inputBackgroundElement: this.inputStack, hintElement: this.hintNode, consoleWrap: aConsoleWrap, + scratchpad: scratchpad, gcliTerm: this }; gcli._internal.commandOutputManager.addListener(this.onCommandOutput, this); gcli._internal.createView(this.opts); if (!commandExports) { commandExports = loadCommands();
--- a/browser/devtools/webconsole/gcli.jsm +++ b/browser/devtools/webconsole/gcli.jsm @@ -5319,17 +5319,18 @@ function getManTemplateData(command, con define('gcli/ui/domtemplate', ['require', 'exports', 'module' ], function(require, exports, module) { var obj = {}; Components.utils.import('resource:///modules/devtools/Templater.jsm', obj); exports.template = obj.template; }); -define("text!gcli/commands/help.css", [], void 0); +define("text!gcli/commands/help.css", [], ""); + define("text!gcli/commands/help_intro.html", [], "\n" + "<h2>${l10n.introHeader}</h2>\n" + "\n" + "<p>\n" + "</p>\n" + ""); define("text!gcli/commands/help_list.html", [], "\n" + @@ -5410,17 +5411,18 @@ function Console(options) { this.inputter = new Inputter({ document: options.chromeDocument, requisition: options.requisition, inputElement: options.inputElement, completeElement: options.completeElement, completionPrompt: '', backgroundElement: options.backgroundElement, - focusManager: this.focusManager + focusManager: this.focusManager, + scratchpad: options.scratchpad }); this.menu = new CommandMenu({ document: options.chromeDocument, requisition: options.requisition, menuClass: 'gcliterm-menu' }); this.hintElement.appendChild(this.menu.element); @@ -5561,34 +5563,36 @@ exports.Console = Console; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -define('gcli/ui/inputter', ['require', 'exports', 'module' , 'gcli/util', 'gcli/types', 'gcli/history', 'text!gcli/ui/inputter.css'], function(require, exports, module) { +define('gcli/ui/inputter', ['require', 'exports', 'module' , 'gcli/util', 'gcli/l10n', 'gcli/types', 'gcli/history', 'text!gcli/ui/inputter.css'], function(require, exports, module) { var cliView = exports; var KeyEvent = require('gcli/util').event.KeyEvent; var dom = require('gcli/util').dom; +var l10n = require('gcli/l10n'); var Status = require('gcli/types').Status; var History = require('gcli/history').History; var inputterCss = require('text!gcli/ui/inputter.css'); /** * A wrapper to take care of the functions concerning an input element */ function Inputter(options) { this.requisition = options.requisition; + this.scratchpad = options.scratchpad; // Suss out where the input element is this.element = options.inputElement || 'gcli-input'; if (typeof this.element === 'string') { this.document = options.document || document; var name = this.element; this.element = this.document.getElementById(name); if (!this.element) { @@ -5860,16 +5864,24 @@ Inputter.prototype.onKeyDown = function( } } }; /** * The main keyboard processing loop */ Inputter.prototype.onKeyUp = function(ev) { + // Give the scratchpad (if enabled) a chance to activate + if (this.scratchpad && this.scratchpad.shouldActivate(ev)) { + if (this.scratchpad.activate(this.element.value)) { + this._setInputInternal('', true); + } + return; + } + // RETURN does a special exec/highlight thing if (ev.keyCode === KeyEvent.DOM_VK_RETURN) { var worst = this.requisition.getStatus(); // Deny RETURN unless the command might work if (worst === Status.VALID) { this._scrollingThroughHistory = false; this.history.add(this.element.value); this.requisition.exec(); @@ -5958,16 +5970,21 @@ Inputter.prototype.getInputState = funct // Workaround for potential XUL bug 676520 where textbox gives incorrect // values for its content if (input.typed == null) { input = { typed: '', cursor: { start: 0, end: 0 } }; console.log('fixing input.typed=""', input); } + // Workaround for a Bug 717268 (which is really a jsdom bug) + if (input.cursor.start == null) { + input.cursor.start = 0; + } + return input; }; cliView.Inputter = Inputter; /** * Completer is an 'input-like' element that sits an input element annotating @@ -5981,16 +5998,17 @@ cliView.Inputter = Inputter; * - completionPrompt (optional) The prompt - defaults to '\u00bb' * (double greater-than, a.k.a right guillemet). The prompt is used directly * in a TextNode, so HTML entities are not allowed. */ function Completer(options) { this.document = options.document || document; this.requisition = options.requisition; this.elementCreated = false; + this.scratchpad = options.scratchpad; this.element = options.completeElement || 'gcli-row-complete'; if (typeof this.element === 'string') { var name = this.element; this.element = this.document.getElementById(name); if (!this.element) { this.elementCreated = true; @@ -6074,16 +6092,21 @@ Completer.prototype.decorate = function( this.resizer(); } }; /** * Ensure that the completion element is the same size and the inputter element */ Completer.prototype.resizer = function() { + // Remove this when jsdom does getBoundingClientRect(). See Bug 717269 + if (!this.inputter.element.getBoundingClientRect) { + return; + } + var rect = this.inputter.element.getBoundingClientRect(); // -4 to line up with 1px of padding and border, top and bottom var height = rect.bottom - rect.top - 4; this.element.style.top = rect.top + 'px'; this.element.style.height = height + 'px'; this.element.style.lineHeight = height + 'px'; this.element.style.left = rect.left + 'px'; @@ -6118,16 +6141,17 @@ Completer.prototype.update = function(in // which is complex due to a need to merge spans. // Bug 707131 questions if we couldn't simplify this to use a template. // // <span class="gcli-prompt">${completionPrompt}</span> // ${appendMarkupStatus()} // ${prefix} // <span class="gcli-in-ontab">${contents}</span> // <span class="gcli-in-closebrace" if="${unclosedJs}">}<span> + // <div class="gcli-in-scratchlink">${scratchLink}</div> var document = this.element.ownerDocument; var prompt = dom.createElement(document, 'span'); prompt.classList.add('gcli-prompt'); prompt.appendChild(document.createTextNode(this.completionPrompt + ' ')); this.element.appendChild(prompt); if (input.typed.length > 0) { @@ -6161,24 +6185,34 @@ Completer.prototype.update = function(in suffix.classList.add('gcli-in-ontab'); suffix.appendChild(document.createTextNode(contents)); this.element.appendChild(suffix); } // Add a grey '}' to the end of the command line when we've opened // with a { but haven't closed it var command = this.requisition.commandAssignment.getValue(); - var unclosedJs = command && command.name === '{' && + var isJsCommand = (command && command.name === '{'); + var isUnclosedJs = isJsCommand && this.requisition.getAssignment(0).getArg().suffix.indexOf('}') === -1; - if (unclosedJs) { + if (isUnclosedJs) { var close = dom.createElement(document, 'span'); close.classList.add('gcli-in-closebrace'); close.appendChild(document.createTextNode(' }')); this.element.appendChild(close); } + + // Create a scratchpad link if it's a JS command and we have a function to + // actually perform the request + if (isJsCommand && this.scratchpad) { + var hint = dom.createElement(document, 'div'); + hint.classList.add('gcli-in-scratchlink'); + hint.appendChild(document.createTextNode(this.scratchpad.linkText)); + this.element.appendChild(hint); + } }; /** * Mark-up an array of Status values with spans */ Completer.prototype.appendMarkupStatus = function(element, scores, input) { if (scores.length === 0) { return; @@ -6281,17 +6315,18 @@ History.prototype.backward = function() if (this._current < this._buffer.length - 1) { this._current++; } return this._buffer[this._current]; }; exports.History = History; -});define("text!gcli/ui/inputter.css", [], void 0); +});define("text!gcli/ui/inputter.css", [], ""); + /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gcli/ui/arg_fetch', ['require', 'exports', 'module' , 'gcli/util', 'gcli/types', 'gcli/ui/field', 'gcli/ui/domtemplate', 'text!gcli/ui/arg_fetch.css', 'text!gcli/ui/arg_fetch.html'], function(require, exports, module) { var argFetch = exports; @@ -7414,31 +7449,33 @@ CommandMenu.prototype.onCommandChange = this.hide(); } }; exports.CommandMenu = CommandMenu; }); -define("text!gcli/ui/menu.css", [], void 0); +define("text!gcli/ui/menu.css", [], ""); + define("text!gcli/ui/menu.html", [], "\n" + "<table class=\"gcli-menu-template\" aria-live=\"polite\">\n" + " <tr class=\"gcli-menu-option\" foreach=\"item in ${items}\"\n" + " onclick=\"${onItemClick}\" title=\"${item.manual || ''}\">\n" + " <td class=\"gcli-menu-name\">${item.name}</td>\n" + " <td class=\"gcli-menu-desc\">${item.description}</td>\n" + " </tr>\n" + " <tr if=\"${error}\">\n" + " <td class=\"gcli-menu-error\" colspan=\"2\">${error}</td>\n" + " </tr>\n" + "</table>\n" + ""); -define("text!gcli/ui/arg_fetch.css", [], void 0); +define("text!gcli/ui/arg_fetch.css", [], ""); + define("text!gcli/ui/arg_fetch.html", [], "\n" + "<!--\n" + "Template for an Assignment.\n" + "Evaluated each time the commandAssignment changes\n" + "-->\n" + "<div class=\"gcli-af-template\" aria-live=\"polite\">\n" + " <div>\n" + " <div class=\"gcli-af-cmddesc\">\n" +
--- a/browser/devtools/webconsole/test/Makefile.in +++ b/browser/devtools/webconsole/test/Makefile.in @@ -145,16 +145,17 @@ include $(topsrcdir)/config/rules.mk browser_webconsole_bug_704295.js \ browser_gcli_inspect.js \ browser_gcli_integrate.js \ browser_gcli_require.js \ browser_gcli_web.js \ browser_webconsole_bug_658368_time_methods.js \ browser_webconsole_bug_622303_persistent_filters.js \ browser_webconsole_window_zombie.js \ + browser_cached_messages.js \ head.js \ $(NULL) _BROWSER_TEST_PAGES = \ test-console.html \ test-network.html \ test-network-request.html \ test-mutation.html \ @@ -217,15 +218,16 @@ include $(topsrcdir)/config/rules.mk test-bug-585956-console-trace.html \ test-bug-644419-log-limits.html \ test-bug-632275-getters.html \ test-bug-646025-console-file-location.html \ test-bug-678816-content.js \ test-file-location.js \ browser_gcli_inspect.html \ test-bug-658368-time-methods.html \ + test-webconsole-error-observer.html \ $(NULL) libs:: $(_BROWSER_TEST_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir) libs:: $(_BROWSER_TEST_PAGES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644 --- /dev/null +++ b/browser/devtools/webconsole/test/browser_cached_messages.js @@ -0,0 +1,83 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is DevTools test code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * David Dahl <ddahl@mozilla.com> + * Mihai Sucan <mihai.sucan@gmail.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"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +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", function onLoad() { + gBrowser.selectedBrowser.removeEventListener("load", onLoad, true); + testOpenUI(true); + }, true); +} + +function testOpenUI(aTestReopen) +{ + // test to see if the messages are + // displayed when the console UI is opened + + HUDService.activateHUDForContext(gBrowser.selectedTab); + let hudId = HUDService.getHudIdByWindow(content); + let hud = HUDService.getHudReferenceById(hudId); + + testLogEntry(hud.outputNode, "log Bazzle", + "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); + + if (aTestReopen) { + HUDService.deactivateHUDForContext(gBrowser.selectedTab); + executeSoon(testOpenUI); + } else { + executeSoon(finish); + } +}
--- a/browser/devtools/webconsole/test/browser_gcli_web.js +++ b/browser/devtools/webconsole/test/browser_gcli_web.js @@ -49,39 +49,83 @@ var define = obj.gcli._internal.define; var console = obj.gcli._internal.console; var Node = Components.interfaces.nsIDOMNode; /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testExec', 'gclitest/testKeyboard', 'gclitest/testHistory', 'gclitest/testRequire', 'gclitest/testJs'], function(require, exports, module) { +define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gcli/types/javascript'], function(require, exports, module) { + + var examiner = require('gclitest/suite').examiner; + var javascript = require('gcli/types/javascript'); + + /** + * Run the tests defined in the test suite + * @param options How the tests are run. Properties include: + * - window: The browser window object to run the tests against + * - useFakeWindow: Use a test subset and a fake DOM to avoid a real document + * - detailedResultLog: console.log test passes and failures in more detail + */ + exports.run = function(options) { + options = options || {}; + + if (options.useFakeWindow) { + // A minimum fake dom to get us through the JS tests + var doc = { title: 'Fake DOM' }; + var fakeWindow = { + window: { document: doc }, + document: doc + }; + + options.window = fakeWindow; + } + + if (options.window) { + javascript.setGlobalObject(options.window); + } + + examiner.run(options); + + if (options.detailedResultLog) { + examiner.log(); + } + else { + console.log('Completed test suite'); + } + }; +}); +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testExec', 'gclitest/testKeyboard', 'gclitest/testScratchpad', 'gclitest/testHistory', 'gclitest/testRequire', 'gclitest/testJs'], function(require, exports, module) { // We need to make sure GCLI is initialized before we begin testing it require('gcli/index'); var examiner = require('test/examiner'); // It's tempting to want to unify these strings and make addSuite() do the // call to require(), however that breaks the build system which looks for // the strings passed to require examiner.addSuite('gclitest/testTokenize', require('gclitest/testTokenize')); examiner.addSuite('gclitest/testSplit', require('gclitest/testSplit')); examiner.addSuite('gclitest/testCli', require('gclitest/testCli')); examiner.addSuite('gclitest/testExec', require('gclitest/testExec')); examiner.addSuite('gclitest/testKeyboard', require('gclitest/testKeyboard')); + examiner.addSuite('gclitest/testScratchpad', require('gclitest/testScratchpad')); examiner.addSuite('gclitest/testHistory', require('gclitest/testHistory')); examiner.addSuite('gclitest/testRequire', require('gclitest/testRequire')); examiner.addSuite('gclitest/testJs', require('gclitest/testJs')); - examiner.run(); - console.log('Completed test suite'); - // examiner.log(); - + exports.examiner = examiner; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('test/examiner', ['require', 'exports', 'module' ], function(require, exports, module) { @@ -114,46 +158,46 @@ var stati = { */ examiner.addSuite = function(name, suite) { examiner.suites[name] = new Suite(name, suite); }; /** * Run all the tests synchronously */ -examiner.run = function() { +examiner.run = function(options) { Object.keys(examiner.suites).forEach(function(suiteName) { var suite = examiner.suites[suiteName]; - suite.run(); + suite.run(options); }.bind(this)); return examiner.suites; }; /** * Run all the tests asynchronously */ -examiner.runAsync = function(callback) { - this.runAsyncInternal(0, callback); +examiner.runAsync = function(options, callback) { + this.runAsyncInternal(0, options, callback); }; /** * Run all the test suits asynchronously */ -examiner.runAsyncInternal = function(i, callback) { +examiner.runAsyncInternal = function(i, options, callback) { if (i >= Object.keys(examiner.suites).length) { if (typeof callback === 'function') { callback(); } return; } var suiteName = Object.keys(examiner.suites)[i]; - examiner.suites[suiteName].runAsync(function() { + examiner.suites[suiteName].runAsync(options, function() { setTimeout(function() { - examiner.runAsyncInternal(i + 1, callback); + examiner.runAsyncInternal(i + 1, options, callback); }.bind(this), delay); }.bind(this)); }; /** * */ examiner.reportToText = function() { @@ -217,65 +261,65 @@ function Suite(suiteName, suite) { this.tests[testName] = test; } }.bind(this)); } /** * Run all the tests in this suite synchronously */ -Suite.prototype.run = function() { +Suite.prototype.run = function(options) { if (typeof this.suite.setup == "function") { - this.suite.setup(); + this.suite.setup(options); } Object.keys(this.tests).forEach(function(testName) { var test = this.tests[testName]; - test.run(); + test.run(options); }.bind(this)); if (typeof this.suite.shutdown == "function") { - this.suite.shutdown(); + this.suite.shutdown(options); } }; /** * Run all the tests in this suite asynchronously */ -Suite.prototype.runAsync = function(callback) { +Suite.prototype.runAsync = function(options, callback) { if (typeof this.suite.setup == "function") { this.suite.setup(); } - this.runAsyncInternal(0, function() { + this.runAsyncInternal(0, options, function() { if (typeof this.suite.shutdown == "function") { this.suite.shutdown(); } if (typeof callback === 'function') { callback(); } }.bind(this)); }; /** * Function used by the async runners that can handle async recursion. */ -Suite.prototype.runAsyncInternal = function(i, callback) { +Suite.prototype.runAsyncInternal = function(i, options, callback) { if (i >= Object.keys(this.tests).length) { if (typeof callback === 'function') { callback(); } return; } var testName = Object.keys(this.tests)[i]; - this.tests[testName].runAsync(function() { + this.tests[testName].runAsync(options, function() { setTimeout(function() { - this.runAsyncInternal(i + 1, callback); + this.runAsyncInternal(i + 1, options, callback); }.bind(this), delay); }.bind(this)); }; /** * Create a JSON object suitable for serialization */ Suite.prototype.toRemote = function() { @@ -299,23 +343,23 @@ function Test(suite, name, func) { this.messages = []; this.status = stati.notrun; } /** * Run just a single test */ -Test.prototype.run = function() { +Test.prototype.run = function(options) { currentTest = this; this.status = stati.executing; this.messages = []; try { - this.func.apply(this.suite); + this.func.apply(this.suite, [ options ]); } catch (ex) { this.status = stati.fail; this.messages.push('' + ex); console.error(ex); if (ex.stack) { console.error(ex.stack); } @@ -326,17 +370,17 @@ Test.prototype.run = function() { } currentTest = null; }; /** * Run all the tests in this suite asynchronously */ -Test.prototype.runAsync = function(callback) { +Test.prototype.runAsync = function(options, callback) { setTimeout(function() { this.run(); if (typeof callback === 'function') { callback(); } }.bind(this), delay); }; @@ -1505,24 +1549,28 @@ function check(initial, action, after) { case KEY_DOWNS_TO: assignment.decrement(); break; } test.is(after, requisition.toString(), initial + ' + ' + action + ' -> ' + after); } -exports.testComplete = function() { +exports.testComplete = function(options) { check('tsela', COMPLETES_TO, 'tselarr '); check('tsn di', COMPLETES_TO, 'tsn dif '); check('tsg a', COMPLETES_TO, 'tsg aaa '); check('{ wind', COMPLETES_TO, '{ window'); check('{ window.docum', COMPLETES_TO, '{ window.document'); - check('{ window.document.titl', COMPLETES_TO, '{ window.document.title '); + + // Bug 717228: This fails under node + if (!options.isNode) { + check('{ window.document.titl', COMPLETES_TO, '{ window.document.title '); + } }; exports.testIncrDecr = function() { check('tsu -70', KEY_UPS_TO, 'tsu -5'); check('tsu -7', KEY_UPS_TO, 'tsu -5'); check('tsu -6', KEY_UPS_TO, 'tsu -5'); check('tsu -5', KEY_UPS_TO, 'tsu -3'); check('tsu -4', KEY_UPS_TO, 'tsu -3'); @@ -1574,16 +1622,69 @@ exports.testIncrDecr = function() { }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ +define('gclitest/testScratchpad', ['require', 'exports', 'module' , 'test/assert'], function(require, exports, module) { + + +var test = require('test/assert'); + +var origScratchpad; + +exports.setup = function(options) { + if (options.inputter) { + origScratchpad = options.inputter.scratchpad; + options.inputter.scratchpad = stubScratchpad; + } +}; + +exports.shutdown = function(options) { + if (options.inputter) { + options.inputter.scratchpad = origScratchpad; + } +}; + +var stubScratchpad = { + shouldActivate: function(ev) { + return true; + }, + activatedCount: 0, + linkText: 'scratchpad.linkText' +}; +stubScratchpad.activate = function(value) { + stubScratchpad.activatedCount++; + return true; +}; + + +exports.testActivate = function(options) { + if (options.inputter) { + var ev = {}; + stubScratchpad.activatedCount = 0; + options.inputter.onKeyUp(ev); + test.is(1, stubScratchpad.activatedCount, 'scratchpad is activated'); + } + else { + console.log('Skipping scratchpad tests'); + } +}; + + +}); +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('gclitest/testHistory', ['require', 'exports', 'module' , 'test/assert', 'gcli/history'], function(require, exports, module) { var test = require('test/assert'); var History = require('gcli/history').History; exports.setup = function() { }; @@ -1823,16 +1924,21 @@ function check(expStatuses, expStatus, e expPredict.forEach(function(p) { contains = predictionsHas(p); test.ok(contains, 'missing prediction ' + p); }); } else if (typeof expPredict === 'number') { contains = true; test.is(assign.getPredictions().length, expPredict, 'prediction count'); + if (assign.getPredictions().length !== expPredict) { + assign.getPredictions().forEach(function(prediction) { + console.log('actual prediction: ', prediction); + }); + } } else { contains = predictionsHas(expPredict); test.ok(contains, 'missing prediction ' + expPredict); } if (!contains) { console.log('Predictions: ' + assign.getPredictions().map(function(p) { @@ -1851,17 +1957,17 @@ exports.testBasic = function() { input('{ w'); check('VVI', Status.ERROR, 'w', 'window'); input('{ windo'); check('VVIIIII', Status.ERROR, 'windo', 'window'); input('{ window'); - check('VVVVVVVV', Status.VALID, 'window', 0); + check('VVVVVVVV', Status.VALID, 'window'); input('{ window.d'); check('VVIIIIIIII', Status.ERROR, 'window.d', 'window.document'); input('{ window.document.title'); check('VVVVVVVVVVVVVVVVVVVVVVV', Status.VALID, 'window.document.title', 0); input('{ d'); @@ -1893,39 +1999,43 @@ exports.testBasic = function() { input('{ donteval.xxx'); check('VVVVVVVVVVVVVV', Status.VALID, 'donteval.xxx', 0); }; }); function undefine() { + delete define.modules['gclitest/index']; delete define.modules['gclitest/suite']; delete define.modules['test/examiner']; delete define.modules['gclitest/testTokenize']; delete define.modules['test/assert']; delete define.modules['gclitest/testSplit']; delete define.modules['gclitest/commands']; delete define.modules['gclitest/testCli']; delete define.modules['gclitest/testExec']; delete define.modules['gclitest/testKeyboard']; + delete define.modules['gclitest/testScratchpad']; delete define.modules['gclitest/testHistory']; delete define.modules['gclitest/testRequire']; delete define.modules['gclitest/requirable']; delete define.modules['gclitest/testJs']; + delete define.globalDomain.modules['gclitest/index']; delete define.globalDomain.modules['gclitest/suite']; delete define.globalDomain.modules['test/examiner']; delete define.globalDomain.modules['gclitest/testTokenize']; delete define.globalDomain.modules['test/assert']; delete define.globalDomain.modules['gclitest/testSplit']; delete define.globalDomain.modules['gclitest/commands']; delete define.globalDomain.modules['gclitest/testCli']; delete define.globalDomain.modules['gclitest/testExec']; delete define.globalDomain.modules['gclitest/testKeyboard']; + delete define.globalDomain.modules['gclitest/testScratchpad']; delete define.globalDomain.modules['gclitest/testHistory']; delete define.globalDomain.modules['gclitest/testRequire']; delete define.globalDomain.modules['gclitest/requirable']; delete define.globalDomain.modules['gclitest/testJs']; } registerCleanupFunction(function() { Services.prefs.clearUserPref("devtools.gcli.enable"); @@ -1943,22 +2053,30 @@ function test() { } function onLoad() { browser.removeEventListener("DOMContentLoaded", onLoad, false); var failed = false; try { openConsole(); - define.globalDomain.require("gclitest/index"); + + var gcliterm = HUDService.getHudByWindow(content).gcliterm; + + var gclitest = define.globalDomain.require("gclitest/index"); + gclitest.run({ + window: gcliterm.document.defaultView, + inputter: gcliterm.opts.console.inputter, + requisition: gcliterm.opts.requistion + }); } catch (ex) { failed = ex; - console.error('Test Failure', ex); - ok(false, '' + ex); + console.error("Test Failure", ex); + ok(false, "" + ex); } finally { closeConsole(); finish(); } if (failed) { throw failed;
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js @@ -43,12 +43,15 @@ registerCleanupFunction(function() { function test() { Services.prefs.setBoolPref("devtools.gcli.enable", false); addTab(TEST_URI); browser.addEventListener("load", function() { 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); }
--- a/browser/devtools/webconsole/test/browser_webconsole_notifications.js +++ b/browser/devtools/webconsole/test/browser_webconsole_notifications.js @@ -14,63 +14,61 @@ * * The Original Code is DevTools test code. * * The Initial Developer of the Original Code is Mozilla Foundation. * Portions created by the Initial Developer are Copyright (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * David Dahl <ddahl@mozilla.com> + * David Dahl <ddahl@mozilla.com> + * Mihai Sucan <mihai.sucan@gmail.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"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html"; +const TEST_URI = "data:text/html,<p>Web Console test for notifications"; function test() { observer.init(); addTab(TEST_URI); - browser.addEventListener("DOMContentLoaded", onLoad, false); + browser.addEventListener("load", onLoad, true); } function webConsoleCreated(aID) { Services.obs.removeObserver(observer, "web-console-created"); - executeSoon(function (){ - ok(HUDService.hudReferences[aID], "We have a hud reference"); - let console = browser.contentWindow.wrappedJSObject.console; - console.log("adding a log message"); - }); + ok(HUDService.hudReferences[aID], "We have a hud reference"); + content.wrappedJSObject.console.log("adding a log message"); } function webConsoleDestroyed(aID) { Services.obs.removeObserver(observer, "web-console-destroyed"); ok(!HUDService.hudReferences[aID], "We do not have a hud reference"); - finishTest(); + executeSoon(finishTest); } function webConsoleMessage(aID, aNodeID) { Services.obs.removeObserver(observer, "web-console-message-created"); ok(aID, "we have a console ID"); - ok(typeof aNodeID == 'string', "message node id is not null"); - closeConsole(); + is(typeof aNodeID, "string", "message node id is a string"); + executeSoon(closeConsole); } let observer = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), observe: function observe(aSubject, aTopic, aData) { @@ -95,11 +93,11 @@ let observer = { { Services.obs.addObserver(this, "web-console-created", false); Services.obs.addObserver(this, "web-console-destroyed", false); Services.obs.addObserver(this, "web-console-message-created", false); } }; function onLoad() { - browser.removeEventListener("DOMContentLoaded", onLoad, false); + browser.removeEventListener("load", onLoad, true); openConsole(); }
new file mode 100644 --- /dev/null +++ b/browser/devtools/webconsole/test/test-webconsole-error-observer.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html dir="ltr" xml:lang="en-US" lang="en-US"> + <head> + <title>WebConsoleErrorObserver test - bug 611032</title> + <!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> + <script type="text/javascript"> + console.log("log Bazzle"); + console.info("info Bazzle"); + console.warn("warn Bazzle"); + console.error("error Bazzle"); + + var foo = {}; + foo.bazBug611032(); + </script> + <style type="text/css"> + .foo { color: cssColorBug611032; } + </style> + </head> + <body> + <h1>WebConsoleErrorObserver test</h1> + </body> +</html> +
--- a/browser/locales/en-US/chrome/browser/devtools/gcli.properties +++ b/browser/locales/en-US/chrome/browser/devtools/gcli.properties @@ -15,17 +15,17 @@ canonDescNone=(No description) # of JavaScript like traditional developer tool command lines. This describes # the '{' command. cliEvalJavascript=Enter JavaScript directly # LOCALIZATION NOTE (fieldSelectionSelect): When a command has a parameter # that has a number of pre-defined options the user interface presents these # in a drop-down menu, where the first 'option' is an indicator that a # selection should be made. This string describes that first option. -fieldSelectionSelect=Select a %S … +fieldSelectionSelect=Select a %S… # LOCALIZATION NOTE (fieldArrayAdd): When a command has a parameter that can # be repeated a number of times (e.g. like the 'cat a.txt b.txt' command) the # user interface presents buttons to add and remove arguments. This string is # used to add arguments. fieldArrayAdd=Add # LOCALIZATION NOTE (fieldArrayDel): When a command has a parameter that can
--- a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties +++ b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties @@ -141,16 +141,21 @@ webConsolePositionBelow=Below webConsolePositionWindow=Window # LOCALIZATION NOTE (webConsoleWindowTitleAndURL): The Web Console floating # panel title, followed by the web page URL. # For RTL languages you need to set the LRM in the string to give the URL # the correct direction. webConsoleWindowTitleAndURL=Web Console - %S +# LOCALIZATION NOTE (scratchpad.linkText): +# The text used in the right hand side of the web console command line when +# Javascript is being entered, to indicate how to jump into scratchpad mode +scratchpad.linkText=Shift+RETURN - Open in Scratchpad + # LOCALIZATION NOTE (Autocomplete.label): # The autocomplete popup panel label/title. Autocomplete.label=Autocomplete popup # LOCALIZATION NOTE (stacktrace.anonymousFunction): # This string is used to display JavaScript functions that have no given name - # they are said to be anonymous. See stacktrace.outputMessage. stacktrace.anonymousFunction=<anonymous>
--- a/browser/themes/gnomestripe/devtools/gcli.css +++ b/browser/themes/gnomestripe/devtools/gcli.css @@ -168,31 +168,29 @@ .gcli-out-shortcut { font-family: "DejaVu Sans Mono", monospace; } /* From: $GCLI/lib/gcli/ui/arg_fetch.css */ .gcli-argfetch { width: 100%; - box-sizing: border-box; -moz-box-sizing: border-box; } .gcli-af-cmddesc { font-weight: bold; text-align: center; margin-bottom: 5px; padding: 3px 10px 0; } .gcli-af-params { padding: 0 10px; width: 100%; - box-sizing: border-box; -moz-box-sizing: border-box; } .gcli-af-paramname { text-align: right; font-size: 90%; } @@ -302,16 +300,23 @@ color: #999; } .gcli-prompt { color: #66F; font-weight: bold; } +.gcli-in-scratchlink { + float: right; + font-size: 85%; + color: #888; + padding-right: 10px; +} + /* From: $GCLI/lib/gcli/commands/help.css */ .gcli-help-name { text-align: end; } .gcli-help-arrow { font-size: 70%;
--- a/browser/themes/pinstripe/devtools/gcli.css +++ b/browser/themes/pinstripe/devtools/gcli.css @@ -172,31 +172,29 @@ .gcli-out-shortcut { font-family: Menlo, Monaco, monospace; } /* From: $GCLI/lib/gcli/ui/arg_fetch.css */ .gcli-argfetch { width: 100%; - box-sizing: border-box; -moz-box-sizing: border-box; } .gcli-af-cmddesc { font-weight: bold; text-align: center; margin-bottom: 5px; padding: 3px 10px 0; } .gcli-af-params { padding: 0 10px; width: 100%; - box-sizing: border-box; -moz-box-sizing: border-box; } .gcli-af-paramname { text-align: right; font-size: 90%; } @@ -306,16 +304,23 @@ color: #999; } .gcli-prompt { color: #66F; font-weight: bold; } +.gcli-in-scratchlink { + float: right; + font-size: 85%; + color: #888; + padding-right: 10px; +} + /* From: $GCLI/lib/gcli/commands/help.css */ .gcli-help-name { text-align: end; } .gcli-help-arrow { font-size: 70%;
--- a/browser/themes/winstripe/devtools/gcli.css +++ b/browser/themes/winstripe/devtools/gcli.css @@ -168,31 +168,29 @@ .gcli-out-shortcut { font-family: Consolas, Inconsolata, "Courier New", monospace; } /* From: $GCLI/lib/gcli/ui/arg_fetch.css */ .gcli-argfetch { width: 100%; - box-sizing: border-box; -moz-box-sizing: border-box; } .gcli-af-cmddesc { font-weight: bold; text-align: center; margin-bottom: 5px; padding: 3px 10px 0; } .gcli-af-params { padding: 0 10px; width: 100%; - box-sizing: border-box; -moz-box-sizing: border-box; } .gcli-af-paramname { text-align: right; font-size: 90%; } @@ -302,16 +300,23 @@ color: #999; } .gcli-prompt { color: #66F; font-weight: bold; } +.gcli-in-scratchlink { + float: right; + font-size: 85%; + color: #888; + padding-right: 10px; +} + /* From: $GCLI/lib/gcli/commands/help.css */ .gcli-help-name { text-align: end; } .gcli-help-arrow { font-size: 70%;
--- a/dom/base/ConsoleAPI.js +++ b/dom/base/ConsoleAPI.js @@ -197,17 +197,18 @@ ConsoleAPI.prototype = { let frame = stack[1]; let consoleEvent = { ID: aOuterWindowID, innerID: aInnerWindowID, level: aLevel, filename: frame.filename, lineNumber: frame.lineNumber, functionName: frame.functionName, - arguments: aArguments + arguments: aArguments, + timeStamp: Date.now(), }; consoleEvent.wrappedJSObject = consoleEvent; ConsoleAPIStorage.recordEvent(aInnerWindowID, consoleEvent); Services.obs.notifyObservers(consoleEvent, "console-api-log-event", aOuterWindowID);
--- a/dom/base/ConsoleAPIStorage.jsm +++ b/dom/base/ConsoleAPIStorage.jsm @@ -116,17 +116,17 @@ var ConsoleAPIStorage = { * @param string aId * The inner window ID for which you want to get the array of cached * events. * @returns array * The array of cached events for the given window. */ getEvents: function CS_getEvents(aId) { - return _consoleStorage[aId] || []; + return (_consoleStorage[aId] || []).slice(0); }, /** * Record an event associated with the given window ID. * * @param string aWindowID * The ID of the inner window for which the event occurred. * @param object aEvent
--- a/toolkit/mozapps/update/updater/bspatch.cpp +++ b/toolkit/mozapps/update/updater/bspatch.cpp @@ -98,28 +98,25 @@ MBS_ApplyPatch(const MBSPatchHeader *hea if (!buf) return MEM_ERROR; int rv = OK; size_t r = header->cblen + header->difflen + header->extralen; unsigned char *wb = buf; while (r) { - size_t c = fread(wb, 1, (r > SSIZE_MAX) ? SSIZE_MAX : r, patchFile); - if (c < 0) { + const size_t count = (r > SSIZE_MAX) ? SSIZE_MAX : r; + size_t c = fread(wb, 1, count, patchFile); + if (c != count) { rv = READ_ERROR; goto end; } r -= c; - - if (c == 0 && r) { - rv = UNEXPECTED_ERROR; - goto end; - } + wb += c; } { MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf; unsigned char *diffsrc = buf + header->cblen; unsigned char *extrasrc = diffsrc + header->difflen; MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc;
--- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -1033,30 +1033,26 @@ PatchFile::LoadSourceFile(FILE* ofile) buf = (unsigned char *) malloc(header.slen); if (!buf) return MEM_ERROR; size_t r = header.slen; unsigned char *rb = buf; while (r) { - size_t c = fread(rb, 1, r, ofile); - if (c < 0) { + const size_t count = mmin(SSIZE_MAX, r); + size_t c = fread(rb, 1, count, ofile); + if (c != count) { LOG(("LoadSourceFile: error reading destination file: " LOG_S "\n", mFile)); return READ_ERROR; } r -= c; rb += c; - - if (c == 0 && r) { - LOG(("LoadSourceFile: expected %d more bytes in destination file\n", r)); - return UNEXPECTED_ERROR; - } } // Verify that the contents of the source file correspond to what we expect. unsigned int crc = crc32(buf, header.slen); if (crc != header.scrc32) { LOG(("LoadSourceFile: destination file crc %d does not match expected " \ @@ -2406,27 +2402,25 @@ GetManifestContents(const NS_tchar *mani char *mbuf = (char *) malloc(ms.st_size + 1); if (!mbuf) return NULL; size_t r = ms.st_size; char *rb = mbuf; while (r) { - size_t c = fread(rb, 1, mmin(SSIZE_MAX, r), mfile); - if (c < 0) { + const size_t count = mmin(SSIZE_MAX, r); + size_t c = fread(rb, 1, count, mfile); + if (c != count) { LOG(("GetManifestContents: error reading manifest file: " LOG_S "\n", manifest)); return NULL; } r -= c; rb += c; - - if (c == 0 && r) - return NULL; } mbuf[ms.st_size] = '\0'; rb = mbuf; #ifndef XP_WIN return rb; #else NS_tchar *wrb = (NS_tchar *) malloc((ms.st_size + 1) * sizeof(NS_tchar));