Bug 1256768 - Fix ESLint errors/warnings in devtools/client/webconsole/console-output.js draft
authorMichael Kohler <mkohler@picobudget.com>
Sat, 20 May 2017 22:54:41 +0200
changeset 582069 8efacd763a468e8965aad036e67ec2c4c152d753
parent 581473 8d60d0f825110cfb646ac31dc16dc011708bcf34
child 629657 f76719c78d494c3ab7757b5c1048ecfb6ed24879
push id59958
push userbmo:me@michaelkohler.info
push dateSat, 20 May 2017 22:31:48 +0000
bugs1256768
milestone55.0a1
Bug 1256768 - Fix ESLint errors/warnings in devtools/client/webconsole/console-output.js MozReview-Commit-ID: 76jPTnoqWq7
.eslintignore
devtools/client/webconsole/console-output.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -117,17 +117,16 @@ devtools/client/storage/test/*.html
 !devtools/client/storage/test/storage-cookies.html
 !devtools/client/storage/test/storage-overflow.html
 !devtools/client/storage/test/storage-search.html
 !devtools/client/storage/test/storage-unsecured-iframe.html
 !devtools/client/storage/test/storage-unsecured-iframe-usercontextid.html
 devtools/client/webaudioeditor/**
 devtools/client/webconsole/net/**
 devtools/client/webconsole/test/**
-devtools/client/webconsole/console-output.js
 devtools/client/webconsole/hudservice.js
 devtools/client/webconsole/webconsole-connection-proxy.js
 devtools/client/webconsole/webconsole.js
 devtools/client/webide/**
 !devtools/client/webide/components/webideCli.js
 devtools/server/tests/browser/storage-*.html
 !devtools/server/tests/browser/storage-unsecured-iframe.html
 devtools/server/tests/browser/stylesheets-nested-iframes.html
--- a/devtools/client/webconsole/console-output.js
+++ b/devtools/client/webconsole/console-output.js
@@ -1,29 +1,28 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const {Ci, Cu} = require("chrome");
+const {Ci} = require("chrome");
 
 loader.lazyImporter(this, "VariablesView", "resource://devtools/client/shared/widgets/VariablesView.jsm");
 loader.lazyImporter(this, "escapeHTML", "resource://devtools/client/shared/widgets/VariablesView.jsm");
 
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
 loader.lazyRequireGetter(this, "TableWidget", "devtools/client/shared/widgets/TableWidget", true);
 loader.lazyRequireGetter(this, "ObjectClient", "devtools/shared/client/main", true);
 
 const { extend } = require("sdk/core/heritage");
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
 const { getSourceNames } = require("devtools/client/shared/source-utils");
 const {Task} = require("devtools/shared/task");
 const l10n = require("devtools/client/webconsole/webconsole-l10n");
 const nodeConstants = require("devtools/shared/dom-node-constants");
 const {PluralForm} = require("devtools/shared/plural-form");
 
@@ -113,17 +112,21 @@ const CONSOLE_API_LEVELS_TO_SEVERITIES =
 // Array of known message source URLs we need to hide from output.
 const IGNORED_SOURCE_URLS = ["debugger eval code"];
 
 // The maximum length of strings to be displayed by the Web Console.
 const MAX_LONG_STRING_LENGTH = 200000;
 
 // Regular expression that matches the allowed CSS property names when using
 // the `window.console` API.
-const RE_ALLOWED_STYLES = /^(?:-moz-)?(?:background|border|box|clear|color|cursor|display|float|font|line|margin|padding|text|transition|outline|white-space|word|writing|(?:min-|max-)?width|(?:min-|max-)?height)/;
+const RE_ALLOWED_STYLES = new RegExp(["^(?:-moz-)?(?:background|border|box|clear|" +
+                                      "color|cursor|display|float|font|line|margin|" +
+                                      "padding|text|transition|outline|white-space|" +
+                                      "word|writing|(?:min-|max-)?width|" +
+                                      "(?:min-|max-)?height)"]);
 
 // Regular expressions to search and replace with 'notallowed' in the styles
 // given to the `window.console` API methods.
 const RE_CLEANUP_STYLES = [
   // url(), -moz-element()
   /\b(?:url|(?:-moz-)?element)[\s('"]+/gi,
 
   // various URL protocols
@@ -145,18 +148,17 @@ const TABLE_COLUMN_MAX_ITEMS = 10;
  *        The console output owner. This usually the WebConsoleFrame instance.
  *        Any other object can be used, as long as it has the following
  *        properties and methods:
  *          - window
  *          - document
  *          - outputMessage(category, methodOrNode[, methodArguments])
  *            TODO: this is needed temporarily, until bug 778766 is fixed.
  */
-function ConsoleOutput(owner)
-{
+function ConsoleOutput(owner) {
   this.owner = owner;
   this._onFlushOutputMessage = this._onFlushOutputMessage.bind(this);
 }
 
 ConsoleOutput.prototype = {
   _dummyElement: null,
 
   /**
@@ -201,30 +203,28 @@ ConsoleOutput.prototype = {
 
   /**
    * Release an actor.
    *
    * @private
    * @param string actorId
    *        The actor ID you want to release.
    */
-  _releaseObject: function (actorId)
-  {
+  _releaseObject: function (actorId) {
     this.owner._releaseObject(actorId);
   },
 
   /**
    * Add a message to output.
    *
    * @param object ...args
    *        Any number of Message objects.
    * @return this
    */
-  addMessage: function (...args)
-  {
+  addMessage: function (...args) {
     for (let msg of args) {
       msg.init(this);
       this.owner.outputMessage(msg._categoryCompat, this._onFlushOutputMessage,
                                [msg]);
     }
     return this;
   },
 
@@ -237,33 +237,31 @@ ConsoleOutput.prototype = {
    * TODO: remove this method once bug 778766 is fixed.
    *
    * @private
    * @param object message
    *        The message object to render.
    * @return DOMElement
    *         The message DOM element that can be added to the console output.
    */
-  _onFlushOutputMessage: function (message)
-  {
+  _onFlushOutputMessage: function (message) {
     return message.render().element;
   },
 
   /**
    * Get an array of selected messages. This list is based on the text selection
    * start and end points.
    *
    * @param number [limit]
    *        Optional limit of selected messages you want. If no value is given,
    *        all of the selected messages are returned.
    * @return array
    *         Array of DOM elements for each message that is currently selected.
    */
-  getSelectedMessages: function (limit)
-  {
+  getSelectedMessages: function (limit) {
     let selection = this.window.getSelection();
     if (selection.isCollapsed) {
       return [];
     }
 
     if (selection.containsNode(this.element, true)) {
       return Array.slice(this.element.children);
     }
@@ -298,81 +296,75 @@ ConsoleOutput.prototype = {
   /**
    * Find the DOM element of a message for any given descendant.
    *
    * @param DOMElement elem
    *        The element to start the search from.
    * @return DOMElement|null
    *         The DOM element of the message, if any.
    */
-  getMessageForElement: function (elem)
-  {
+  getMessageForElement: function (elem) {
     while (elem && elem.parentNode) {
       if (elem.classList && elem.classList.contains("message")) {
         return elem;
       }
       elem = elem.parentNode;
     }
     return null;
   },
 
   /**
    * Select all messages.
    */
-  selectAllMessages: function ()
-  {
+  selectAllMessages: function () {
     let selection = this.window.getSelection();
     selection.removeAllRanges();
     let range = this.document.createRange();
     range.selectNodeContents(this.element);
     selection.addRange(range);
   },
 
   /**
    * Add a message to the selection.
    *
    * @param DOMElement elem
    *        The message element to select.
    */
-  selectMessage: function (elem)
-  {
+  selectMessage: function (elem) {
     let selection = this.window.getSelection();
     selection.removeAllRanges();
     let range = this.document.createRange();
     range.selectNodeContents(elem);
     selection.addRange(range);
   },
 
   /**
    * Open an URL in a new tab.
    * @see WebConsole.openLink() in hudservice.js
    */
-  openLink: function ()
-  {
+  openLink: function () {
     this.owner.owner.openLink.apply(this.owner.owner, arguments);
   },
 
   openLocationInDebugger: function ({url, line}) {
     return this.owner.owner.viewSourceInDebugger(url, line);
   },
 
   /**
    * Open the variables view to inspect an object actor.
    * @see JSTerm.openVariablesView() in webconsole.js
    */
-  openVariablesView: function ()
-  {
+  openVariablesView: function () {
     this.owner.jsterm.openVariablesView.apply(this.owner.jsterm, arguments);
   },
 
   /**
    * Destroy this ConsoleOutput instance.
    */
-  destroy: function ()
-  {
+  destroy: function () {
     this._dummyElement = null;
     this.owner = null;
   },
 }; // ConsoleOutput.prototype
 
 /**
  * Message objects container.
  * @type object
@@ -380,18 +372,17 @@ ConsoleOutput.prototype = {
 var Messages = {};
 
 /**
  * The BaseMessage object is used for all types of messages. Every kind of
  * message should use this object as its base.
  *
  * @constructor
  */
-Messages.BaseMessage = function ()
-{
+Messages.BaseMessage = function () {
   this.widgets = new Set();
   this._onClickAnchor = this._onClickAnchor.bind(this);
   this._repeatID = { uid: gSequenceId() };
   this.textContent = "";
 };
 
 Messages.BaseMessage.prototype = {
   /**
@@ -466,58 +457,54 @@ Messages.BaseMessage.prototype = {
    * Initialize the message.
    *
    * @param object output
    *        The ConsoleOutput owner.
    * @param object [parent=null]
    *        Optional: a different message object that owns this instance.
    * @return this
    */
-  init: function (output, parent = null)
-  {
+  init: function (output, parent = null) {
     this.output = output;
     this.parent = parent;
     return this;
   },
 
   /**
    * Non-unique ID for this message object used for tracking duplicate messages.
    * Different message kinds can identify themselves based their own criteria.
    *
    * @return string
    */
-  getRepeatID: function ()
-  {
+  getRepeatID: function () {
     return JSON.stringify(this._repeatID);
   },
 
   /**
    * Render the message. After this method is invoked the |element| property
    * will point to the DOM element of this message.
    * @return this
    */
-  render: function ()
-  {
+  render: function () {
     if (!this.element) {
       this.element = this._renderCompat();
     }
     return this;
   },
 
   /**
    * Prepare the message container for the Web Console, such that it is
    * compatible with the current implementation.
    * TODO: remove this once bug 778766 is fixed.
    *
    * @private
    * @return Element
    *         The DOM element that wraps the message.
    */
-  _renderCompat: function ()
-  {
+  _renderCompat: function () {
     let doc = this.output.document;
     let container = doc.createElementNS(XHTML_NS, "div");
     container.id = "console-msg-" + gSequenceId();
     container.className = "message";
     if (this.category == "input") {
       // Assistive technology tools shouldn't echo input to the user,
       // as the user knows what they've just typed.
       container.setAttribute("aria-live", "off");
@@ -539,41 +526,38 @@ Messages.BaseMessage.prototype = {
    *
    * @private
    * @param Element element
    *        The DOM element to which you want to add a click event handler.
    * @param function [callback=this._onClickAnchor]
    *        Optional click event handler. The default event handler is
    *        |this._onClickAnchor|.
    */
-  _addLinkCallback: function (element, callback = this._onClickAnchor)
-  {
+  _addLinkCallback: function (element, callback = this._onClickAnchor) {
     // This is going into the WebConsoleFrame object instance that owns
     // the ConsoleOutput object. The WebConsoleFrame owner is the WebConsole
     // object instance from hudservice.js.
     // TODO: move _addMessageLinkCallback() into ConsoleOutput once bug 778766
     // is fixed.
     this.output.owner._addMessageLinkCallback(element, callback);
   },
 
   /**
    * The default |click| event handler for links in the output. This function
    * opens the anchor's link in a new tab.
    *
    * @private
    * @param Event event
    *        The DOM event that invoked this function.
    */
-  _onClickAnchor: function (event)
-  {
+  _onClickAnchor: function (event) {
     this.output.openLink(event.target.href);
   },
 
-  destroy: function ()
-  {
+  destroy: function () {
     // Destroy all widgets that have registered themselves in this.widgets
     for (let widget of this.widgets) {
       widget.destroy();
     }
     this.widgets.clear();
   }
 };
 
@@ -816,18 +800,17 @@ Messages.Simple.prototype = extend(Messa
   },
 
   get _filterKeyCompat() {
     return this._categoryCompat !== null && this._severityCompat !== null ?
            COMPAT.PREFERENCE_KEYS[this._categoryCompat][this._severityCompat] :
            null;
   },
 
-  init: function ()
-  {
+  init: function () {
     Messages.BaseMessage.prototype.init.apply(this, arguments);
     this._groupDepthCompat = this.output.owner.groupDepth;
     this._initRepeatID();
     return this;
   },
 
   /**
    * Tells if the message can be expanded/collapsed.
@@ -838,18 +821,17 @@ Messages.Simple.prototype = extend(Messa
   /**
    * Getter that tells if this message is collapsed - no details are shown.
    * @type boolean
    */
   get collapsed() {
     return this.collapsible && this.element && !this.element.hasAttribute("open");
   },
 
-  _initRepeatID: function ()
-  {
+  _initRepeatID: function () {
     if (!this._filterDuplicates) {
       return;
     }
 
     // Add the properties we care about for identifying duplicate messages.
     let rid = this._repeatID;
     delete rid.uid;
 
@@ -860,29 +842,27 @@ Messages.Simple.prototype = extend(Messa
     rid.location = this.location;
     rid.link = this._link;
     rid.linkCallback = this._linkCallback + "";
     rid.className = this._className;
     rid.groupDepth = this._groupDepthCompat;
     rid.textContent = "";
   },
 
-  getRepeatID: function ()
-  {
+  getRepeatID: function () {
     // No point in returning a string that includes other properties when there
     // is a unique ID.
     if (this._repeatID.uid) {
       return JSON.stringify({ uid: this._repeatID.uid });
     }
 
     return JSON.stringify(this._repeatID);
   },
 
-  render: function ()
-  {
+  render: function () {
     if (this.element) {
       return this;
     }
 
     let timestamp = new Widgets.MessageTimestamp(this, this.timestamp).render();
 
     let icon = this.document.createElementNS(XHTML_NS, "span");
     icon.className = "icon";
@@ -946,18 +926,17 @@ Messages.Simple.prototype = extend(Messa
     return this;
   },
 
   /**
    * Render the message body DOM element.
    * @private
    * @return Element
    */
-  _renderBody: function ()
-  {
+  _renderBody: function () {
     let bodyWrapper = this.document.createElementNS(XHTML_NS, "span");
     bodyWrapper.className = "message-body-wrapper";
 
     let bodyFlex = this.document.createElementNS(XHTML_NS, "span");
     bodyFlex.className = "message-flex-body";
     bodyWrapper.appendChild(bodyFlex);
 
     let body = this.document.createElementNS(XHTML_NS, "span");
@@ -1009,18 +988,17 @@ Messages.Simple.prototype = extend(Messa
     return bodyWrapper;
   },
 
   /**
    * Render the repeat bubble DOM element part of the message.
    * @private
    * @return Element
    */
-  _renderRepeatNode: function ()
-  {
+  _renderRepeatNode: function () {
     if (!this._filterDuplicates) {
       return null;
     }
 
     let repeatNode = this.document.createElementNS(XHTML_NS, "span");
     repeatNode.setAttribute("value", "1");
     repeatNode.className = "message-repeats";
     repeatNode.textContent = 1;
@@ -1028,18 +1006,17 @@ Messages.Simple.prototype = extend(Messa
     return repeatNode;
   },
 
   /**
    * Render the message source location DOM element.
    * @private
    * @return Element
    */
-  _renderLocation: function ()
-  {
+  _renderLocation: function () {
     if (!this.location) {
       return null;
     }
 
     let {url, line, column} = this.location;
     if (IGNORED_SOURCE_URLS.indexOf(url) != -1) {
       return null;
     }
@@ -1053,55 +1030,51 @@ Messages.Simple.prototype = extend(Messa
    * The click event handler for the message expander arrow element. This method
    * toggles the display of message details.
    *
    * @private
    * @param nsIDOMEvent ev
    *        The DOM event object.
    * @see this.toggleDetails()
    */
-  _onClickCollapsible: function (ev)
-  {
+  _onClickCollapsible: function (ev) {
     ev.preventDefault();
     this.toggleDetails();
   },
 
   /**
    * Expand/collapse message details.
    */
-  toggleDetails: function ()
-  {
+  toggleDetails: function () {
     let twisty = this.element.querySelector(".theme-twisty");
     if (this.element.hasAttribute("open")) {
       this.element.removeAttribute("open");
       twisty.removeAttribute("open");
     } else {
       this.element.setAttribute("open", true);
       twisty.setAttribute("open", true);
     }
   },
 }); // Messages.Simple.prototype
 
-
 /**
  * The Extended message.
  *
  * @constructor
  * @extends Messages.Simple
  * @param array messagePieces
  *        The message to display given as an array of elements. Each array
  *        element can be a DOM node, function, ObjectActor, LongString or
  *        a string.
  * @param object [options]
  *        Options for rendering this message:
  *        - quoteStrings: boolean that tells if you want strings to be wrapped
  *        in quotes or not.
  */
-Messages.Extended = function (messagePieces, options = {})
-{
+Messages.Extended = function (messagePieces, options = {}) {
   Messages.Simple.call(this, null, options);
 
   this._messagePieces = messagePieces;
 
   if ("quoteStrings" in options) {
     this._quoteStrings = options.quoteStrings;
   }
 
@@ -1120,32 +1093,30 @@ Messages.Extended.prototype = extend(Mes
 
   /**
    * Boolean that tells if the strings displayed in this message are wrapped.
    * @private
    * @type boolean
    */
   _quoteStrings: true,
 
-  getRepeatID: function ()
-  {
+  getRepeatID: function () {
     if (this._repeatID.uid) {
       return JSON.stringify({ uid: this._repeatID.uid });
     }
 
     // Sets are not stringified correctly. Temporarily switching to an array.
     let actors = this._repeatID.actors;
     this._repeatID.actors = [...actors];
     let result = JSON.stringify(this._repeatID);
     this._repeatID.actors = actors;
     return result;
   },
 
-  render: function ()
-  {
+  render: function () {
     let result = this.document.createDocumentFragment();
 
     for (let i = 0; i < this._messagePieces.length; i++) {
       let separator = i > 0 ? this._renderBodyPieceSeparator() : null;
       if (separator) {
         result.appendChild(separator);
       }
 
@@ -1159,29 +1130,30 @@ Messages.Extended.prototype = extend(Mes
   },
 
   /**
    * Render the separator between the pieces of the message.
    *
    * @private
    * @return Element
    */
-  _renderBodyPieceSeparator: function () { return null; },
+  _renderBodyPieceSeparator: function () {
+    return null;
+  },
 
   /**
    * Render one piece/element of the message array.
    *
    * @private
    * @param mixed piece
    *        Message element to display - this can be a LongString, ObjectActor,
    *        DOM node or a function to invoke.
    * @return Element
    */
-  _renderBodyPiece: function (piece, options = {})
-  {
+  _renderBodyPiece: function (piece, options = {}) {
     if (piece instanceof Ci.nsIDOMNode) {
       return piece;
     }
     if (typeof piece == "function") {
       return piece(this);
     }
 
     return this._renderValueGrip(piece, options);
@@ -1202,18 +1174,17 @@ Messages.Extended.prototype = extend(Mes
    *        grip. This is typically set to true when the object needs to be
    *        displayed in an array preview, or as a property value in object
    *        previews, etc.
    *        - shorten - boolean that tells the renderer to display a truncated
    *        grip.
    * @return DOMElement
    *         The DOM element that displays the given grip.
    */
-  _renderValueGrip: function (grip, options = {})
-  {
+  _renderValueGrip: function (grip, options = {}) {
     let isPrimitive = VariablesView.isPrimitive({ value: grip });
     let isActorGrip = WebConsoleUtils.isActorGrip(grip);
     let noStringQuotes = !this._quoteStrings;
     if ("noStringQuotes" in options) {
       noStringQuotes = options.noStringQuotes;
     }
 
     if (isActorGrip) {
@@ -1230,17 +1201,17 @@ Messages.Extended.prototype = extend(Mes
 
     let unshortenedGrip = grip;
     if (options.shorten) {
       grip = this.shortenValueGrip(grip);
     }
 
     let result = this.document.createElementNS(XHTML_NS, "span");
     if (isPrimitive) {
-      if (Widgets.URLString.prototype.containsURL.call(Widgets.URLString.prototype, grip)) {
+      if (Widgets.URLString.prototype.containsURL(grip)) {
         let widget = new Widgets.URLString(this, grip, unshortenedGrip).render();
         return widget.element;
       }
 
       let className = this.getClassNameForValueGrip(grip);
       if (className) {
         result.className = className;
       }
@@ -1261,18 +1232,17 @@ Messages.Extended.prototype = extend(Mes
    *
    * @param object grip
    *        Value grip from the server.
    * @return object
    *        Possible values of object:
    *        - A shortened string, if original grip was of string type.
    *        - The unmodified input grip, if it wasn't of string type.
    */
-  shortenValueGrip: function (grip)
-  {
+  shortenValueGrip: function (grip) {
     let shortVal = grip;
     if (typeof (grip) == "string") {
       shortVal = grip.replace(/(\r\n|\n|\r)/gm, " ");
       if (shortVal.length > MAX_STRING_GRIP_LENGTH) {
         shortVal = shortVal.substring(0, MAX_STRING_GRIP_LENGTH - 1) + ELLIPSIS;
       }
     }
 
@@ -1282,18 +1252,17 @@ Messages.Extended.prototype = extend(Mes
   /**
    * Get a CodeMirror-compatible class name for a given value grip.
    *
    * @param object grip
    *        Value grip from the server.
    * @return string
    *         The class name for the grip.
    */
-  getClassNameForValueGrip: function (grip)
-  {
+  getClassNameForValueGrip: function (grip) {
     let map = {
       "number": "cm-number",
       "longstring": "console-string",
       "string": "console-string",
       "regexp": "cm-string-2",
       "boolean": "cm-atom",
       "-infinity": "cm-atom",
       "infinity": "cm-atom",
@@ -1320,52 +1289,48 @@ Messages.Extended.prototype = extend(Mes
    * @param object objectActor
    *        The ObjectActor to display.
    * @param object options
    *        Options to use for displaying the ObjectActor.
    * @see this._renderValueGrip for the available options.
    * @return DOMElement
    *         The DOM element that displays the object actor.
    */
-  _renderObjectActor: function (objectActor, options = {})
-  {
-    let widget = Widgets.ObjectRenderers.byClass[objectActor.class];
+  _renderObjectActor: function (objectActor, options = {}) {
+    let Widget = Widgets.ObjectRenderers.byClass[objectActor.class];
 
     let { preview } = objectActor;
-    if ((!widget || (widget.canRender && !widget.canRender(objectActor)))
+    if ((!Widget || (Widget.canRender && !Widget.canRender(objectActor)))
         && preview
         && preview.kind) {
-      widget = Widgets.ObjectRenderers.byKind[preview.kind];
+      Widget = Widgets.ObjectRenderers.byKind[preview.kind];
     }
 
-    if (!widget || (widget.canRender && !widget.canRender(objectActor))) {
-      widget = Widgets.JSObject;
+    if (!Widget || (Widget.canRender && !Widget.canRender(objectActor))) {
+      Widget = Widgets.JSObject;
     }
 
-    let instance = new widget(this, objectActor, options).render();
+    let instance = new Widget(this, objectActor, options).render();
     return instance.element;
   },
 }); // Messages.Extended.prototype
 
-
-
 /**
  * The JavaScriptEvalOutput message.
  *
  * @constructor
  * @extends Messages.Extended
  * @param object evalResponse
  *        The evaluation response packet received from the server.
  * @param string [errorMessage]
  *        Optional error message to display.
  * @param string [errorDocLink]
  * Optional error doc URL to link to.
  */
-Messages.JavaScriptEvalOutput = function (evalResponse, errorMessage, errorDocLink)
-{
+Messages.JavaScriptEvalOutput = function (evalResponse, errorMessage, errorDocLink) {
   let severity = "log", msg, quoteStrings = true;
 
   // Store also the response packet from the back end. It might
   // be useful to extensions customizing the console output.
   this.response = evalResponse;
 
   if (typeof (errorMessage) !== "undefined") {
     severity = "error";
@@ -1396,18 +1361,17 @@ Messages.JavaScriptEvalOutput.prototype 
 /**
  * The ConsoleGeneric message is used for console API calls.
  *
  * @constructor
  * @extends Messages.Extended
  * @param object packet
  *        The Console API call packet received from the server.
  */
-Messages.ConsoleGeneric = function (packet)
-{
+Messages.ConsoleGeneric = function (packet) {
   let options = {
     className: "cm-s-mozilla",
     timestamp: packet.timeStamp,
     category: packet.category || "webdev",
     severity: CONSOLE_API_LEVELS_TO_SEVERITIES[packet.level],
     prefix: packet.prefix,
     private: packet.private,
     filterDuplicates: true,
@@ -1436,36 +1400,33 @@ Messages.ConsoleGeneric = function (pack
   this._repeatID.styles = packet.styles;
   this.stack = this._repeatID.stacktrace = packet.stacktrace;
   this._styles = packet.styles || [];
 };
 
 Messages.ConsoleGeneric.prototype = extend(Messages.Extended.prototype, {
   _styles: null,
 
-  _renderBodyPieceSeparator: function ()
-  {
+  _renderBodyPieceSeparator: function () {
     return this.document.createTextNode(" ");
   },
 
-  render: function ()
-  {
+  render: function () {
     let result = this.document.createDocumentFragment();
     this._renderBodyPieces(result);
 
     this._message = result;
     this._stacktrace = null;
 
     Messages.Simple.prototype.render.call(this);
 
     return this;
   },
 
-  _renderBodyPieces: function (container)
-  {
+  _renderBodyPieces: function (container) {
     let lastStyle = null;
     let stylePieces = this._styles.length > 0 ? this._styles.length : 1;
 
     for (let i = 0; i < this._messagePieces.length; i++) {
       // Pieces with an associated style definition come from "%c" formatting.
       // For body pieces beyond that, add a separator before each one.
       if (i >= stylePieces) {
         container.appendChild(this._renderBodyPieceSeparator());
@@ -1480,18 +1441,17 @@ Messages.ConsoleGeneric.prototype = exte
 
       container.appendChild(this._renderBodyPiece(piece, lastStyle));
     }
 
     this._messagePieces = null;
     this._styles = null;
   },
 
-  _renderBodyPiece: function (piece, style)
-  {
+  _renderBodyPiece: function (piece, style) {
     // Skip quotes for top-level strings.
     let options = { noStringQuotes: true };
     let elem = Messages.Extended.prototype._renderBodyPiece.call(this, piece, options);
     let result = elem;
 
     if (style) {
       if (elem.nodeType == nodeConstants.ELEMENT_NODE) {
         elem.style = style;
@@ -1514,18 +1474,17 @@ Messages.ConsoleGeneric.prototype = exte
    * - only some of the properties are allowed, based on a whitelist. See
    *   RE_ALLOWED_STYLES.
    *
    * @param string style
    *        The style string to cleanup.
    * @return string
    *         The style value after cleanup.
    */
-  cleanupStyle: function (style)
-  {
+  cleanupStyle: function (style) {
     for (let r of RE_CLEANUP_STYLES) {
       style = style.replace(r, "notallowed");
     }
 
     let dummy = this.output._dummyElement;
     if (!dummy) {
       dummy = this.output._dummyElement =
         this.document.createElementNS(XHTML_NS, "div");
@@ -1555,18 +1514,17 @@ Messages.ConsoleGeneric.prototype = exte
 /**
  * The ConsoleTrace message is used for console.trace() calls.
  *
  * @constructor
  * @extends Messages.Simple
  * @param object packet
  *        The Console API call packet received from the server.
  */
-Messages.ConsoleTrace = function (packet)
-{
+Messages.ConsoleTrace = function (packet) {
   let options = {
     className: "cm-s-mozilla",
     timestamp: packet.timeStamp,
     category: packet.category || "webdev",
     severity: CONSOLE_API_LEVELS_TO_SEVERITIES[packet.level],
     private: packet.private,
     filterDuplicates: true,
     location: {
@@ -1596,18 +1554,17 @@ Messages.ConsoleTrace.prototype = extend
    * method. This array is cleared when the message is initialized, and
    * associated actors are released.
    *
    * @private
    * @type array
    */
   _arguments: null,
 
-  init: function ()
-  {
+  init: function () {
     let result = Messages.Simple.prototype.init.apply(this, arguments);
 
     // We ignore console.trace() arguments. Release object actors.
     if (Array.isArray(this._arguments)) {
       for (let arg of this._arguments) {
         if (WebConsoleUtils.isActorGrip(arg)) {
           this.output._releaseObject(arg.actor);
         }
@@ -1662,18 +1619,17 @@ Messages.ConsoleTrace.prototype = extend
 /**
  * The ConsoleTable message is used for console.table() calls.
  *
  * @constructor
  * @extends Messages.Extended
  * @param object packet
  *        The Console API call packet received from the server.
  */
-Messages.ConsoleTable = function (packet)
-{
+Messages.ConsoleTable = function (packet) {
   let options = {
     className: "cm-s-mozilla",
     timestamp: packet.timeStamp,
     category: packet.category || "webdev",
     severity: CONSOLE_API_LEVELS_TO_SEVERITIES[packet.level],
     private: packet.private,
     filterDuplicates: false,
     location: {
@@ -1721,18 +1677,17 @@ Messages.ConsoleTable.prototype = extend
    * A promise that resolves when the table data is ready or null if invalid
    * arguments are provided.
    *
    * @private
    * @type promise|null
    */
   _populatePromise: null,
 
-  init: function ()
-  {
+  init: function () {
     let result = Messages.Extended.prototype.init.apply(this, arguments);
     this._data = [];
     this._columns = {};
 
     this._populatePromise = this._populateTableData();
 
     return result;
   },
@@ -1741,18 +1696,17 @@ Messages.ConsoleTable.prototype = extend
    * Sets the key value pair of the id and display name for the columns in the
    * table.
    *
    * @private
    * @param array|string columns
    *        Either a string or array containing the names for the columns in
    *        the output table.
    */
-  _setColumns: function (columns)
-  {
+  _setColumns: function (columns) {
     if (columns.class == "Array") {
       let items = columns.preview.items;
 
       for (let item of items) {
         if (typeof item == "string") {
           this._columns[item] = item;
         }
       }
@@ -1764,67 +1718,66 @@ Messages.ConsoleTable.prototype = extend
   /**
    * Retrieves the table data and columns from the arguments received from the
    * server.
    *
    * @return Promise|null
    *         Returns a promise that resolves when the table data is ready or
    *         null if the arguments are invalid.
    */
-  _populateTableData: function ()
-  {
+  _populateTableData: function () {
     let deferred = promise.defer();
 
     if (this._arguments.length <= 0) {
-      return;
+      return deferred.reject();
     }
 
     let data = this._arguments[0];
     if (data.class != "Array" && data.class != "Object" &&
         data.class != "Map" && data.class != "Set" &&
         data.class != "WeakMap" && data.class != "WeakSet") {
-      return;
+      return deferred.reject();
     }
 
     let hasColumnsArg = false;
     if (this._arguments.length > 1) {
       if (data.class == "Object" || data.class == "Array") {
-        this._columns["_index"] = l10n.getStr("table.index");
+        this._columns._index = l10n.getStr("table.index");
       } else {
-        this._columns["_index"] = l10n.getStr("table.iterationIndex");
+        this._columns._index = l10n.getStr("table.iterationIndex");
       }
 
       this._setColumns(this._arguments[1]);
       hasColumnsArg = true;
     }
 
     if (data.class == "Object" || data.class == "Array") {
       // Get the object properties, and parse the key and value properties into
       // the table data and columns.
       this.client = new ObjectClient(this.output.owner.jsterm.hud.proxy.client,
           data);
-      this.client.getPrototypeAndProperties(aResponse => {
-        let {ownProperties} = aResponse;
+      this.client.getPrototypeAndProperties(response => {
+        let {ownProperties} = response;
         let rowCount = 0;
         let columnCount = 0;
 
         for (let index of Object.keys(ownProperties || {})) {
           // Avoid outputting the length property if the data argument provided
           // is an array
           if (data.class == "Array" && index == "length") {
             continue;
           }
 
           if (!hasColumnsArg) {
-            this._columns["_index"] = l10n.getStr("table.index");
+            this._columns._index = l10n.getStr("table.index");
           }
 
           if (data.class == "Array") {
-            if (index == parseInt(index)) {
-              index = parseInt(index);
+            if (index == parseInt(index, 10)) {
+              index = parseInt(index, 10);
             }
           }
 
           let property = ownProperties[index].value;
           let item = { _index: index };
 
           if (property.class == "Object" || property.class == "Array") {
             let {preview} = property;
@@ -1839,39 +1792,39 @@ Messages.ConsoleTable.prototype = extend
 
               if (!hasColumnsArg && !(key in this._columns) &&
                   (++columnCount <= TABLE_COLUMN_MAX_ITEMS)) {
                 this._columns[key] = key;
               }
             }
           } else {
             // Display the value for any non-object data input.
-            item["_value"] = this._renderValueGrip(property, { concise: true });
+            item._value = this._renderValueGrip(property, { concise: true });
 
             if (!hasColumnsArg && !("_value" in this._columns)) {
-              this._columns["_value"] = l10n.getStr("table.value");
+              this._columns._value = l10n.getStr("table.value");
             }
           }
 
           this._data.push(item);
 
           if (++rowCount == TABLE_ROW_MAX_ITEMS) {
             break;
           }
         }
 
         deferred.resolve();
       });
     } else if (data.class == "Map" || data.class == "WeakMap") {
       let entries = data.preview.entries;
 
       if (!hasColumnsArg) {
-        this._columns["_index"] = l10n.getStr("table.iterationIndex");
-        this._columns["_key"] = l10n.getStr("table.key");
-        this._columns["_value"] = l10n.getStr("table.value");
+        this._columns._index = l10n.getStr("table.iterationIndex");
+        this._columns._key = l10n.getStr("table.key");
+        this._columns._value = l10n.getStr("table.value");
       }
 
       let rowCount = 0;
       for (let [key, value] of entries) {
         let item = {
           _index: rowCount,
           _key: this._renderValueGrip(key, { concise: true }),
           _value: this._renderValueGrip(value, { concise: true })
@@ -1884,42 +1837,41 @@ Messages.ConsoleTable.prototype = extend
         }
       }
 
       deferred.resolve();
     } else if (data.class == "Set" || data.class == "WeakSet") {
       let entries = data.preview.items;
 
       if (!hasColumnsArg) {
-        this._columns["_index"] = l10n.getStr("table.iterationIndex");
-        this._columns["_value"] = l10n.getStr("table.value");
+        this._columns._index = l10n.getStr("table.iterationIndex");
+        this._columns._value = l10n.getStr("table.value");
       }
 
       let rowCount = 0;
       for (let entry of entries) {
         let item = {
-          _index : rowCount,
+          _index: rowCount,
           _value: this._renderValueGrip(entry, { concise: true })
         };
 
         this._data.push(item);
 
         if (++rowCount == TABLE_ROW_MAX_ITEMS) {
           break;
         }
       }
 
       deferred.resolve();
     }
 
     return deferred.promise;
   },
 
-  render: function ()
-  {
+  render: function () {
     this._attachment = this._renderTable();
     Messages.Extended.prototype.render.apply(this, arguments);
     this.element.setAttribute("open", true);
     return this;
   },
 
   _renderMessage: function () {
     let cmvar = this.document.createElementNS(XHTML_NS, "span");
@@ -1978,18 +1930,17 @@ var Widgets = {};
 
 /**
  * The base widget class.
  *
  * @constructor
  * @param object message
  *        The owning message.
  */
-Widgets.BaseWidget = function (message)
-{
+Widgets.BaseWidget = function (message) {
   this.message = message;
 };
 
 Widgets.BaseWidget.prototype = {
   /**
    * The owning message object.
    * @type object
    */
@@ -2052,18 +2003,17 @@ Widgets.BaseWidget.prototype = {
    *        of the new DOM element. Otherwise, the value becomes the
    *        .textContent of the new DOM element.
    * @param string [textContent]
    *        If this argument is provided the value is used as the textContent of
    *        the new DOM element.
    * @return DOMElement
    *         The new DOM element.
    */
-  el: function (tagNameIdAndClasses)
-  {
+  el: function (tagNameIdAndClasses) {
     let attrs, text;
     if (typeof arguments[1] == "object") {
       attrs = arguments[1];
       text = arguments[2];
     } else {
       text = arguments[1];
     }
 
@@ -2094,72 +2044,67 @@ Widgets.BaseWidget.prototype = {
  * The timestamp widget.
  *
  * @constructor
  * @param object message
  *        The owning message.
  * @param number timestamp
  *        The UNIX timestamp to display.
  */
-Widgets.MessageTimestamp = function (message, timestamp)
-{
+Widgets.MessageTimestamp = function (message, timestamp) {
   Widgets.BaseWidget.call(this, message);
   this.timestamp = timestamp;
 };
 
 Widgets.MessageTimestamp.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The UNIX timestamp.
    * @type number
    */
   timestamp: 0,
 
-  render: function ()
-  {
+  render: function () {
     if (this.element) {
       return this;
     }
 
     this.element = this.document.createElementNS(XHTML_NS, "span");
     this.element.className = "timestamp devtools-monospace";
     this.element.textContent = l10n.timestampString(this.timestamp) + " ";
 
     return this;
   },
 }); // Widgets.MessageTimestamp.prototype
 
-
 /**
  * The URLString widget, for rendering strings where at least one token is a
  * URL.
  *
  * @constructor
  * @param object message
  *        The owning message.
  * @param string str
  *        The string, which contains at least one valid URL.
  * @param string unshortenedStr
  *        The unshortened form of the string, if it was shortened.
  */
-Widgets.URLString = function (message, str, unshortenedStr)
-{
+Widgets.URLString = function (message, str, unshortenedStr) {
   Widgets.BaseWidget.call(this, message);
   this.str = str;
   this.unshortenedStr = unshortenedStr;
 };
 
 Widgets.URLString.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The string to format, which contains at least one valid URL.
    * @type string
    */
   str: "",
 
-  render: function ()
-  {
+  render: function () {
     if (this.element) {
       return this;
     }
 
     // The rendered URLString will be a <span> containing a number of text
     // <spans> for non-URL tokens and <a>'s for URL tokens.
     this.element = this.el("span", {
       class: "console-string"
@@ -2183,32 +2128,32 @@ Widgets.URLString.prototype = extend(Wid
         }
         this.element.appendChild(this._renderText(this.str.slice(textStart, tokenStart)));
         textStart = tokenStart + token.length;
         this.element.appendChild(this._renderURL(token, unshortenedToken));
       }
     }
 
     // Clean up any non-URL text at the end of the source string.
-    this.element.appendChild(this._renderText(this.str.slice(textStart, this.str.length)));
+    const rendered = this._renderText(this.str.slice(textStart, this.str.length));
+    this.element.appendChild(rendered);
     this.element.appendChild(this._renderText("\""));
 
     return this;
   },
 
   /**
    * Determines whether a grip is a string containing a URL.
    *
    * @param string grip
    *        The grip, which may contain a URL.
    * @return boolean
    *         Whether the grip is a string containing a URL.
    */
-  containsURL: function (grip)
-  {
+  containsURL: function (grip) {
     if (typeof grip != "string") {
       return false;
     }
 
     let tokens = grip.split(/\s+/);
     return tokens.some(this._isURL);
   },
 
@@ -2237,18 +2182,17 @@ Widgets.URLString.prototype = extend(Wid
    *
    * @param string url
    *        The string to be rendered as a url.
    * @param string fullUrl
    *        The unshortened form of the URL, if it was shortened.
    * @return DOMElement
    *         An element containing the rendered string.
    */
-  _renderURL: function (url, fullUrl)
-  {
+  _renderURL: function (url, fullUrl) {
     let unshortened = fullUrl || url;
     let result = this.el("a", {
       class: "url",
       title: unshortened,
       href: unshortened,
       draggable: false
     }, url);
     this.message._addLinkCallback(result);
@@ -2268,76 +2212,70 @@ Widgets.URLString.prototype = extend(Wid
  *        The owning message.
  * @param object objectActor
  *        The ObjectActor to display.
  * @param object [options]
  *        Options for displaying the given ObjectActor. See
  *        Messages.Extended.prototype._renderValueGrip for the available
  *        options.
  */
-Widgets.JSObject = function (message, objectActor, options = {})
-{
+Widgets.JSObject = function (message, objectActor, options = {}) {
   Widgets.BaseWidget.call(this, message);
   this.objectActor = objectActor;
   this.options = options;
   this._onClick = this._onClick.bind(this);
 };
 
 Widgets.JSObject.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The ObjectActor displayed by the widget.
    * @type object
    */
   objectActor: null,
 
-  render: function ()
-  {
+  render: function () {
     if (!this.element) {
       this._render();
     }
 
     return this;
   },
 
-  _render: function ()
-  {
+  _render: function () {
     let str = VariablesView.getString(this.objectActor, this.options);
     let className = this.message.getClassNameForValueGrip(this.objectActor);
     if (!className && this.objectActor.class == "Object") {
       className = "cm-variable";
     }
 
     this.element = this._anchor(str, { className: className });
   },
 
   /**
    * Render a concise representation of an object.
    */
-  _renderConciseObject: function ()
-  {
+  _renderConciseObject: function () {
     this.element = this._anchor(this.objectActor.class,
                                 { className: "cm-variable" });
   },
 
   /**
    * Render the `<class> { ` prefix of an object.
    */
-  _renderObjectPrefix: function ()
-  {
+  _renderObjectPrefix: function () {
     let { kind } = this.objectActor.preview;
     this.element = this.el("span.kind-" + kind);
     this._anchor(this.objectActor.class, { className: "cm-variable" });
     this._text(" { ");
   },
 
   /**
    * Render the ` }` suffix of an object.
    */
-  _renderObjectSuffix: function ()
-  {
+  _renderObjectSuffix: function () {
     this._text(" }");
   },
 
   /**
    * Render an object property.
    *
    * @param String key
    *        The property name.
@@ -2347,57 +2285,63 @@ Widgets.JSObject.prototype = extend(Widg
    *        The container node to render to.
    * @param Boolean needsComma
    *        True if there was another property before this one and we need to
    *        separate them with a comma.
    * @param Boolean valueIsText
    *        Add the value as is, don't treat it as a grip and pass it to
    *        `_renderValueGrip`.
    */
-  _renderObjectProperty: function (key, value, container, needsComma, valueIsText = false)
-  {
+  _renderObjectProperty: function (
+    key,
+    value,
+    container,
+    needsComma,
+    valueIsText = false
+  ) {
     if (needsComma) {
       this._text(", ");
     }
 
     container.appendChild(this.el("span.cm-property", key));
     this._text(": ");
 
     if (valueIsText) {
       this._text(value);
     } else {
-      let valueElem = this.message._renderValueGrip(value, { concise: true, shorten: true });
+      let valueElem = this.message._renderValueGrip(value, {
+        concise: true,
+        shorten: true
+      });
       container.appendChild(valueElem);
     }
   },
 
   /**
    * Render this object's properties.
    *
    * @param nsIDOMNode container
    *        The container node to render to.
    * @param Boolean needsComma
    *        True if there was another property before this one and we need to
    *        separate them with a comma.
    */
-  _renderObjectProperties: function (container, needsComma)
-  {
+  _renderObjectProperties: function (container, needsComma) {
     let { preview } = this.objectActor;
     let { ownProperties, safeGetterValues } = preview;
 
     let shown = 0;
 
     let getValue = desc => {
       if (desc.get) {
         return "Getter";
       } else if (desc.set) {
         return "Setter";
-      } else {
-        return desc.value;
       }
+      return desc.value;
     };
 
     for (let key of Object.keys(ownProperties || {})) {
       this._renderObjectProperty(key, getValue(ownProperties[key]), container,
                                  shown > 0 || needsComma,
                                  ownProperties[key].get || ownProperties[key].set);
       shown++;
     }
@@ -2435,18 +2379,17 @@ Widgets.JSObject.prototype = extend(Widg
    *        on the anchor open the link in a new tab.
    *        - appendTo (DOMElement): append the element to the given DOM
    *        element. If not provided, the anchor is appended to |this.element|
    *        if it is available. If |appendTo| is provided and if it is a falsy
    *        value, the anchor is not appended to any element.
    * @return DOMElement
    *         The DOM element of the new anchor.
    */
-  _anchor: function (text, options = {})
-  {
+  _anchor: function (text, options = {}) {
     if (!options.onClick) {
       // If the anchor has an URL, open it in a new tab. If not, show the
       // current object actor.
       options.onClick = options.href ? this._onClickAnchor : this._onClick;
     }
 
     options.onContextMenu = options.onContextMenu || this._onContextMenu;
 
@@ -2464,27 +2407,25 @@ Widgets.JSObject.prototype = extend(Widg
       options.appendTo.appendChild(anchor);
     } else if (!("appendTo" in options) && this.element) {
       this.element.appendChild(anchor);
     }
 
     return anchor;
   },
 
-  openObjectInVariablesView: function ()
-  {
+  openObjectInVariablesView: function () {
     this.output.openVariablesView({
       label: VariablesView.getString(this.objectActor, { concise: true }),
       objectActor: this.objectActor,
       autofocus: true,
     });
   },
 
-  storeObjectInWindow: function ()
-  {
+  storeObjectInWindow: function () {
     let evalString = `{ let i = 0;
       while (this.hasOwnProperty("temp" + i) && i < 1000) {
         i++;
       }
       this["temp" + i] = _self;
       "temp" + i;
     }`;
     let options = {
@@ -2496,18 +2437,17 @@ Widgets.JSObject.prototype = extend(Widg
       this.output.owner.jsterm.setInputValue(res.result);
     });
   },
 
   /**
    * The click event handler for objects shown inline.
    * @private
    */
-  _onClick: function ()
-  {
+  _onClick: function () {
     this.openObjectInVariablesView();
   },
 
   _onContextMenu: function (ev) {
     // TODO offer a nice API for the context menu.
     // Probably worth to take a look at Firebug's way
     // https://github.com/firebug/firebug/blob/master/extension/content/firebug/chrome/menu.js
     let doc = ev.target.ownerDocument;
@@ -2543,18 +2483,17 @@ Widgets.JSObject.prototype = extend(Widg
    *
    * @private
    * @param string str
    *        String to add.
    * @param DOMElement [target = this.element]
    *        Optional DOM element to append the string to. The default is
    *        this.element.
    */
-  _text: function (str, target = this.element)
-  {
+  _text: function (str, target = this.element) {
     target.appendChild(this.document.createTextNode(str));
   },
 }); // Widgets.JSObject.prototype
 
 Widgets.ObjectRenderers = {};
 Widgets.ObjectRenderers.byKind = {};
 Widgets.ObjectRenderers.byClass = {};
 
@@ -2579,18 +2518,17 @@ Widgets.ObjectRenderers.byClass = {};
  *        - initialize (function, optional): the constructor of the renderer
  *        widget. This function is invoked with the following arguments: the
  *        owner message object instance, the object actor grip to display, and
  *        an options object. See Messages.Extended.prototype._renderValueGrip()
  *        for details about the options object.
  *        - render (function, required): the method that displays the given
  *        object actor.
  */
-Widgets.ObjectRenderers.add = function (obj)
-{
+Widgets.ObjectRenderers.add = function (obj) {
   let extendObj = obj.extends || Widgets.JSObject;
 
   let constructor = function () {
     if (obj.initialize) {
       obj.initialize.apply(this, arguments);
     } else {
       extendObj.apply(this, arguments);
     }
@@ -2616,25 +2554,23 @@ Widgets.ObjectRenderers.add = function (
   } else if (obj.byKind) {
     Widgets.ObjectRenderers.byKind[obj.byKind] = constructor;
   } else {
     throw new Error("You are adding an object renderer without any byClass or " +
                     "byKind property.");
   }
 };
 
-
 /**
  * The widget used for displaying Date objects.
  */
 Widgets.ObjectRenderers.add({
   byClass: "Date",
 
-  render: function ()
-  {
+  render: function () {
     let {preview} = this.objectActor;
     this.element = this.el("span.class-" + this.objectActor.class);
 
     let anchorText = this.objectActor.class;
     let anchorClass = "cm-variable";
     if (preview && "timestamp" in preview && typeof preview.timestamp != "number") {
       anchorText = new Date(preview.timestamp).toString(); // invalid date
       anchorClass = "";
@@ -2654,27 +2590,24 @@ Widgets.ObjectRenderers.add({
 });
 
 /**
  * The widget used for displaying Function objects.
  */
 Widgets.ObjectRenderers.add({
   byClass: "Function",
 
-  render: function ()
-  {
+  render: function () {
     let grip = this.objectActor;
     this.element = this.el("span.class-" + this.objectActor.class);
 
     // TODO: Bug 948484 - support arrow functions and ES6 generators
     let name = grip.userDisplayName || grip.displayName || grip.name || "";
     name = VariablesView.getString(name, { noStringQuotes: true });
 
-    let str = this.options.concise ? name || "function " : "function " + name;
-
     if (this.options.concise) {
       this._anchor(name || "function", {
         className: name ? "cm-variable" : "cm-keyword",
       });
       if (!name) {
         this._text(" ");
       }
     } else if (name) {
@@ -2702,31 +2635,29 @@ Widgets.ObjectRenderers.add({
 
     this._text(")");
   },
 
   _onClick: function () {
     let location = this.objectActor.location;
     if (location && IGNORED_SOURCE_URLS.indexOf(location.url) === -1) {
       this.output.openLocationInDebugger(location);
-    }
-    else {
+    } else {
       this.openObjectInVariablesView();
     }
   }
 }); // Widgets.ObjectRenderers.byClass.Function
 
 /**
  * The widget used for displaying ArrayLike objects.
  */
 Widgets.ObjectRenderers.add({
   byKind: "ArrayLike",
 
-  render: function ()
-  {
+  render: function () {
     let {preview} = this.objectActor;
     let {items} = preview;
     this.element = this.el("span.kind-" + preview.kind);
 
     this._anchor(this.objectActor.class, { className: "cm-variable" });
 
     if (!items || this.options.concise) {
       this._text("[");
@@ -2740,18 +2671,17 @@ Widgets.ObjectRenderers.add({
     let isFirst = true;
     let emptySlots = 0;
     // A helper that renders a comma between items if isFirst == false.
     let renderSeparator = () => !isFirst && this._text(", ");
 
     for (let item of items) {
       if (item === null) {
         emptySlots++;
-      }
-      else {
+      } else {
         renderSeparator();
         isFirst = false;
 
         if (emptySlots) {
           this._renderEmptySlots(emptySlots);
           emptySlots = 0;
         }
 
@@ -2770,37 +2700,38 @@ Widgets.ObjectRenderers.add({
       this._text(", ");
 
       let n = preview.length - shown;
       let str = VariablesView.stringifiers._getNMoreString(n);
       this._anchor(str);
     }
 
     this._text(" ]");
+
+    return this;
   },
 
-  _renderEmptySlots: function (aNumSlots, aAppendComma = true) {
+  _renderEmptySlots: function (numSlots, appendComma = true) {
     let slotLabel = l10n.getStr("emptySlotLabel");
-    let slotText = PluralForm.get(aNumSlots, slotLabel);
-    this._text("<" + slotText.replace("#1", aNumSlots) + ">");
-    if (aAppendComma) {
+    let slotText = PluralForm.get(numSlots, slotLabel);
+    this._text("<" + slotText.replace("#1", numSlots) + ">");
+    if (appendComma) {
       this._text(", ");
     }
   },
 
 }); // Widgets.ObjectRenderers.byKind.ArrayLike
 
 /**
  * The widget used for displaying MapLike objects.
  */
 Widgets.ObjectRenderers.add({
   byKind: "MapLike",
 
-  render: function ()
-  {
+  render: function () {
     let {preview} = this.objectActor;
     let {entries} = preview;
 
     let container = this.element = this.el("span.kind-" + preview.kind);
     this._anchor(this.objectActor.class, { className: "cm-variable" });
 
     if (!entries || this.options.concise) {
       if (typeof preview.size == "number") {
@@ -2853,24 +2784,22 @@ Widgets.ObjectRenderers.add({
 }); // Widgets.ObjectRenderers.byKind.MapLike
 
 /**
  * The widget used for displaying objects with a URL.
  */
 Widgets.ObjectRenderers.add({
   byKind: "ObjectWithURL",
 
-  render: function ()
-  {
+  render: function () {
     this.element = this._renderElement(this.objectActor,
                                        this.objectActor.preview.url);
   },
 
-  _renderElement: function (objectActor, url)
-  {
+  _renderElement: function (objectActor, url) {
     let container = this.el("span.kind-" + objectActor.preview.kind);
 
     this._anchor(objectActor.class, {
       className: "cm-variable",
       appendTo: container,
     });
 
     if (!VariablesView.isFalsy({ value: url })) {
@@ -2884,18 +2813,17 @@ Widgets.ObjectRenderers.add({
 }); // Widgets.ObjectRenderers.byKind.ObjectWithURL
 
 /**
  * The widget used for displaying objects with a string next to them.
  */
 Widgets.ObjectRenderers.add({
   byKind: "ObjectWithText",
 
-  render: function ()
-  {
+  render: function () {
     let {preview} = this.objectActor;
     this.element = this.el("span.kind-" + preview.kind);
 
     this._anchor(this.objectActor.class, { className: "cm-variable" });
 
     if (!this.options.concise) {
       this._text(" ");
       this.element.appendChild(this.el("span.theme-fg-color6",
@@ -2905,18 +2833,17 @@ Widgets.ObjectRenderers.add({
 });
 
 /**
  * The widget used for displaying DOM event previews.
  */
 Widgets.ObjectRenderers.add({
   byKind: "DOMEvent",
 
-  render: function ()
-  {
+  render: function () {
     let {preview} = this.objectActor;
 
     let container = this.element = this.el("span.kind-" + preview.kind);
 
     this._anchor(preview.type || this.objectActor.class,
                  { className: "cm-variable" });
 
     if (this.options.concise) {
@@ -2987,24 +2914,24 @@ Widgets.ObjectRenderers.add({
       case nodeConstants.DOCUMENT_FRAGMENT_NODE:
       case nodeConstants.ELEMENT_NODE:
         return true;
       default:
         return false;
     }
   },
 
-  render: function ()
-  {
-    switch (this.objectActor.preview.nodeType) {
+  render: function () {
+    const {preview} = this.objectActor;
+
+    switch (preview.nodeType) {
       case nodeConstants.DOCUMENT_NODE:
         this._renderDocumentNode();
         break;
       case nodeConstants.ATTRIBUTE_NODE: {
-        let {preview} = this.objectActor;
         this.element = this.el("span.attributeNode.kind-" + preview.kind);
         let attr = this._renderAttributeNode(preview.nodeName, preview.value, true);
         this.element.appendChild(attr);
         break;
       }
       case nodeConstants.TEXT_NODE:
         this._renderTextNode();
         break;
@@ -3017,69 +2944,64 @@ Widgets.ObjectRenderers.add({
       case nodeConstants.ELEMENT_NODE:
         this._renderElementNode();
         break;
       default:
         throw new Error("Unsupported nodeType: " + preview.nodeType);
     }
   },
 
-  _renderDocumentNode: function ()
-  {
+  _renderDocumentNode: function () {
     let fn =
       Widgets.ObjectRenderers.byKind.ObjectWithURL.prototype._renderElement;
     this.element = fn.call(this, this.objectActor,
                            this.objectActor.preview.location);
     this.element.classList.add("documentNode");
   },
 
-  _renderAttributeNode: function (nodeName, nodeValue, addLink)
-  {
+  _renderAttributeNode: function (nodeName, nodeValue, addLink) {
     let value = VariablesView.getString(nodeValue, { noStringQuotes: true });
 
     let fragment = this.document.createDocumentFragment();
     if (addLink) {
       this._anchor(nodeName, { className: "cm-attribute", appendTo: fragment });
     } else {
       fragment.appendChild(this.el("span.cm-attribute", nodeName));
     }
 
     this._text("=\"", fragment);
     fragment.appendChild(this.el("span.theme-fg-color6", escapeHTML(value)));
     this._text("\"", fragment);
 
     return fragment;
   },
 
-  _renderTextNode: function ()
-  {
+  _renderTextNode: function () {
     let {preview} = this.objectActor;
     this.element = this.el("span.textNode.kind-" + preview.kind);
 
     this._anchor(preview.nodeName, { className: "cm-variable" });
     this._text(" ");
 
     let text = VariablesView.getString(preview.textContent);
     this.element.appendChild(this.el("span.console-string", text));
   },
 
-  _renderCommentNode: function ()
-  {
+  _renderCommentNode: function () {
     let {preview} = this.objectActor;
     let comment = "<!-- " + VariablesView.getString(preview.textContent, {
       noStringQuotes: true,
     }) + " -->";
 
     this.element = this._anchor(comment, {
       className: "kind-" + preview.kind + " commentNode cm-comment",
     });
   },
 
-  _renderDocumentFragmentNode: function ()
-  {
+  _renderDocumentFragmentNode: function () {
     let {preview} = this.objectActor;
     let {childNodes} = preview;
     let container = this.element = this.el("span.documentFragmentNode.kind-" +
                                            preview.kind);
 
     this._anchor(this.objectActor.class, { className: "cm-variable" });
 
     if (!childNodes || this.options.concise) {
@@ -3108,38 +3030,38 @@ Widgets.ObjectRenderers.add({
       let n = preview.childNodesLength - shown;
       let str = VariablesView.stringifiers._getNMoreString(n);
       this._anchor(str);
     }
 
     this._text(" ]");
   },
 
-  _renderElementNode: function ()
-  {
-    let doc = this.document;
+  _renderElementNode: function () {
     let {attributes, nodeName} = this.objectActor.preview;
 
-    this.element = this.el("span." + "kind-" + this.objectActor.preview.kind + ".elementNode");
+    this.element = this.el("span." + "kind-" + this.objectActor.preview.kind +
+                           ".elementNode");
 
     this._text("<");
     let openTag = this.el("span.cm-tag");
     this.element.appendChild(openTag);
 
     let tagName = this._anchor(nodeName, {
       className: "cm-tag",
       appendTo: openTag
     });
 
     if (this.options.concise) {
       if (attributes.id) {
         tagName.appendChild(this.el("span.cm-attribute", "#" + attributes.id));
       }
       if (attributes.class) {
-        tagName.appendChild(this.el("span.cm-attribute", "." + attributes.class.split(/\s+/g).join(".")));
+        const joinedClasses = "." + attributes.class.split(/\s+/g).join(".");
+        tagName.appendChild(this.el("span.cm-attribute", joinedClasses));
       }
     } else {
       for (let name of Object.keys(attributes)) {
         let attr = this._renderAttributeNode(" " + name, attributes[name]);
         this.element.appendChild(attr);
       }
     }
 
@@ -3157,18 +3079,17 @@ Widgets.ObjectRenderers.add({
    * will attach mouseover/out event listeners to do so, and the inspector icon
    * to open the node in the inspector.
    * @return a promise that resolves when the node has been linked to the
    * inspector, or rejects if it wasn't (either if no toolbox could be found to
    * access the inspector, or if the node isn't present in the inspector, i.e.
    * if the node is in a DocumentFragment or not part of the tree, or not of
    * type nodeConstants.ELEMENT_NODE).
    */
-  linkToInspector: Task.async(function* ()
-  {
+  linkToInspector: Task.async(function* () {
     if (this._linkedToInspector) {
       return;
     }
 
     // Checking the node type
     if (this.objectActor.preview.nodeType !== nodeConstants.ELEMENT_NODE) {
       throw new Error("The object cannot be linked to the inspector as it " +
         "isn't an element node");
@@ -3179,17 +3100,18 @@ Widgets.ObjectRenderers.add({
     this.toolbox = gDevTools.getToolbox(target);
     if (!this.toolbox) {
       // In cases like the browser console, there is no toolbox.
       return;
     }
 
     // Checking that the inspector supports the node
     yield this.toolbox.initInspector();
-    this._nodeFront = yield this.toolbox.walker.getNodeActorFromObjectActor(this.objectActor.actor);
+    this._nodeFront = yield this.toolbox.walker.getNodeActorFromObjectActor(
+      this.objectActor.actor);
     if (!this._nodeFront) {
       throw new Error("The object cannot be linked to the inspector, the " +
         "corresponding nodeFront could not be found");
     }
 
     // At this stage, the message may have been cleared already
     if (!this.document) {
       throw new Error("The object cannot be linked to the inspector, the " +
@@ -3214,68 +3136,66 @@ Widgets.ObjectRenderers.add({
     this._openInspectorNode.title = l10n.getStr("openNodeInInspector");
   }),
 
   /**
    * Highlight the DOMNode corresponding to the ObjectActor in the page.
    * @return a promise that resolves when the node has been highlighted, or
    * rejects if the node cannot be highlighted (detached from the DOM)
    */
-  highlightDomNode: Task.async(function* ()
-  {
+  highlightDomNode: Task.async(function* () {
     yield this.linkToInspector();
     let isAttached = yield this.toolbox.walker.isInDOMTree(this._nodeFront);
     if (isAttached) {
       yield this.toolbox.highlighterUtils.highlightNodeFront(this._nodeFront);
     } else {
-      throw null;
+      throw new Error("Node is not attached.");
     }
   }),
 
   /**
    * Unhighlight a previously highlit node
    * @see highlightDomNode
    * @return a promise that resolves when the highlighter has been hidden
    */
-  unhighlightDomNode: function ()
-  {
+  unhighlightDomNode: function () {
     return this.linkToInspector().then(() => {
       return this.toolbox.highlighterUtils.unhighlight();
     }).then(null, e => console.error(e));
   },
 
   /**
    * Open the DOMNode corresponding to the ObjectActor in the inspector panel
    * @return a promise that resolves when the inspector has been switched to
    * and the node has been selected, or rejects if the node cannot be selected
    * (detached from the DOM). Note that in any case, the inspector panel will
    * be switched to.
    */
-  openNodeInInspector: Task.async(function* ()
-  {
+  openNodeInInspector: Task.async(function* () {
     yield this.linkToInspector();
     yield this.toolbox.selectTool("inspector");
 
     let isAttached = yield this.toolbox.walker.isInDOMTree(this._nodeFront);
     if (isAttached) {
       let onReady = promise.defer();
       this.toolbox.inspector.once("inspector-updated", onReady.resolve);
       yield this.toolbox.selection.setNodeFront(this._nodeFront, "console");
       yield onReady.promise;
     } else {
-      throw null;
+      throw new Error("Node is not attached.");
     }
   }),
 
-  destroy: function ()
-  {
+  destroy: function () {
     if (this.toolbox && this._nodeFront) {
       this.element.removeEventListener("mouseover", this.highlightDomNode);
       this.element.removeEventListener("mouseout", this.unhighlightDomNode);
-      this._openInspectorNode.removeEventListener("mousedown", this.openNodeInInspector, true);
+      this._openInspectorNode.removeEventListener("mousedown",
+                                                  this.openNodeInInspector,
+                                                  true);
 
       if (this._linkedToInspector) {
         this.unhighlightDomNode().then(() => {
           this.toolbox = null;
           this._nodeFront = null;
         });
       } else {
         this.toolbox = null;
@@ -3286,18 +3206,17 @@ Widgets.ObjectRenderers.add({
 }); // Widgets.ObjectRenderers.byKind.DOMNode
 
 /**
  * The widget user for displaying Promise objects.
  */
 Widgets.ObjectRenderers.add({
   byClass: "Promise",
 
-  render: function ()
-  {
+  render: function () {
     let { ownProperties, safeGetterValues } = this.objectActor.preview || {};
     if ((!ownProperties && !safeGetterValues) || this.options.concise) {
       this._renderConciseObject();
       return;
     }
 
     this._renderObjectPrefix();
     let container = this.element;
@@ -3370,18 +3289,17 @@ Widgets.ObjectRenderers.add({
 });
 
 /**
  * The widget used for displaying generic JS object previews.
  */
 Widgets.ObjectRenderers.add({
   byKind: "Object",
 
-  render: function ()
-  {
+  render: function () {
     let { ownProperties, safeGetterValues } = this.objectActor.preview || {};
     if ((!ownProperties && !safeGetterValues) || this.options.concise) {
       this._renderConciseObject();
       return;
     }
 
     this._renderObjectPrefix();
     this._renderObjectProperties(this.element, false);
@@ -3395,36 +3313,34 @@ Widgets.ObjectRenderers.add({
  * @constructor
  * @param object message
  *        The owning message.
  * @param object longStringActor
  *        The LongStringActor to display.
  * @param object options
  *        Options, such as noStringQuotes
  */
-Widgets.LongString = function (message, longStringActor, options)
-{
+Widgets.LongString = function (message, longStringActor, options) {
   Widgets.BaseWidget.call(this, message);
   this.longStringActor = longStringActor;
   this.noStringQuotes = (options && "noStringQuotes" in options) ?
     options.noStringQuotes : !this.message._quoteStrings;
 
   this._onClick = this._onClick.bind(this);
   this._onSubstring = this._onSubstring.bind(this);
 };
 
 Widgets.LongString.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The LongStringActor displayed by the widget.
    * @type object
    */
   longStringActor: null,
 
-  render: function ()
-  {
+  render: function () {
     if (this.element) {
       return this;
     }
 
     let result = this.element = this.document.createElementNS(XHTML_NS, "span");
     result.className = "longString console-string";
     this._renderString(this.longStringActor.initial);
     result.appendChild(this._renderEllipsis());
@@ -3433,64 +3349,60 @@ Widgets.LongString.prototype = extend(Wi
   },
 
   /**
    * Render the long string in the widget element.
    * @private
    * @param string str
    *        The string to display.
    */
-  _renderString: function (str)
-  {
+  _renderString: function (str) {
     this.element.textContent = VariablesView.getString(str, {
       noStringQuotes: this.noStringQuotes,
       noEllipsis: true,
     });
   },
 
   /**
    * Render the anchor ellipsis that allows the user to expand the long string.
    *
    * @private
    * @return Element
    */
-  _renderEllipsis: function ()
-  {
+  _renderEllipsis: function () {
     let ellipsis = this.document.createElementNS(XHTML_NS, "a");
     ellipsis.className = "longStringEllipsis";
     ellipsis.textContent = l10n.getStr("longStringEllipsis");
     ellipsis.href = "#";
     ellipsis.draggable = false;
     this.message._addLinkCallback(ellipsis, this._onClick);
 
     return ellipsis;
   },
 
   /**
    * The click event handler for the ellipsis shown after the short string. This
    * function expands the element to show the full string.
    * @private
    */
-  _onClick: function ()
-  {
+  _onClick: function () {
     let longString = this.output.webConsoleClient.longString(this.longStringActor);
     let toIndex = Math.min(longString.length, MAX_LONG_STRING_LENGTH);
 
     longString.substring(longString.initial.length, toIndex, this._onSubstring);
   },
 
   /**
    * The longString substring response callback.
    *
    * @private
    * @param object response
    *        Response packet.
    */
-  _onSubstring: function (response)
-  {
+  _onSubstring: function (response) {
     if (response.error) {
       console.error("LongString substring failure: " + response.error);
       return;
     }
 
     this.element.lastChild.remove();
     this.element.classList.remove("longString");
 
@@ -3507,27 +3419,25 @@ Widgets.LongString.prototype = extend(Wi
       this._logWarningAboutStringTooLong();
     }
   },
 
   /**
    * Inform user that the string he tries to view is too long.
    * @private
    */
-  _logWarningAboutStringTooLong: function ()
-  {
+  _logWarningAboutStringTooLong: function () {
     let msg = new Messages.Simple(l10n.getStr("longStringTooLong"), {
       category: "output",
       severity: "warning",
     });
     this.output.addMessage(msg);
   },
 }); // Widgets.LongString.prototype
 
-
 /**
  * The stacktrace widget.
  *
  * @constructor
  * @extends Widgets.BaseWidget
  * @param object message
  *        The owning message.
  * @param array stacktrace
@@ -3576,18 +3486,17 @@ Widgets.Stacktrace.prototype = extend(Wi
  * @param object message
  *        The owning message.
  * @param array data
  *        Array of objects that holds the data to log in the table.
  * @param object columns
  *        Object containing the key value pair of the id and display name for
  *        the columns in the table.
  */
-Widgets.Table = function (message, data, columns)
-{
+Widgets.Table = function (message, data, columns) {
   Widgets.BaseWidget.call(this, message);
   this.data = data;
   this.columns = columns;
 };
 
 Widgets.Table.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * Array of objects that holds the data to output in the table.
@@ -3620,17 +3529,16 @@ Widgets.Table.prototype = extend(Widgets
     for (let row of this.data) {
       this.table.push(row);
     }
 
     return this;
   }
 }); // Widgets.Table.prototype
 
-function gSequenceId()
-{
+function gSequenceId() {
   return gSequenceId.n++;
 }
 gSequenceId.n = 0;
 
 exports.ConsoleOutput = ConsoleOutput;
 exports.Messages = Messages;
 exports.Widgets = Widgets;