Merge fx-team to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 20 May 2016 14:14:00 -0700
changeset 369236 44fa05b72b6fb2ef0edfe73e4767154ab99381bc
parent 369224 c403ac05b8f42e44a5f7a0c98c2bf190b28706b1 (current diff)
parent 369152 c62705a833ff9c985c71ddf4c07054de113525c3 (diff)
child 369237 30b83fcb0009b524cf3982a8aeb2bc0fc6d2d5b7
child 369680 df823f36e8cfb09e6f5eec1a125c6db97afb53b4
push id18806
push userbmo:gps@mozilla.com
push dateFri, 20 May 2016 21:59:07 +0000
reviewersmerge
milestone49.0a1
Merge fx-team to central, a=merge
devtools/client/inspector/inspector-panel.js
devtools/server/actors/storage.js
devtools/shared/security/socket.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -115,16 +115,17 @@ devtools/client/webconsole/**
 !devtools/client/webconsole/panel.js
 !devtools/client/webconsole/jsterm.js
 devtools/client/webide/**
 devtools/server/**
 !devtools/server/actors/webbrowser.js
 !devtools/server/actors/styles.js
 devtools/shared/*.js
 !devtools/shared/css-lexer.js
+!devtools/shared/task.js
 devtools/shared/*.jsm
 devtools/shared/apps/**
 devtools/shared/client/**
 devtools/shared/discovery/**
 devtools/shared/gcli/**
 !devtools/shared/gcli/templater.js
 devtools/shared/heapsnapshot/**
 devtools/shared/inspector/**
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -1431,27 +1431,16 @@ CustomizeMode.prototype = {
           lwthemePrefs.setComplexValue("recommendedThemes",
                                        Ci.nsISupportsString, string);
           this.parentNode.hidePopup();
         });
         panel.insertBefore(tbb, footer);
       }
       let hideRecommendedLabel = (footer.previousSibling == recommendedLabel);
       recommendedLabel.hidden = hideRecommendedLabel;
-
-      let hideMyThemesSection = themesInMyThemesSection < 2 && hideRecommendedLabel;
-      let headerLabel = doc.getElementById("customization-lwtheme-menu-header");
-      if (hideMyThemesSection) {
-        let element = recommendedLabel.previousSibling;
-        while (element && element != headerLabel) {
-          element.hidden = true;
-          element = element.previousSibling;
-        }
-      }
-      headerLabel.hidden = hideMyThemesSection;
     }.bind(this));
   },
 
   resetLWThemesMenu: function(target) {
     let doc = target.ownerDocument;
     let footer = doc.getElementById("customization-lwtheme-menu-footer");
     let recommendedLabel = doc.getElementById("customization-lwtheme-menu-recommended");
     this.swatchForTheme(doc);
--- a/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
+++ b/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
@@ -57,16 +57,36 @@ add_task(function* () {
      "The second theme in the 'My Themes' section should be the newly installed theme: " +
      "Installed theme id: " + installedThemeId + "; First theme ID: " + firstLWThemeId);
   is(header.nextSibling.nextSibling.nextSibling, recommendedHeader,
      "There should be two themes in the 'My Themes' section");
 
   let defaultTheme = header.nextSibling;
   defaultTheme.doCommand();
   is(Services.prefs.getCharPref("lightweightThemes.selectedThemeID"), "", "No lwtheme should be selected");
+
+  yield endCustomizing();
+  Services.prefs.setCharPref("lightweightThemes.usedThemes", "[]");
+  Services.prefs.setCharPref("lightweightThemes.recommendedThemes", "[]");
+  info("Removed all recommended themes");
+  yield startCustomizing();
+  popupShownPromise = popupShown(popup);
+  EventUtils.synthesizeMouseAtCenter(themesButton, {});
+  info("Clicked on themes button a second time");
+  yield popupShownPromise;
+  header = document.getElementById("customization-lwtheme-menu-header");
+  is(header.hidden, false, "Header should never be hidden");
+  is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme");
+  is(header.nextSibling.hidden, false, "The default theme should never be hidden");
+  recommendedHeader = document.getElementById("customization-lwtheme-menu-recommended");
+  is(header.nextSibling.nextSibling, recommendedHeader,
+     "There should only be one theme (default) in the 'My Themes' section by default");
+  let footer = document.getElementById("customization-lwtheme-menu-footer");
+  is(recommendedHeader.nextSibling.id, footer.id, "There should be no recommended themes in the menu");
+  is(recommendedHeader.hidden, true, "The recommendedHeader should be hidden since there are no recommended themes");
 });
 
 add_task(function* asyncCleanup() {
   yield endCustomizing();
 
   Services.prefs.clearUserPref("lightweightThemes.usedThemes");
   Services.prefs.clearUserPref("lightweightThemes.recommendedThemes");
 });
--- a/devtools/client/aboutdebugging/modules/worker.js
+++ b/devtools/client/aboutdebugging/modules/worker.js
@@ -1,15 +1,15 @@
 /* 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 { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "gDevTools",
   "devtools/client/framework/devtools", true);
 loader.lazyRequireGetter(this, "TargetFactory",
   "devtools/client/framework/target", true);
 loader.lazyRequireGetter(this, "Toolbox",
   "devtools/client/framework/toolbox", true);
 
--- a/devtools/client/animationinspector/animation-controller.js
+++ b/devtools/client/animationinspector/animation-controller.js
@@ -9,18 +9,18 @@
    imports globals from animation-controller.js */
 /* globals AnimationsPanel */
 /* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */
 
 "use strict";
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
-Cu.import("resource://gre/modules/Task.jsm");
 var { loader, require } = Cu.import("resource://devtools/shared/Loader.jsm");
+var { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 loader.lazyRequireGetter(this, "AnimationsFront", "devtools/server/actors/animation", true);
 
 const { LocalizationHelper } = require("devtools/client/shared/l10n");
 
 const STRINGS_URI = "chrome://devtools/locale/animationinspector.properties";
--- a/devtools/client/animationinspector/components/animation-details.js
+++ b/devtools/client/animationinspector/components/animation-details.js
@@ -1,18 +1,17 @@
 /* -*- 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 {Cu} = require("chrome");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {createNode, TimeScale} = require("devtools/client/animationinspector/utils");
 const {Keyframes} = require("devtools/client/animationinspector/components/keyframes");
 
 /**
  * UI component responsible for displaying detailed information for a given
  * animation.
  * This includes information about timing, easing, keyframes, animated
--- a/devtools/client/animationinspector/components/animation-target-node.js
+++ b/devtools/client/animationinspector/components/animation-target-node.js
@@ -1,18 +1,17 @@
 /* -*- 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 {Cu} = require("chrome");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {DomNodePreview} = require("devtools/client/inspector/shared/dom-node-preview");
 
 // Map dom node fronts by animation fronts so we don't have to get them from the
 // walker every time the timeline is refreshed.
 var nodeFronts = new WeakMap();
 
 /**
--- a/devtools/client/canvasdebugger/canvasdebugger.js
+++ b/devtools/client/canvasdebugger/canvasdebugger.js
@@ -16,18 +16,17 @@ const { CallWatcherFront } = require("de
 const { CanvasFront } = require("devtools/server/actors/canvas");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { LocalizationHelper } = require("devtools/client/shared/l10n");
 const { Heritage, WidgetMethods, setNamedTimeout, clearNamedTimeout,
         setConditionalTimeout } = require("devtools/client/shared/widgets/view-helpers");
 
 const CANVAS_ACTOR_RECORDING_ATTEMPT = DevToolsUtils.testing ? 500 : 5000;
 
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
   "resource://gre/modules/PluralForm.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
   "resource://gre/modules/FileUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
--- a/devtools/client/canvasdebugger/test/head.js
+++ b/devtools/client/canvasdebugger/test/head.js
@@ -1,16 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 var { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
-var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 
 var Services = require("Services");
 var promise = require("promise");
 var { gDevTools } = require("devtools/client/framework/devtools");
 var { DebuggerClient } = require("devtools/shared/client/main");
 var { DebuggerServer } = require("devtools/server/main");
 var { CallWatcherFront } = require("devtools/server/actors/call-watcher");
--- a/devtools/client/debugger/content/actions/breakpoints.js
+++ b/devtools/client/debugger/content/actions/breakpoints.js
@@ -5,16 +5,17 @@
 
 const constants = require("../constants");
 const promise = require("promise");
 const { asPaused } = require("../utils");
 const { PROMISE } = require("devtools/client/shared/redux/middleware/promise");
 const {
   getSource, getBreakpoint, getBreakpoints, makeLocationId
 } = require("../queries");
+const { Task } = require("devtools/shared/task");
 
 // Because breakpoints are just simple data structures, we still need
 // a way to lookup the actual client instance to talk to the server.
 // We keep an internal database of clients based off of actor ID.
 const BREAKPOINT_CLIENT_STORE = new Map();
 
 function setBreakpointClient(actor, client) {
   BREAKPOINT_CLIENT_STORE.set(actor, client);
--- a/devtools/client/debugger/content/actions/event-listeners.js
+++ b/devtools/client/debugger/content/actions/event-listeners.js
@@ -2,16 +2,17 @@
  * 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 constants = require("../constants");
 const { asPaused } = require("../utils");
 const { reportException } = require("devtools/shared/DevToolsUtils");
 const { setNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
+const { Task } = require("devtools/shared/task");
 
 const FETCH_EVENT_LISTENERS_DELAY = 200; // ms
 
 function fetchEventListeners() {
   return (dispatch, getState) => {
     // Make sure we"re not sending a batch of closely repeated requests.
     // This can easily happen whenever new sources are fetched.
     setNamedTimeout("event-listeners-fetch", FETCH_EVENT_LISTENERS_DELAY, () => {
--- a/devtools/client/debugger/content/actions/sources.js
+++ b/devtools/client/debugger/content/actions/sources.js
@@ -4,16 +4,17 @@
 "use strict";
 
 const constants = require("../constants");
 const promise = require("promise");
 const Services = require("Services");
 const { dumpn } = require("devtools/shared/DevToolsUtils");
 const { PROMISE, HISTOGRAM_ID } = require("devtools/client/shared/redux/middleware/promise");
 const { getSource, getSourceText } = require("../queries");
+const { Task } = require("devtools/shared/task");
 
 const NEW_SOURCE_IGNORED_URLS = ["debugger eval code", "XStringBundle"];
 const FETCH_SOURCE_RESPONSE_DELAY = 200; // ms
 
 function getSourceClient(source) {
   return gThreadClient.source(source);
 }
 
--- a/devtools/client/debugger/content/utils.js
+++ b/devtools/client/debugger/content/utils.js
@@ -1,16 +1,17 @@
 /* -*- 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 { reportException } = require("devtools/shared/DevToolsUtils");
+const { Task } = require("devtools/shared/task");
 
 function asPaused(client, func) {
   if (client.state != "paused") {
     return Task.spawn(function* () {
       yield client.interrupt();
       let result;
 
       try {
--- a/devtools/client/debugger/content/views/sources-view.js
+++ b/devtools/client/debugger/content/views/sources-view.js
@@ -18,16 +18,17 @@ const actions = Object.assign(
   require("../actions/breakpoints")
 );
 const { bindActionCreators } = require("devtools/client/shared/vendor/redux");
 const {
   Heritage,
   WidgetMethods,
   setNamedTimeout
 } = require("devtools/client/shared/widgets/view-helpers");
+const { Task } = require("devtools/shared/task");
 
 const NEW_SOURCE_DISPLAY_DELAY = 200; // ms
 const FUNCTION_SEARCH_POPUP_POSITION = "topcenter bottomleft";
 const BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH = 1000; // chars
 const BREAKPOINT_CONDITIONAL_POPUP_POSITION = "before_start";
 const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_X = 7; // px
 const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_Y = -3; // px
 
--- a/devtools/client/debugger/debugger-controller.js
+++ b/devtools/client/debugger/debugger-controller.js
@@ -144,22 +144,20 @@ var {Toolbox} = require("devtools/client
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var promise = require("devtools/shared/deprecated-sync-thenables");
 var Editor = require("devtools/client/sourceeditor/editor");
 var DebuggerEditor = require("devtools/client/sourceeditor/debugger");
 var {Tooltip} = require("devtools/client/shared/widgets/Tooltip");
 var FastListWidget = require("devtools/client/shared/widgets/FastListWidget");
 var {LocalizationHelper} = require("devtools/client/shared/l10n");
 var {PrefsHelper} = require("devtools/client/shared/prefs");
+var {Task} = require("devtools/shared/task");
 
 XPCOMUtils.defineConstant(this, "EVENTS", EVENTS);
 
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "Parser",
   "resource://devtools/shared/Parser.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
   "resource://gre/modules/ShortcutUtils.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
   "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
--- a/devtools/client/dom/dom-panel.js
+++ b/devtools/client/dom/dom-panel.js
@@ -6,17 +6,17 @@
 "use strict";
 
 const { Cu } = require("chrome");
 const { defer } = require("sdk/core/promise");
 const { ObjectClient } = require("devtools/shared/client/main");
 
 const promise = require("promise");
 const EventEmitter = require("devtools/shared/event-emitter");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 /**
  * This object represents DOM panel. It's responsibility is to
  * render Document Object Model of the current debugger target.
  */
 function DomPanel(iframeWindow, toolbox) {
   this.panelWin = iframeWindow;
   this._toolbox = toolbox;
--- a/devtools/client/framework/connect/connect.js
+++ b/devtools/client/framework/connect/connect.js
@@ -3,24 +3,24 @@
 /* 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";
 
 var Cu = Components.utils;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
 var {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var Services = require("Services");
 var {gDevTools} = require("devtools/client/framework/devtools");
 var {TargetFactory} = require("devtools/client/framework/target");
 var {Toolbox} = require("devtools/client/framework/toolbox");
 var promise = require("promise");
 var {DebuggerClient} = require("devtools/shared/client/main");
+var {Task} = require("devtools/shared/task");
 
 var gClient;
 var gConnectionTimeout;
 
 XPCOMUtils.defineLazyGetter(window, "l10n", function () {
   return Services.strings.createBundle("chrome://devtools/locale/connection-screen.properties");
 });
 
--- a/devtools/client/framework/sidebar.js
+++ b/devtools/client/framework/sidebar.js
@@ -4,17 +4,17 @@
  * 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/. */
 
 const {Cu} = require("chrome");
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 var Services = require("Services");
-var {Task} = require("resource://gre/modules/Task.jsm");
+var {Task} = require("devtools/shared/task");
 var EventEmitter = require("devtools/shared/event-emitter");
 var Telemetry = require("devtools/client/shared/telemetry");
 
 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 /**
  * ToolSidebar provides methods to register tabs in the sidebar.
  * It's assumed that the sidebar contains a xul:tabbox.
--- a/devtools/client/framework/source-location.js
+++ b/devtools/client/framework/source-location.js
@@ -1,14 +1,14 @@
 /* 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 { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { assert } = require("devtools/shared/DevToolsUtils");
 
 /**
  * A manager class that wraps a TabTarget and listens to source changes
  * from source maps and resolves non-source mapped locations to the source mapped
  * versions and back and forth, and creating smart elements with a location that
  * auto-update when the source changes (from pretty printing, source maps loading, etc)
  *
--- a/devtools/client/framework/target-from-url.js
+++ b/devtools/client/framework/target-from-url.js
@@ -4,17 +4,17 @@
 
 "use strict";
 
 const { Cu, Ci } = require("chrome");
 
 const { TargetFactory } = require("devtools/client/framework/target");
 const { DebuggerServer } = require("devtools/server/main");
 const { DebuggerClient } = require("devtools/shared/client/main");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 /**
  * Construct a Target for a given URL object having various query parameters:
  *
  * type: tab, process
  *    {String} The type of target to connect to.  Currently tabs and processes are supported types.
  *
  * If type="tab":
--- a/devtools/client/framework/test/shared-head.js
+++ b/devtools/client/framework/test/shared-head.js
@@ -22,17 +22,17 @@ const {console} = scopedCuImport("resour
 const {ScratchpadManager} = scopedCuImport("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
 const {loader, require} = scopedCuImport("resource://devtools/shared/Loader.jsm");
 
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {TargetFactory} = require("devtools/client/framework/target");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 let promise = require("promise");
 const Services = require("Services");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 
 const TEST_DIR = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
 const CHROME_URL_ROOT = TEST_DIR + "/";
 const URL_ROOT = CHROME_URL_ROOT.replace("chrome://mochitests/content/",
                                          "http://example.com/");
 const URL_ROOT_SSL = CHROME_URL_ROOT.replace("chrome://mochitests/content/",
                                              "https://example.com/");
--- a/devtools/client/framework/toolbox-highlighter-utils.js
+++ b/devtools/client/framework/toolbox-highlighter-utils.js
@@ -2,17 +2,17 @@
 /* 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 promise = require("promise");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 
 /**
  * Client-side highlighter shared module.
  * To be used by toolbox panels that need to highlight DOM elements.
  *
  * Highlighting and selecting elements is common enough that it needs to be at
  * toolbox level, accessible by any panel that needs it.
--- a/devtools/client/framework/toolbox-init.js
+++ b/devtools/client/framework/toolbox-init.js
@@ -14,17 +14,17 @@ if (url.search.length > 1) {
   const Ci = Components.interfaces;
   const { gDevTools } = Cu.import("resource://devtools/client/framework/gDevTools.jsm", {});
   const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
   const { targetFromURL } = require("devtools/client/framework/target-from-url");
   const { Toolbox } = require("devtools/client/framework/toolbox");
   const { TargetFactory } = require("devtools/client/framework/target");
   const { DebuggerServer } = require("devtools/server/main");
   const { DebuggerClient } = require("devtools/shared/client/main");
-  const { Task } = require("resource://gre/modules/Task.jsm");
+  const { Task } = require("devtools/shared/task");
 
   // `host` is the frame element loading the toolbox.
   let host = window.QueryInterface(Ci.nsIInterfaceRequestor)
                    .getInterface(Ci.nsIDOMWindowUtils)
                    .containerElement;
 
   // Specify the default tool to open
   let tool = url.searchParams.get("tool");
--- a/devtools/client/framework/toolbox-options.js
+++ b/devtools/client/framework/toolbox-options.js
@@ -4,17 +4,17 @@
  * 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 Services = require("Services");
 const promise = require("promise");
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const {gDevTools} = require("devtools/client/framework/devtools");
 
 exports.OptionsPanel = OptionsPanel;
 
 XPCOMUtils.defineLazyGetter(this, "l10n", function () {
   let bundle = Services.strings.createBundle("chrome://devtools/locale/toolbox.properties");
   let l10n = function (name, ...aArgs) {
     try {
--- a/devtools/client/framework/toolbox-process-window.js
+++ b/devtools/client/framework/toolbox-process-window.js
@@ -13,17 +13,17 @@ var { loader, require } = Cu.import("res
 loader.require("devtools/client/framework/devtools-browser");
 
 var { gDevTools } = require("devtools/client/framework/devtools");
 var { TargetFactory } = require("devtools/client/framework/target");
 var { Toolbox } = require("devtools/client/framework/toolbox");
 var Services = require("Services");
 var { DebuggerClient } = require("devtools/shared/client/main");
 var { PrefsHelper } = require("devtools/client/shared/prefs");
-var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+var { Task } = require("devtools/shared/task");
 
 /**
  * Shortcuts for accessing various debugger preferences.
  */
 var Prefs = new PrefsHelper("devtools.debugger", {
   chromeDebuggingHost: ["Char", "chrome-debugging-host"],
   chromeDebuggingPort: ["Int", "chrome-debugging-port"]
 });
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -14,17 +14,17 @@ const MIN_ZOOM = 0.5;
 const MAX_ZOOM = 2;
 const OS_HISTOGRAM = "DEVTOOLS_OS_ENUMERATED_PER_USER";
 const OS_IS_64_BITS = "DEVTOOLS_OS_IS_64_BITS_PER_USER";
 const SCREENSIZE_HISTOGRAM = "DEVTOOLS_SCREEN_RESOLUTION_ENUMERATED_PER_USER";
 
 var {Cc, Ci, Cu} = require("chrome");
 var promise = require("promise");
 var Services = require("Services");
-var {Task} = require("resource://gre/modules/Task.jsm");
+var {Task} = require("devtools/shared/task");
 var {gDevTools} = require("devtools/client/framework/devtools");
 var EventEmitter = require("devtools/shared/event-emitter");
 var Telemetry = require("devtools/client/shared/telemetry");
 var HUDService = require("devtools/client/webconsole/hudservice");
 var viewSource = require("devtools/client/shared/view-source");
 var { attachThread, detachThread } = require("./attach-thread");
 
 Cu.import("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
--- a/devtools/client/inspector/breadcrumbs.js
+++ b/devtools/client/inspector/breadcrumbs.js
@@ -100,17 +100,17 @@ HTMLBreadcrumbs.prototype = {
 
   /**
 
    * Build a string that represents the node: tagName#id.class1.class2.
    * @param {NodeFront} node The node to pretty-print
    * @return {String}
    */
   prettyPrintNodeAsText: function (node) {
-    let text = node.tagName.toLowerCase();
+    let text = node.displayName;
     if (node.isPseudoElement) {
       text = node.isBeforePseudoElement ? "::before" : "::after";
     }
 
     if (node.id) {
       text += "#" + node.id;
     }
 
@@ -146,17 +146,17 @@ HTMLBreadcrumbs.prototype = {
     idLabel.className = "breadcrumbs-widget-item-id plain";
 
     let classesLabel = this.chromeDoc.createElement("label");
     classesLabel.className = "breadcrumbs-widget-item-classes plain";
 
     let pseudosLabel = this.chromeDoc.createElement("label");
     pseudosLabel.className = "breadcrumbs-widget-item-pseudo-classes plain";
 
-    let tagText = node.tagName.toLowerCase();
+    let tagText = node.displayName;
     if (node.isPseudoElement) {
       tagText = node.isBeforePseudoElement ? "::before" : "::after";
     }
     let idText = node.id ? ("#" + node.id) : "";
     let classesText = "";
 
     if (node.className) {
       let classList = node.className.split(/\s+/);
--- a/devtools/client/inspector/fonts/fonts.js
+++ b/devtools/client/inspector/fonts/fonts.js
@@ -1,26 +1,23 @@
 /* -*- 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 {Cu} = require("chrome");
 const {gDevTools} = require("devtools/client/framework/devtools");
 const Services = require("Services");
 
 const DEFAULT_PREVIEW_TEXT = "Abc";
 const PREVIEW_UPDATE_DELAY = 150;
 
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 
 function FontInspector(inspector, window) {
   this.inspector = inspector;
   this.pageStyle = this.inspector.pageStyle;
   this.chromeDoc = window.document;
   this.init();
 }
 
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -10,16 +10,17 @@ const {Cc, Ci, Cu} = require("chrome");
 
 var Services = require("Services");
 var promise = require("promise");
 var EventEmitter = require("devtools/shared/event-emitter");
 var clipboard = require("sdk/clipboard");
 var {HostType} = require("devtools/client/framework/toolbox").Toolbox;
 const {executeSoon} = require("devtools/shared/DevToolsUtils");
 var {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
+var {Task} = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "CSS", "CSS");
 
 loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true);
 loader.lazyRequireGetter(this, "ComputedViewTool", "devtools/client/inspector/computed/computed", true);
 loader.lazyRequireGetter(this, "FontInspector", "devtools/client/inspector/fonts/fonts", true);
 loader.lazyRequireGetter(this, "HTMLBreadcrumbs", "devtools/client/inspector/breadcrumbs", true);
 loader.lazyRequireGetter(this, "InspectorSearch", "devtools/client/inspector/inspector-search", true);
--- a/devtools/client/inspector/inspector-search.js
+++ b/devtools/client/inspector/inspector-search.js
@@ -2,16 +2,17 @@
  * 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 {Cu, Ci} = require("chrome");
 
 const promise = require("promise");
+const {Task} = require("devtools/shared/task");
 
 loader.lazyGetter(this, "system", () => require("devtools/shared/system"));
 loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
 loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/client/shared/autocomplete-popup").AutocompletePopup);
 
 // Maximum number of selector suggestions shown in the panel.
 const MAX_SUGGESTIONS = 15;
 
@@ -446,21 +447,16 @@ SelectorAutocompleter.prototype = {
         value = attrPart + value;
       }
 
       let item = {
         preLabel: query,
         label: value
       };
 
-      // In case of tagNames, change the case to small
-      if (value.match(/.*[\.#][^\.#]{0,}$/) == null) {
-        item.label = value.toLowerCase();
-      }
-
       // In case the query's state is tag and the item's state is id or class
       // adjust the preLabel
       if (aState === this.States.TAG && state === this.States.CLASS) {
         item.preLabel = "." + item.preLabel;
       }
       if (aState === this.States.TAG && state === this.States.ID) {
         item.preLabel = "#" + item.preLabel;
       }
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -2,17 +2,17 @@
 /* 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 {Cc, Ci} = require("chrome");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const {InplaceEditor, editableItem} =
       require("devtools/client/shared/inplace-editor");
 const {ReflowFront} = require("devtools/server/actors/layout");
 const {LocalizationHelper} = require("devtools/client/shared/l10n");
 
 const STRINGS_URI = "chrome://devtools/locale/shared.properties";
 const SHARED_L10N = new LocalizationHelper(STRINGS_URI);
 const NUMERIC = /^-?[\d\.]+$/;
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -36,17 +36,17 @@ const promise = require("promise");
 const Services = require("Services");
 const {Tooltip} = require("devtools/client/shared/widgets/Tooltip");
 const EventEmitter = require("devtools/shared/event-emitter");
 const Heritage = require("sdk/core/heritage");
 const {parseAttribute} =
       require("devtools/client/shared/node-attribute-parser");
 const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis",
       Ci.nsIPrefLocalizedString).data;
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const {scrollIntoViewIfNeeded} = require("devtools/shared/layout/utils");
 const {PrefObserver} = require("devtools/client/styleeditor/utils");
 const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 const {template} = require("devtools/shared/gcli/templater");
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 loader.lazyRequireGetter(this, "CSS", "CSS");
@@ -2707,21 +2707,21 @@ function ElementEditor(container, node) 
       this.container.undo.do(() => {
         doMods.apply();
       }, function () {
         undoMods.apply();
       });
     }
   });
 
-  let tagName = this.getTagName(this.node);
-  this.tag.textContent = tagName;
-  this.closeTag.textContent = tagName;
-
-  let isVoidElement = HTML_VOID_ELEMENTS.includes(tagName);
+  let displayName = this.node.displayName;
+  this.tag.textContent = displayName;
+  this.closeTag.textContent = displayName;
+
+  let isVoidElement = HTML_VOID_ELEMENTS.includes(displayName);
   if (node.isInHTMLDocument && isVoidElement) {
     this.elt.classList.add("void-element");
   }
 
   this.update();
   this.initialized = true;
 }
 
@@ -2740,33 +2740,16 @@ ElementEditor.prototype = {
     flashElementOn(this.getAttributeElement(attrName));
 
     this.animationTimers[attrName] = setTimeout(() => {
       flashElementOff(this.getAttributeElement(attrName));
     }, this.markup.CONTAINER_FLASHING_DURATION);
   },
 
   /**
-   * Returns the name of a node.
-   *
-   * @param  {DOMNode} node
-   *         The node to get the name of.
-   * @return {String} A tag name with correct case
-   */
-  getTagName: function (node) {
-    // Check the node is a SVG element
-    if (node.namespaceURI === "http://www.w3.org/2000/svg") {
-      // nodeName is already in the correct case
-      return node.nodeName;
-    }
-
-    return node.nodeName.toLowerCase();
-  },
-
-  /**
    * Returns information about node in the editor.
    *
    * @param  {DOMNode} node
    *         The node to get information from.
    * @return {Object} An object literal with the following information:
    *         {type: "attribute", name: "rel", value: "index", el: node}
    */
   getInfoAtNode: function (node) {
--- a/devtools/client/inspector/rules/models/rule.js
+++ b/devtools/client/inspector/rules/models/rule.js
@@ -78,17 +78,17 @@ Rule.prototype = {
   },
 
   get inheritedSource() {
     if (this._inheritedSource) {
       return this._inheritedSource;
     }
     this._inheritedSource = "";
     if (this.inherited) {
-      let eltText = this.inherited.tagName.toLowerCase();
+      let eltText = this.inherited.displayName;
       if (this.inherited.id) {
         eltText += "#" + this.inherited.id;
       }
       this._inheritedSource =
         CssLogic._strings.formatStringFromName("rule.inheritedFrom",
                                                [eltText], 1);
     }
     return this._inheritedSource;
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -6,17 +6,17 @@
 /* globals gDevTools */
 
 "use strict";
 
 const {Cc, Ci} = require("chrome");
 const promise = require("promise");
 const Services = require("Services");
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const {Tools} = require("devtools/client/definitions");
 const {CssLogic} = require("devtools/shared/inspector/css-logic");
 const {ELEMENT_STYLE} = require("devtools/server/actors/styles");
 const {OutputParser} = require("devtools/client/shared/output-parser");
 const {PrefObserver, PREF_ORIG_SOURCES} =
       require("devtools/client/styleeditor/utils");
 const {ElementStyle} =
       require("devtools/client/inspector/rules/models/element-style");
--- a/devtools/client/inspector/shared/dom-node-preview.js
+++ b/devtools/client/inspector/shared/dom-node-preview.js
@@ -1,15 +1,14 @@
 /* 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 {Cu} = require("chrome");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {createNode} = require("devtools/client/animationinspector/utils");
 const { LocalizationHelper } = require("devtools/client/shared/l10n");
 
 const STRINGS_URI = "chrome://devtools/locale/inspector.properties";
 const L10N = new LocalizationHelper(STRINGS_URI);
 
 /**
@@ -273,26 +272,26 @@ DomNodePreview.prototype = {
         this.render(this.nodeFront);
         break;
       }
     }
   },
 
   render: function (nodeFront) {
     this.nodeFront = nodeFront;
-    let {tagName, attributes} = nodeFront;
+    let {displayName, attributes} = nodeFront;
 
     if (nodeFront.isPseudoElement) {
       this.pseudoEl.textContent = nodeFront.isBeforePseudoElement
                                    ? "::before"
                                    : "::after";
       this.pseudoEl.style.display = "inline";
       this.tagNameEl.style.display = "none";
     } else {
-      this.tagNameEl.textContent = tagName.toLowerCase();
+      this.tagNameEl.textContent = displayName;
       this.pseudoEl.style.display = "none";
       this.tagNameEl.style.display = "inline";
     }
 
     let idIndex = attributes.findIndex(({name}) => name === "id");
     if (idIndex > -1 && attributes[idIndex].value) {
       this.idEl.querySelector(".attribute-value").textContent =
         attributes[idIndex].value;
--- a/devtools/client/inspector/shared/style-inspector-menu.js
+++ b/devtools/client/inspector/shared/style-inspector-menu.js
@@ -4,17 +4,17 @@
  * 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/. */
 /* global _strings */
 
 "use strict";
 
 const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const Services = require("Services");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "overlays",
   "devtools/client/inspector/shared/style-inspector-overlays");
 loader.lazyServiceGetter(this, "clipboardHelper",
   "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
 loader.lazyGetter(this, "_strings", () => {
   return Services.strings
   .createBundle("chrome://devtools-shared/locale/styleinspector.properties");
--- a/devtools/client/inspector/shared/style-inspector-overlays.js
+++ b/devtools/client/inspector/shared/style-inspector-overlays.js
@@ -7,27 +7,26 @@
 "use strict";
 
 // The style-inspector overlays are:
 // - tooltips that appear when hovering over property values
 // - editor tooltips that appear when clicking color swatches, etc.
 // - in-content highlighters that appear when hovering over property values
 // - etc.
 
-const {Cu} = require("chrome");
 const {
   Tooltip,
   SwatchColorPickerTooltip,
   SwatchCubicBezierTooltip,
   CssDocsTooltip,
   SwatchFilterTooltip
 } = require("devtools/client/shared/widgets/Tooltip");
 const EventEmitter = require("devtools/shared/event-emitter");
 const promise = require("promise");
-Cu.import("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const Services = require("Services");
 
 const PREF_IMAGE_TOOLTIP_SIZE = "devtools.inspector.imagePreviewTooltipSize";
 
 // Types of existing tooltips
 const TOOLTIP_IMAGE_TYPE = "image";
 const TOOLTIP_FONTFAMILY_TYPE = "font-family";
 
--- a/devtools/client/inspector/test/browser_inspector_breadcrumbs.js
+++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs.js
@@ -2,57 +2,73 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 // Test that the breadcrumbs widget content is correct.
 
 const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs.html";
 const NODES = [
-  {selector: "#i1111", result: "i1 i11 i111 i1111"},
-  {selector: "#i22", result: "i2 i22"},
-  {selector: "#i2111", result: "i2 i21 i211 i2111"},
-  {selector: "#i21", result: "i2 i21 i211 i2111"},
-  {selector: "#i22211", result: "i2 i22 i222 i2221 i22211"},
-  {selector: "#i22", result: "i2 i22 i222 i2221 i22211"},
-  {selector: "#i3", result: "i3"},
+  {selector: "#i1111", ids: "i1 i11 i111 i1111", nodeName: "div",
+    title: "div#i1111"},
+  {selector: "#i22", ids: "i2 i22", nodeName: "div",
+    title: "div#i22"},
+  {selector: "#i2111", ids: "i2 i21 i211 i2111", nodeName: "div",
+    title: "div#i2111"},
+  {selector: "#i21", ids: "i2 i21 i211 i2111", nodeName: "div",
+    title: "div#i21"},
+  {selector: "#i22211", ids: "i2 i22 i222 i2221 i22211", nodeName: "div",
+    title: "div#i22211"},
+  {selector: "#i22", ids: "i2 i22 i222 i2221 i22211", nodeName: "div",
+    title: "div#i22"},
+  {selector: "#i3", ids: "i3", nodeName: "article",
+    title: "article#i3"},
+  {selector: "clipPath", ids: "vector clip", nodeName: "clipPath",
+    title: "clipPath#clip"},
 ];
 
 add_task(function* () {
   let { inspector } = yield openInspectorForURL(TEST_URI);
   let container = inspector.panelDoc.getElementById("inspector-breadcrumbs");
 
   for (let node of NODES) {
     info("Testing node " + node.selector);
 
     info("Selecting node and waiting for breadcrumbs to update");
     let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
     yield selectNode(node.selector, inspector);
     yield breadcrumbsUpdated;
 
     info("Performing checks for node " + node.selector);
-    let buttonsLabelIds = node.result.split(" ");
+    let buttonsLabelIds = node.ids.split(" ");
 
     // html > body > …
     is(container.childNodes.length, buttonsLabelIds.length + 2,
       "Node " + node.selector + ": Items count");
 
     for (let i = 2; i < container.childNodes.length; i++) {
       let expectedId = "#" + buttonsLabelIds[i - 2];
       let button = container.childNodes[i];
       let labelId = button.querySelector(".breadcrumbs-widget-item-id");
       is(labelId.textContent, expectedId,
-        "Node #" + node.selector + ": button " + i + " matches");
+        "Node " + node.selector + ": button " + i + " matches");
     }
 
     let checkedButton = container.querySelector("button[checked]");
     let labelId = checkedButton.querySelector(".breadcrumbs-widget-item-id");
     let id = inspector.selection.nodeFront.id;
     is(labelId.textContent, "#" + id,
-      "Node #" + node.selector + ": selection matches");
+      "Node " + node.selector + ": selection matches");
+
+    let labelTag = checkedButton.querySelector(".breadcrumbs-widget-item-tag");
+    is(labelTag.textContent, node.nodeName,
+      "Node " + node.selector + " has the expected tag name");
+
+    is(checkedButton.getAttribute("tooltiptext"), node.title,
+      "Node " + node.selector + " has the expected tooltip");
   }
 
   yield testPseudoElements(inspector, container);
 });
 
 function* testPseudoElements(inspector, container) {
   info("Checking for pseudo elements");
 
--- a/devtools/client/inspector/test/browser_inspector_infobar_01.js
+++ b/devtools/client/inspector/test/browser_inspector_infobar_01.js
@@ -10,44 +10,52 @@ const TEST_URI = URL_ROOT + "doc_inspect
 
 add_task(function* () {
   let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
 
   let testData = [
     {
       selector: "#top",
       position: "bottom",
-      tag: "DIV",
+      tag: "div",
       id: "top",
       classes: ".class1.class2",
       dims: "500" + " \u00D7 " + "100"
     },
     {
       selector: "#vertical",
       position: "overlap",
-      tag: "DIV",
+      tag: "div",
       id: "vertical",
       classes: ""
       // No dims as they will vary between computers
     },
     {
       selector: "#bottom",
       position: "top",
-      tag: "DIV",
+      tag: "div",
       id: "bottom",
       classes: "",
       dims: "500" + " \u00D7 " + "100"
     },
     {
       selector: "body",
       position: "bottom",
-      tag: "BODY",
+      tag: "body",
       classes: ""
       // No dims as they will vary between computers
     },
+    {
+      selector: "clipPath",
+      position: "bottom",
+      tag: "clipPath",
+      id: "clip",
+      classes: ""
+      // No dims as element is not displayed and we just want to test tag name
+    },
   ];
 
   for (let currTest of testData) {
     yield testPosition(currTest, inspector, testActor);
   }
 });
 
 function* testPosition(test, inspector, testActor) {
--- a/devtools/client/inspector/test/browser_inspector_search-07.js
+++ b/devtools/client/inspector/test/browser_inspector_search-07.js
@@ -6,17 +6,17 @@
 // Test that searching for classes on SVG elements does work (see bug 1219920).
 
 const TEST_URL = URL_ROOT + "doc_inspector_search-svg.html";
 
 // An array of (key, suggestions) pairs where key is a key to press and
 // suggestions is an array of suggestions that should be shown in the popup.
 const TEST_DATA = [{
   key: "c",
-  suggestions: ["circle", ".class1", ".class2"]
+  suggestions: ["circle", "clipPath", ".class1", ".class2"]
 }, {
   key: "VK_BACK_SPACE",
   suggestions: []
 }, {
   key: ".",
   suggestions: [".class1", ".class2"]
 }];
 
--- a/devtools/client/inspector/test/doc_inspector_breadcrumbs.html
+++ b/devtools/client/inspector/test/doc_inspector_breadcrumbs.html
@@ -59,10 +59,16 @@
       <link />
       <link />
       <link />
       <link />
       <link />
       <link />
     </article>
     <div id='pseudo-container'></div>
+    <svg id="vector" viewBox="0 0 10 10">
+      <clipPath id="clip">
+        <rect id="rectangle" x="0" y="0" width="10" height="5"></rect>
+      </clipPath>
+      <circle cx="5" cy="5" r="5" fill="blue" clip-path="url(#clip)"></circle>
+    </svg>
   </body>
 </html>
--- a/devtools/client/inspector/test/doc_inspector_infobar_01.html
+++ b/devtools/client/inspector/test/doc_inspector_infobar_01.html
@@ -18,16 +18,27 @@
       bottom: 0px;
       background: blue;
     }
 
     #vertical {
       height: 100%;
       background: green;
     }
+
+    svg {
+      width: 10px;
+      height: 10px;
+    }
    </style>
  </head>
  <body>
   <div id="vertical">Vertical</div>
   <div id="top" class="class1 class2">Top</div>
   <div id="bottom">Bottom</div>
+  <svg viewBox="0 0 10 10">
+    <clipPath id="clip">
+      <rect x="0" y="0" width="10" height="5"></rect>
+    </clipPath>
+    <circle cx="5" cy="5" r="5" fill="blue" clip-path="url(#clip)"></circle>
+  </svg>
  </body>
  </html>
--- a/devtools/client/inspector/test/doc_inspector_search-svg.html
+++ b/devtools/client/inspector/test/doc_inspector_search-svg.html
@@ -2,12 +2,15 @@
 <html lang="en">
 <head>
   <meta charset="utf-8">
   <title>Inspector SVG Search Box Test</title>
 </head>
 <body>
   <div class="class1"></div>
   <svg>
+    <clipPath>
+      <rect x="0" y="0" width="10" height="5"></rect>
+    </clipPath>
     <circle cx="0" cy="0" r="50" class="class2" />
   </svg>
 </body>
 </html>
--- a/devtools/client/memory/initializer.js
+++ b/devtools/client/memory/initializer.js
@@ -6,17 +6,17 @@
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 const BrowserLoaderModule = {};
 Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
 const { require } = BrowserLoaderModule.BrowserLoader({
   baseURI: "resource://devtools/client/memory/",
   window: this
 });
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
 const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 const App = createFactory(require("devtools/client/memory/app"));
 const Store = require("devtools/client/memory/store");
 const { assert } = require("devtools/shared/DevToolsUtils");
 
 /**
--- a/devtools/client/memory/panel.js
+++ b/devtools/client/memory/panel.js
@@ -1,16 +1,16 @@
 /* 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 { Cc, Ci, Cu, Cr } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { MemoryFront } = require("devtools/server/actors/memory");
 const HeapAnalysesClient = require("devtools/shared/heapsnapshot/HeapAnalysesClient");
 const promise = require("promise");
 
 function MemoryPanel(iframeWindow, toolbox) {
   this.panelWin = iframeWindow;
   this._toolbox = toolbox;
--- a/devtools/client/memory/test/chrome/head.js
+++ b/devtools/client/memory/test/chrome/head.js
@@ -7,17 +7,17 @@ var { classes: Cc, interfaces: Ci, utils
 Cu.import("resource://testing-common/Assert.jsm");
 
 Cu.import("resource://devtools/client/shared/browser-loader.js");
 var { require } = BrowserLoader({
   baseURI: "resource://devtools/client/memory/",
   window: this
 });
 var Services = require("Services");
-var { Task } = require("resource://gre/modules/Task.jsm");
+var { Task } = require("devtools/shared/task");
 
 var EXPECTED_DTU_ASSERT_FAILURE_COUNT = 0;
 
 SimpleTest.registerCleanupFunction(function () {
   if (DevToolsUtils.assertionFailureCount !== EXPECTED_DTU_ASSERT_FAILURE_COUNT) {
     ok(false, "Should have had the expected number of DevToolsUtils.assert() failures. Expected " +
        EXPECTED_DTU_ASSERT_FAILURE_COUNT + ", got " + DevToolsUtils.assertionFailureCount);
   }
--- a/devtools/client/memory/test/unit/head.js
+++ b/devtools/client/memory/test/unit/head.js
@@ -12,17 +12,17 @@ var DevToolsUtils = require("devtools/sh
 DevToolsUtils.testing = true;
 DevToolsUtils.dumpn.wantLogging = true;
 DevToolsUtils.dumpv.wantVerbose = false;
 
 var { OS } = require("resource://gre/modules/osfile.jsm");
 var { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
 var { TargetFactory } = require("devtools/client/framework/target");
 var promise = require("promise");
-var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+var { Task } = require("devtools/shared/task");
 var { expectState } = require("devtools/server/actors/common");
 var HeapSnapshotFileUtils = require("devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
 var HeapAnalysesClient = require("devtools/shared/heapsnapshot/HeapAnalysesClient");
 var { addDebuggerToGlobal } = require("resource://gre/modules/jsdebugger.jsm");
 var Store = require("devtools/client/memory/store");
 var { L10N } = require("devtools/client/memory/utils");
 var SYSTEM_PRINCIPAL = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
 
--- a/devtools/client/netmonitor/har/har-automation.js
+++ b/devtools/client/netmonitor/har/har-automation.js
@@ -1,19 +1,18 @@
 /* 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 { Cu, Ci } = require("chrome");
+const { Ci } = require("chrome");
 const { Class } = require("sdk/core/heritage");
 const { resolve } = require("promise");
 const Services = require("Services");
-
-Cu.import("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "HarCollector", "devtools/client/netmonitor/har/har-collector", true);
 loader.lazyRequireGetter(this, "HarExporter", "devtools/client/netmonitor/har/har-exporter", true);
 loader.lazyRequireGetter(this, "HarUtils", "devtools/client/netmonitor/har/har-utils", true);
 
 const prefDomain = "devtools.netmonitor.har.";
 
 // Helper tracer. Should be generic sharable by other modules (bug 1171927)
--- a/devtools/client/netmonitor/netmonitor-controller.js
+++ b/devtools/client/netmonitor/netmonitor-controller.js
@@ -114,33 +114,31 @@ Cu.import("resource://devtools/client/sh
 
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const promise = require("promise");
 const Services = require("Services");
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
 const EventEmitter = require("devtools/shared/event-emitter");
 const Editor = require("devtools/client/sourceeditor/editor");
 const {TimelineFront} = require("devtools/server/actors/timeline");
+const { Task } = require("devtools/shared/task");
 
 XPCOMUtils.defineConstant(this, "EVENTS", EVENTS);
 XPCOMUtils.defineConstant(this, "ACTIVITY_TYPE", ACTIVITY_TYPE);
 XPCOMUtils.defineConstant(this, "Editor", Editor);
 
 XPCOMUtils.defineLazyModuleGetter(this, "Chart",
   "resource://devtools/client/shared/widgets/Chart.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Curl",
   "resource://devtools/client/shared/Curl.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "CurlUtils",
   "resource://devtools/client/shared/Curl.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
   "resource://gre/modules/PluralForm.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
   "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
 
 XPCOMUtils.defineLazyServiceGetter(this, "DOMParser",
   "@mozilla.org/xmlextras/domparser;1", "nsIDOMParser");
--- a/devtools/client/netmonitor/panel.js
+++ b/devtools/client/netmonitor/panel.js
@@ -2,17 +2,17 @@
 /* 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 promise = require("promise");
 const EventEmitter = require("devtools/shared/event-emitter");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 function NetMonitorPanel(iframeWindow, toolbox) {
   this.panelWin = iframeWindow;
   this._toolbox = toolbox;
 
   this._view = this.panelWin.NetMonitorView;
   this._controller = this.panelWin.NetMonitorController;
   this._controller._target = this.target;
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
-var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var { gDevTools } = require("devtools/client/framework/devtools");
+var { Task } = require("devtools/shared/task");
 var { CurlUtils } = Cu.import("resource://devtools/client/shared/Curl.jsm", {});
 var Services = require("Services");
 var promise = require("promise");
 var NetworkHelper = require("devtools/shared/webconsole/network-helper");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var { TargetFactory } = require("devtools/client/framework/target");
 var { Toolbox } = require("devtools/client/framework/toolbox");
 
--- a/devtools/client/performance/components/test/head.js
+++ b/devtools/client/performance/components/test/head.js
@@ -5,17 +5,17 @@
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://testing-common/Assert.jsm");
 var { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
 var { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
 var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
-var { Task } = require("resource://gre/modules/Task.jsm");
+var { Task } = require("devtools/shared/task");
 var { TargetFactory } = require("devtools/client/framework/target");
 var { Toolbox } = require("devtools/client/framework/toolbox");
 
 DevToolsUtils.testing = true;
 var { require: browserRequire } = BrowserLoader({
   baseURI: "resource://devtools/client/performance/",
   window: this
 });
--- a/devtools/client/performance/legacy/actors.js
+++ b/devtools/client/performance/legacy/actors.js
@@ -1,14 +1,14 @@
 /* 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 { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 const promise = require("promise");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { Poller } = require("devtools/client/shared/poller");
 
 const CompatUtils = require("devtools/client/performance/legacy/compatibility");
 const RecordingUtils = require("devtools/shared/performance/recording-utils");
 const { TimelineFront } = require("devtools/server/actors/timeline");
--- a/devtools/client/performance/legacy/front.js
+++ b/devtools/client/performance/legacy/front.js
@@ -1,15 +1,15 @@
 /* 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 { Cu } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 const Services = require("Services");
 const promise = require("promise");
 const { extend } = require("sdk/util/object");
 
 const Actors = require("devtools/client/performance/legacy/actors");
 const { LegacyPerformanceRecording } = require("devtools/client/performance/legacy/recording");
 const { importRecording } = require("devtools/client/performance/legacy/recording");
--- a/devtools/client/performance/legacy/recording.js
+++ b/devtools/client/performance/legacy/recording.js
@@ -1,15 +1,15 @@
 /* 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 { Cc, Ci, Cu, Cr } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 const PerformanceIO = require("devtools/client/performance/modules/io");
 const RecordingUtils = require("devtools/shared/performance/recording-utils");
 const { PerformanceRecordingCommon } = require("devtools/shared/performance/recording-common");
 const { merge } = require("sdk/util/object");
 
 /**
  * Model for a wholistic profile, containing the duration, profiling data,
--- a/devtools/client/performance/modules/widgets/graphs.js
+++ b/devtools/client/performance/modules/widgets/graphs.js
@@ -3,17 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 /**
  * This file contains the base line graph that all Performance line graphs use.
  */
 
 const { Cc, Ci, Cu, Cr } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { Heritage } = require("devtools/client/shared/widgets/view-helpers");
 const LineGraphWidget = require("devtools/client/shared/widgets/LineGraphWidget");
 const BarGraphWidget = require("devtools/client/shared/widgets/BarGraphWidget");
 const MountainGraphWidget = require("devtools/client/shared/widgets/MountainGraphWidget");
 const { CanvasGraphUtils } = require("devtools/client/shared/widgets/Graphs");
 
 const promise = require("promise");
 const EventEmitter = require("devtools/shared/event-emitter");
--- a/devtools/client/performance/panel.js
+++ b/devtools/client/performance/panel.js
@@ -1,17 +1,17 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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 { Cc, Ci, Cu, Cr } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "EventEmitter",
   "devtools/shared/event-emitter");
 
 function PerformancePanel(iframeWindow, toolbox) {
   this.panelWin = iframeWindow;
   this.toolbox = toolbox;
--- a/devtools/client/performance/performance-controller.js
+++ b/devtools/client/performance/performance-controller.js
@@ -5,17 +5,17 @@
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 var BrowserLoaderModule = {};
 Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
 var { loader, require } = BrowserLoaderModule.BrowserLoader({
   baseURI: "resource://devtools/client/performance/",
   window: this
 });
-var { Task } = require("resource://gre/modules/Task.jsm");
+var { Task } = require("devtools/shared/task");
 var { Heritage, ViewHelpers, WidgetMethods, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
 var { gDevTools } = require("devtools/client/framework/devtools");
 
 // Events emitted by various objects in the panel.
 var EVENTS = require("devtools/client/performance/events");
 Object.defineProperty(this, "EVENTS", {
   value: EVENTS,
   enumerable: true,
--- a/devtools/client/performance/test/helpers/profiler-mm-utils.js
+++ b/devtools/client/performance/test/helpers/profiler-mm-utils.js
@@ -5,17 +5,17 @@
 
 /**
  * The following functions are used in testing to control and inspect
  * the nsIProfiler in child process content. These should be called from
  * the parent process.
  */
 
 const { Cc, Ci } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 const FRAME_SCRIPT_UTILS_URL = "chrome://devtools/content/shared/frame-script-utils.js";
 
 let gMM = null;
 
 /**
  * Loads the relevant frame scripts into the provided browser's message manager.
  */
--- a/devtools/client/performance/test/helpers/wait-utils.js
+++ b/devtools/client/performance/test/helpers/wait-utils.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 /* globals dump */
 
 const { CC } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { once, observeOnce } = require("devtools/client/performance/test/helpers/event-utils");
 
 /**
  * Blocks the main thread for the specified amount of time.
  */
 exports.busyWait = function (time) {
   dump(`Busy waiting for: ${time} milliseconds.\n`);
--- a/devtools/client/projecteditor/lib/project.js
+++ b/devtools/client/projecteditor/lib/project.js
@@ -7,17 +7,17 @@
 const { Cu } = require("chrome");
 const { Class } = require("sdk/core/heritage");
 const { EventTarget } = require("sdk/event/target");
 const { emit } = require("sdk/event/core");
 const { scope, on, forget } = require("devtools/client/projecteditor/lib/helpers/event");
 const prefs = require("sdk/preferences/service");
 const { LocalStore } = require("devtools/client/projecteditor/lib/stores/local");
 const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 const promise = require("promise");
 const { TextEncoder, TextDecoder } = require("sdk/io/buffer");
 const url = require("sdk/url");
 
 const gDecoder = new TextDecoder();
 const gEncoder = new TextEncoder();
 
 /**
--- a/devtools/client/projecteditor/lib/projecteditor.js
+++ b/devtools/client/projecteditor/lib/projecteditor.js
@@ -14,17 +14,17 @@ const { registeredPlugins } = require("d
 const { EventTarget } = require("sdk/event/target");
 const { on, forget } = require("devtools/client/projecteditor/lib/helpers/event");
 const { emit } = require("sdk/event/core");
 const { merge } = require("sdk/util/object");
 const promise = require("promise");
 const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
 const { DOMHelpers } = Cu.import("resource://devtools/client/shared/DOMHelpers.jsm");
 const Services = require("Services");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 const ITCHPAD_URL = "chrome://devtools/content/projecteditor/chrome/content/projecteditor.xul";
 const { confirm } = require("devtools/client/projecteditor/lib/helpers/prompts");
 const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
 
 // Enabled Plugins
 require("devtools/client/projecteditor/lib/plugins/dirty/dirty");
 require("devtools/client/projecteditor/lib/plugins/delete/delete");
 require("devtools/client/projecteditor/lib/plugins/new/new");
--- a/devtools/client/projecteditor/lib/stores/local.js
+++ b/devtools/client/projecteditor/lib/stores/local.js
@@ -4,17 +4,17 @@
  * 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/. */
 
 const { Cc, Ci, Cu, ChromeWorker } = require("chrome");
 const { Class } = require("sdk/core/heritage");
 const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
 const { emit } = require("sdk/event/core");
 const { Store } = require("devtools/client/projecteditor/lib/stores/base");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 const promise = require("promise");
 const Services = require("Services");
 const { on, forget } = require("devtools/client/projecteditor/lib/helpers/event");
 const { FileResource } = require("devtools/client/projecteditor/lib/stores/resource");
 
 const CHECK_LINKED_DIRECTORY_DELAY = 5000;
 const SHOULD_LIVE_REFRESH = true;
 // XXX: Ignores should be customizable
--- a/devtools/client/projecteditor/lib/stores/resource.js
+++ b/devtools/client/projecteditor/lib/stores/resource.js
@@ -11,17 +11,17 @@ const { TextEncoder, TextDecoder } = req
 const { Class } = require("sdk/core/heritage");
 const { EventTarget } = require("sdk/event/target");
 const { emit } = require("sdk/event/core");
 const URL = require("sdk/url");
 const promise = require("promise");
 const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
 const { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
 const mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 
 const gDecoder = new TextDecoder();
 const gEncoder = new TextEncoder();
 
 /**
  * A Resource is a single file-like object that can be respresented
  * as a file for ProjectEditor.
  *
--- a/devtools/client/promisedebugger/promise-controller.js
+++ b/devtools/client/promisedebugger/promise-controller.js
@@ -7,17 +7,17 @@
 /* global PromisesPanel */
 
 "use strict";
 
 var { utils: Cu } = Components;
 const { loader, require } =
   Cu.import("resource://devtools/shared/Loader.jsm", {});
 
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "EventEmitter",
   "devtools/shared/event-emitter");
 loader.lazyRequireGetter(this, "DevToolsUtils",
   "devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "PromisesFront",
   "devtools/server/actors/promises", true);
--- a/devtools/client/promisedebugger/promise-panel.js
+++ b/devtools/client/promisedebugger/promise-panel.js
@@ -1,15 +1,16 @@
 /* -*- 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/. */
 
 /* global PromisesController, promise */
+/* import-globals-from promise-controller.js */
 
 "use strict";
 
 /**
  * The main promise debugger UI.
  */
 var PromisesPanel = {
   PANEL_INITIALIZED: "panel-initialized",
--- a/devtools/client/responsive.html/actions/screenshot.js
+++ b/devtools/client/responsive.html/actions/screenshot.js
@@ -8,17 +8,17 @@
 
 const {
   TAKE_SCREENSHOT_START,
   TAKE_SCREENSHOT_END,
 } = require("./index");
 
 const { getFormatStr } = require("../utils/l10n");
 const { getToplevelWindow } = require("sdk/window/utils");
-const { Task: { spawn } } = require("resource://gre/modules/Task.jsm");
+const { Task: { spawn } } = require("devtools/shared/task");
 const e10s = require("../utils/e10s");
 
 const BASE_URL = "resource://devtools/client/responsive.html";
 const audioCamera = new window.Audio(`${BASE_URL}/audio/camera-click.mp3`);
 
 const animationFrame = () => new Promise(resolve => {
   window.requestAnimationFrame(resolve);
 });
--- a/devtools/client/responsive.html/browser/swap.js
+++ b/devtools/client/responsive.html/browser/swap.js
@@ -1,16 +1,16 @@
 /* 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 promise = require("promise");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 /**
  * Swap page content from an existing tab into a new browser within a container
  * page.  Page state is preserved by using `swapFrameLoaders`, just like when
  * you move a tab to a new window.  This provides a seamless transition for the
  * user since the page is not reloaded.
  *
  * See /devtools/docs/responsive-design-mode.md for a high level overview of how
--- a/devtools/client/responsive.html/components/browser.js
+++ b/devtools/client/responsive.html/components/browser.js
@@ -1,17 +1,17 @@
 /* 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/. */
 
 /* eslint-env browser */
 
 "use strict";
 
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { getToplevelWindow } = require("sdk/window/utils");
 const { DOM: dom, createClass, addons, PropTypes } =
   require("devtools/client/shared/vendor/react");
 
 const Types = require("../types");
 const e10s = require("../utils/e10s");
 const message = require("../utils/message");
--- a/devtools/client/responsive.html/devices.js
+++ b/devtools/client/responsive.html/devices.js
@@ -1,16 +1,16 @@
 /* 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 Services = require("Services");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { GetDevices } = require("devtools/client/shared/devices");
 const { addDevice, addDeviceType } = require("./actions/devices");
 
 const DISPLAYED_DEVICES_PREF = "devtools.responsive.html.displayedDeviceList";
 
 /**
  * Get the device catalog and load the devices onto the store.
  *
--- a/devtools/client/responsive.html/index.js
+++ b/devtools/client/responsive.html/index.js
@@ -8,17 +8,17 @@
 
 const { utils: Cu } = Components;
 const { BrowserLoader } =
   Cu.import("resource://devtools/client/shared/browser-loader.js", {});
 const { require } = BrowserLoader({
   baseURI: "resource://devtools/client/responsive.html/",
   window: this
 });
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const Telemetry = require("devtools/client/shared/telemetry");
 const { loadSheet } = require("sdk/stylesheet/utils");
 
 const { createFactory, createElement } =
   require("devtools/client/shared/vendor/react");
 const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
--- a/devtools/client/responsive.html/manager.js
+++ b/devtools/client/responsive.html/manager.js
@@ -1,16 +1,16 @@
 /* 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 promise = require("promise");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { TouchEventSimulator } = require("devtools/shared/touch/simulator");
 const { getOwnerWindow } = require("sdk/tabs/utils");
 const { on, off } = require("sdk/event/core");
 const { startup } = require("sdk/window/helpers");
 const events = require("./events");
 const message = require("./utils/message");
 const { swapToInnerBrowser } = require("./browser/swap");
--- a/devtools/client/responsive.html/test/unit/head.js
+++ b/devtools/client/responsive.html/test/unit/head.js
@@ -4,16 +4,16 @@
 "use strict";
 
 /* eslint no-unused-vars: [2, {"vars": "local"}] */
 
 const { utils: Cu } = Components;
 const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 
 const promise = require("promise");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const Store = require("devtools/client/responsive.html/store");
 
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 DevToolsUtils.testing = true;
 do_register_cleanup(() => {
   DevToolsUtils.testing = false;
 });
--- a/devtools/client/responsivedesign/responsivedesign.jsm
+++ b/devtools/client/responsivedesign/responsivedesign.jsm
@@ -6,17 +6,17 @@
 
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 var {loader, require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var Telemetry = require("devtools/client/shared/telemetry");
 var {showDoorhanger} = require("devtools/client/shared/doorhanger");
 var {TouchEventSimulator} = require("devtools/shared/touch/simulator");
-var {Task} = require("resource://gre/modules/Task.jsm");
+var {Task} = require("devtools/shared/task");
 var promise = require("promise");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var Services = require("Services");
 var EventEmitter = require("devtools/shared/event-emitter");
 var {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
 var { LocalizationHelper } = require("devtools/client/shared/l10n");
 
 loader.lazyImporter(this, "SystemAppProxy",
--- a/devtools/client/scratchpad/test/browser_scratchpad_autocomplete.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_autocomplete.js
@@ -1,17 +1,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 /* Bug 968896 */
 
 // Test the completions using numbers.
 const source = "0x1.";
 const completions = ["toExponential", "toFixed", "toString"];
-Cu.import("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 function test() {
   const options = { tabContent: "test scratchpad autocomplete" };
   openTabAndScratchpad(options)
     .then(Task.async(runTests))
     .then(finish, console.error);
 }
 
--- a/devtools/client/scratchpad/test/browser_scratchpad_close_toolbox.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_close_toolbox.js
@@ -1,15 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that closing the toolbox after having opened a scratchpad leaves the
 // latter in a functioning state.
 
-var {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+var {Task} = require("devtools/shared/task");
 var {TargetFactory} = require("devtools/client/framework/target");
 
 function test() {
   const options = {
     tabContent: "test closing toolbox and then reusing scratchpad"
   };
   openTabAndScratchpad(options)
     .then(Task.async(runTests))
--- a/devtools/client/scratchpad/test/browser_scratchpad_disable_view_menu_items.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_disable_view_menu_items.js
@@ -1,15 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test if the view menu items "Larger Font" and "Smaller Font" are disabled
 // when the font size reaches the maximum/minimum values.
 
-var {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+var {Task} = require("devtools/shared/task");
 
 function test() {
   const options = {
     tabContent: 'test if view menu items "Larger Font" and "Smaller Font" are enabled/disabled.'
   };
   openTabAndScratchpad(options)
     .then(Task.async(runTests))
     .then(finish, console.error);
--- a/devtools/client/scratchpad/test/browser_scratchpad_inspect_primitives.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_inspect_primitives.js
@@ -1,15 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that inspecting primitive values uses the object inspector, not an
 // inline comment.
 
-var {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+var {Task} = require("devtools/shared/task");
 
 function test() {
   const options = {
     tabContent: "test inspecting primitive values"
   };
   openTabAndScratchpad(options)
     .then(Task.async(runTests))
     .then(finish, console.error);
--- a/devtools/client/shadereditor/shadereditor.js
+++ b/devtools/client/shadereditor/shadereditor.js
@@ -1,28 +1,28 @@
 /* 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";
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://devtools/client/shared/widgets/SideMenuWidget.jsm");
 
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const promise = require("promise");
 const Services = require("Services");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {Tooltip} = require("devtools/client/shared/widgets/Tooltip");
 const Editor = require("devtools/client/sourceeditor/editor");
 const {LocalizationHelper} = require("devtools/client/shared/l10n");
 const {Heritage, WidgetMethods, setNamedTimeout} =
   require("devtools/client/shared/widgets/view-helpers");
+const {Task} = require("devtools/shared/task");
 
 // The panel's window global is an EventEmitter firing the following events:
 const EVENTS = {
   // When new programs are received from the server.
   NEW_PROGRAM: "ShaderEditor:NewProgram",
   PROGRAMS_ADDED: "ShaderEditor:ProgramsAdded",
 
   // When the vertex and fragment sources were shown in the editor.
--- a/devtools/client/shadereditor/test/head.js
+++ b/devtools/client/shadereditor/test/head.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
-var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
+var { Task } = require("devtools/shared/task");
 
 var Services = require("Services");
 var promise = require("promise");
 var { gDevTools } = require("devtools/client/framework/devtools");
 var { DebuggerClient } = require("devtools/shared/client/main");
 var { DebuggerServer } = require("devtools/server/main");
 var { WebGLFront } = require("devtools/server/actors/webgl");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
--- a/devtools/client/shared/components/test/mochitest/head.js
+++ b/devtools/client/shared/components/test/mochitest/head.js
@@ -9,17 +9,17 @@ Cu.import("resource://testing-common/Ass
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var { gDevTools } = require("devtools/client/framework/devtools");
 var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
 var promise = require("promise");
 var Services = require("Services");
 var { DebuggerServer } = require("devtools/server/main");
 var { DebuggerClient } = require("devtools/shared/client/main");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
-var { Task } = require("resource://gre/modules/Task.jsm");
+var { Task } = require("devtools/shared/task");
 var { TargetFactory } = require("devtools/client/framework/target");
 var { Toolbox } = require("devtools/client/framework/toolbox");
 
 DevToolsUtils.testing = true;
 var { require: browserRequire } = BrowserLoader({
   baseURI: "resource://devtools/client/shared/",
   window: this
 });
--- a/devtools/client/shared/css-parsing-utils.js
+++ b/devtools/client/shared/css-parsing-utils.js
@@ -9,21 +9,21 @@
 // parseDeclarations - parse a CSS rule into declarations
 // RuleRewriter - rewrite CSS rule text
 // parsePseudoClassesAndAttributes - parse selector and extract
 //     pseudo-classes
 // parseSingleValue - parse a single CSS property value
 
 "use strict";
 
-const {Cc, Ci, Cu} = require("chrome");
+const {Cc, Ci} = require("chrome");
 loader.lazyRequireGetter(this, "CSS", "CSS");
 const promise = require("promise");
 const {getCSSLexer} = require("devtools/shared/css-lexer");
-Cu.import("resource://gre/modules/Task.jsm", this);
+const {Task} = require("devtools/shared/task");
 loader.lazyGetter(this, "DOMUtils", () => {
   return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
 });
 
 const SELECTOR_ATTRIBUTE = exports.SELECTOR_ATTRIBUTE = 1;
 const SELECTOR_ELEMENT = exports.SELECTOR_ELEMENT = 2;
 const SELECTOR_PSEUDO_CLASS = exports.SELECTOR_PSEUDO_CLASS = 3;
 
--- a/devtools/client/shared/doorhanger.js
+++ b/devtools/client/shared/doorhanger.js
@@ -2,17 +2,17 @@
  * 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, Cc } = require("chrome");
 const Services = require("Services");
 const { DOMHelpers } = require("resource://devtools/client/shared/DOMHelpers.jsm");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { Promise } = require("resource://gre/modules/Promise.jsm");
 const { getMostRecentBrowserWindow } = require("sdk/window/utils");
 
 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const DEV_EDITION_PROMO_URL = "chrome://devtools/content/framework/dev-edition-promo/dev-edition-promo.xul";
 const DEV_EDITION_PROMO_ENABLED_PREF = "devtools.devedition.promo.enabled";
 const DEV_EDITION_PROMO_SHOWN_PREF = "devtools.devedition.promo.shown";
 const DEV_EDITION_PROMO_URL_PREF = "devtools.devedition.promo.url";
--- a/devtools/client/shared/frame-script-utils.js
+++ b/devtools/client/shared/frame-script-utils.js
@@ -1,17 +1,17 @@
 /* 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";
 var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 const {require, loader} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const promise = require("promise");
-loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm", "Task");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyGetter(this, "nsIProfilerModule", () => {
   return Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
 });
 
 addMessageListener("devtools:test:history", function ({ data }) {
   content.history[data.direction]();
 });
--- a/devtools/client/shared/redux/middleware/task.js
+++ b/devtools/client/shared/redux/middleware/task.js
@@ -1,14 +1,14 @@
 /* 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 { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { executeSoon, isGenerator, reportException } = require("devtools/shared/DevToolsUtils");
 const ERROR_TYPE = exports.ERROR_TYPE = "@@redux/middleware/task#error";
 
 /**
  * A middleware that allows generator thunks (functions) and promise
  * to be dispatched. If it's a generator, it is called with `dispatch`
  * and `getState`, allowing the action to create multiple actions (most likely
  * asynchronously) and yield on each. If called with a promise, calls `dispatch`
--- a/devtools/client/shared/test/test-actor.js
+++ b/devtools/client/shared/test/test-actor.js
@@ -4,17 +4,17 @@
 
 "use strict";
 
 // A helper actor for inspector and markupview tests.
 
 var { Cc, Ci, Cu, Cr } = require("chrome");
 const {getRect, getElementFromPoint, getAdjustedQuads} = require("devtools/shared/layout/utils");
 const promise = require("promise");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 var DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
 var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
             .getService(Ci.mozIJSSubScriptLoader);
 
 // Set up a dummy environment so that EventUtils works. We need to be careful to
 // pass a window object into each EventUtils method we call rather than having
 // it rely on the |window| global.
 let EventUtils = {};
--- a/devtools/client/shared/view-source.js
+++ b/devtools/client/shared/view-source.js
@@ -1,15 +1,15 @@
 /* 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";
 
-loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm");
+var { Task } = require("devtools/shared/task");
 
 var Services = require("Services");
 var {gDevTools} = require("devtools/client/framework/devtools");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 
 /**
  * Tries to open a Stylesheet file in the Style Editor. If the file is not found,
  * it is opened in source view instead.
--- a/devtools/client/shared/widgets/FlameGraph.js
+++ b/devtools/client/shared/widgets/FlameGraph.js
@@ -1,14 +1,14 @@
 /* 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 { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { ViewHelpers, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
 const { LocalizationHelper } = require("devtools/client/shared/l10n");
 
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "EventEmitter",
   "devtools/shared/event-emitter");
 
 loader.lazyRequireGetter(this, "getColor",
--- a/devtools/client/shared/widgets/Graphs.js
+++ b/devtools/client/shared/widgets/Graphs.js
@@ -1,16 +1,16 @@
 /* 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 { Cc, Ci, Cu, Cr } = require("chrome");
 
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 const { Heritage, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
 const { getCurrentZoom } = require("devtools/shared/layout/utils");
 
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "EventEmitter",
   "devtools/shared/event-emitter");
 
 loader.lazyImporter(this, "DevToolsWorker",
--- a/devtools/client/shared/widgets/LineGraphWidget.js
+++ b/devtools/client/shared/widgets/LineGraphWidget.js
@@ -1,13 +1,13 @@
 "use strict";
 
 const { Cc, Ci, Cu, Cr } = require("chrome");
 
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 const { ViewHelpers, Heritage } = require("devtools/client/shared/widgets/view-helpers");
 const { AbstractCanvasGraph, CanvasGraphUtils } = require("devtools/client/shared/widgets/Graphs");
 const { LocalizationHelper } = require("devtools/client/shared/l10n");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const L10N = new LocalizationHelper("chrome://devtools/locale/graphs.properties");
 
 // Line graph constants.
--- a/devtools/client/shared/widgets/Tooltip.js
+++ b/devtools/client/shared/widgets/Tooltip.js
@@ -13,30 +13,29 @@ const {MdnDocsWidget} = require("devtool
 const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
 const {TooltipToggle} = require("devtools/client/shared/widgets/tooltip/TooltipToggle");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {colorUtils} = require("devtools/client/shared/css-color");
 const Heritage = require("sdk/core/heritage");
 const {Eyedropper} = require("devtools/client/eyedropper/eyedropper");
 const Editor = require("devtools/client/sourceeditor/editor");
 const Services = require("Services");
+const {Task} = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "beautify", "devtools/shared/jsbeautify/beautify");
 loader.lazyRequireGetter(this, "setNamedTimeout", "devtools/client/shared/widgets/view-helpers", true);
 loader.lazyRequireGetter(this, "clearNamedTimeout", "devtools/client/shared/widgets/view-helpers", true);
 loader.lazyRequireGetter(this, "setNamedTimeout", "devtools/client/shared/widgets/view-helpers", true);
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
   "resource://devtools/client/shared/widgets/VariablesView.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "VariablesViewController",
   "resource://devtools/client/shared/widgets/VariablesViewController.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
 
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 const SPECTRUM_FRAME = "chrome://devtools/content/shared/widgets/spectrum-frame.xhtml";
 const CUBIC_BEZIER_FRAME =
       "chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
 const MDN_DOCS_FRAME = "chrome://devtools/content/shared/widgets/mdn-docs-frame.xhtml";
 const FILTER_FRAME = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
 const ESCAPE_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE;
--- a/devtools/client/shared/widgets/VariablesView.jsm
+++ b/devtools/client/shared/widgets/VariablesView.jsm
@@ -14,24 +14,24 @@ const LAZY_EXPAND_DELAY = 50; // ms
 const SCROLL_PAGE_SIZE_DEFAULT = 0;
 const PAGE_SIZE_SCROLL_HEIGHT_RATIO = 100;
 const PAGE_SIZE_MAX_JUMPS = 30;
 const SEARCH_ACTION_MAX_DELAY = 300; // ms
 const ITEM_FLASH_DURATION = 300; // ms
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://devtools/shared/event-emitter.js");
-Cu.import("resource://gre/modules/Task.jsm");
 const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const Services = require("Services");
 const { getSourceNames } = require("devtools/client/shared/source-utils");
 const promise = require("promise");
 const { Heritage, ViewHelpers, setNamedTimeout } =
   require("devtools/client/shared/widgets/view-helpers");
+const { Task } = require("devtools/shared/task");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
   "resource://gre/modules/PluralForm.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
   "@mozilla.org/widget/clipboardhelper;1",
   "nsIClipboardHelper");
 
--- a/devtools/client/shared/widgets/tooltip/TooltipToggle.js
+++ b/devtools/client/shared/widgets/tooltip/TooltipToggle.js
@@ -1,17 +1,17 @@
 /* -*- 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 {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 
 const DEFAULT_SHOW_DELAY = 50;
 
 /**
  * Tooltip helper designed to show/hide the tooltip when the mouse hovers over
  * particular nodes.
  *
  * This works by tracking mouse movements on a base container node (baseNode)
--- a/devtools/client/storage/ui.js
+++ b/devtools/client/storage/ui.js
@@ -1,16 +1,16 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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 {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {LocalizationHelper} = require("devtools/client/shared/l10n");
 
 loader.lazyRequireGetter(this, "TreeWidget",
                          "devtools/client/shared/widgets/TreeWidget", true);
 loader.lazyRequireGetter(this, "TableWidget",
                          "devtools/client/shared/widgets/TableWidget", true);
 loader.lazyRequireGetter(this, "ViewHelpers",
--- a/devtools/client/styleeditor/StyleEditorUI.jsm
+++ b/devtools/client/styleeditor/StyleEditorUI.jsm
@@ -9,17 +9,17 @@ this.EXPORTED_SYMBOLS = ["StyleEditorUI"
 
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const {require, loader} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const Services = require("Services");
 const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {gDevTools} = require("devtools/client/framework/devtools");
 /* import-globals-from StyleEditorUtil.jsm */
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUtil.jsm");
 const {SplitView} = Cu.import("resource://devtools/client/shared/SplitView.jsm", {});
 const {StyleSheetEditor} = Cu.import("resource://devtools/client/styleeditor/StyleSheetEditor.jsm");
 loader.lazyImporter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
 const {PrefObserver, PREF_ORIG_SOURCES} =
--- a/devtools/client/styleeditor/StyleSheetEditor.jsm
+++ b/devtools/client/styleeditor/StyleSheetEditor.jsm
@@ -13,21 +13,21 @@ const Cu = Components.utils;
 
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const Editor = require("devtools/client/sourceeditor/editor");
 const promise = require("promise");
 const {CssLogic} = require("devtools/shared/inspector/css-logic");
 const {console} = require("resource://gre/modules/Console.jsm");
 const Services = require("Services");
 const EventEmitter = require("devtools/shared/event-emitter");
+const {Task} = require("devtools/shared/task");
 
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 const { TextDecoder, OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
-Cu.import("resource://gre/modules/Task.jsm");
 /* import-globals-from StyleEditorUtil.jsm */
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUtil.jsm");
 
 const LOAD_ERROR = "error-load";
 const SAVE_ERROR = "error-save";
 
 // max update frequency in ms (avoid potential typing lag and/or flicker)
 // @see StyleEditor.updateStylesheet
--- a/devtools/client/styleeditor/styleeditor-panel.js
+++ b/devtools/client/styleeditor/styleeditor-panel.js
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {Cu} = require("chrome");
 
 var Services = require("Services");
 var promise = require("promise");
-var {Task} = require("resource://gre/modules/Task.jsm");
+var {Task} = require("devtools/shared/task");
 var {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
 var EventEmitter = require("devtools/shared/event-emitter");
 
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUI.jsm");
 /* import-globals-from StyleEditorUtil.jsm */
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUtil.jsm");
 
 loader.lazyGetter(this, "StyleSheetsFront",
--- a/devtools/client/webaudioeditor/includes.js
+++ b/devtools/client/webaudioeditor/includes.js
@@ -6,17 +6,17 @@
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const { loader, require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 
 var { EventTarget } = require("sdk/event/target");
 
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 const { Class } = require("sdk/core/heritage");
 const EventEmitter = require("devtools/shared/event-emitter");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const Services = require("Services");
 const { gDevTools } = require("devtools/client/framework/devtools");
 const { LocalizationHelper } = require("devtools/client/shared/l10n");
 const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
 
--- a/devtools/client/webaudioeditor/test/browser_wa_destroy-node-01.js
+++ b/devtools/client/webaudioeditor/test/browser_wa_destroy-node-01.js
@@ -33,16 +33,19 @@ add_task(function* () {
 
   // Flatten arrays of event arguments and take the first (AudioNodeModel)
   // and get its ID.
   let actorIDs = created.map(ev => ev[0].id);
 
   // Click a soon-to-be dead buffer node
   yield clickGraphNode(panelWin, actorIDs[5]);
 
+  // Wait for a tick before gc to prevent this test from intermittent timeout
+  // where the node never get collected.
+  yield DevToolsUtils.waitForTick();
   forceCC();
 
   // Wait for destruction and graph to re-render
   yield Promise.all([destroyed, waitForGraphRendered(panelWin, 3, 2)]);
 
   // Test internal storage
   is(panelWin.gAudioNodes.length, 3, "All nodes should be GC'd except one gain, osc and dest node.");
 
--- a/devtools/client/webaudioeditor/test/browser_webaudio-actor-destroy-node.js
+++ b/devtools/client/webaudioeditor/test/browser_webaudio-actor-destroy-node.js
@@ -11,16 +11,20 @@ add_task(function* () {
   let waitUntilDestroyed = getN(front, "destroy-node", 10);
   let [, , created] = yield Promise.all([
     front.setup({ reload: true }),
     once(front, "start-context"),
     // Should create 1 destination node and 10 disposable buffer nodes
     getN(front, "create-node", 13)
   ]);
 
+  // Wait for a tick before gc to prevent this test from intermittent timeout
+  // where the node never get collected.
+  yield DevToolsUtils.waitForTick();
+
   // Force CC so we can ensure it's run to clear out dead AudioNodes
   forceCC();
 
   let destroyed = yield waitUntilDestroyed;
 
   destroyed.forEach((node, i) => {
     ok(node.type, "AudioBufferSourceNode", "Only buffer nodes are destroyed");
     ok(actorIsInList(created, destroyed[i]),
--- a/devtools/client/webaudioeditor/test/head.js
+++ b/devtools/client/webaudioeditor/test/head.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
-var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
+var { Task } = require("devtools/shared/task");
 var Services = require("Services");
 var { gDevTools } = require("devtools/client/framework/devtools");
 var { TargetFactory } = require("devtools/client/framework/target");
 var { DebuggerServer } = require("devtools/server/main");
 var { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
 
 var Promise = require("promise");
 var Services = require("Services");
--- a/devtools/client/webconsole/console-output.js
+++ b/devtools/client/webconsole/console-output.js
@@ -7,32 +7,32 @@
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 
 const Services = require("Services");
 
 loader.lazyImporter(this, "VariablesView", "resource://devtools/client/shared/widgets/VariablesView.jsm");
 loader.lazyImporter(this, "escapeHTML", "resource://devtools/client/shared/widgets/VariablesView.jsm");
-loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm");
 loader.lazyImporter(this, "PluralForm", "resource://gre/modules/PluralForm.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 Heritage = require("sdk/core/heritage");
+const { extend } = require("sdk/core/heritage");
 const URI = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const STRINGS_URI = "chrome://devtools/locale/webconsole.properties";
 
 const WebConsoleUtils = require("devtools/shared/webconsole/utils").Utils;
 const { getSourceNames } = require("devtools/client/shared/source-utils");
+const {Task} = require("devtools/shared/task");
 const l10n = new WebConsoleUtils.L10n(STRINGS_URI);
 
 const MAX_STRING_GRIP_LENGTH = 36;
 const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
 
 // Constants for compatibility with the Web Console output implementation before
 // bug 778766.
 // TODO: remove these once bug 778766 is fixed.
@@ -57,27 +57,33 @@ const COMPAT = {
     LOG: 3,
   },
 
   // The preference keys to use for each category/severity combination, indexed
   // first by category (rows) and then by severity (columns).
   //
   // Most of these rather idiosyncratic names are historical and predate the
   // division of message type into "category" and "severity".
+  /* eslint-disable no-multi-spaces */
+  /* eslint-disable max-len */
+  /* eslint-disable no-inline-comments */
   PREFERENCE_KEYS: [
-    // Error        Warning       Info    Log
-    [ "network", "netwarn", null, "networkinfo", ],  // Network
-    [ "csserror", "cssparser", null, null, ],  // CSS
-    [ "exception", "jswarn", null, "jslog", ],  // JS
-    [ "error", "warn", "info", "log", ],  // Web Developer
-    [ null, null, null, null, ],  // Input
-    [ null, null, null, null, ],  // Output
-    [ "secerror", "secwarn", null, null, ],  // Security
-    [ "servererror", "serverwarn", "serverinfo", "serverlog", ],  // Server Logging
+    // Error         Warning       Info          Log
+    [ "network",     "netwarn",    null,         "networkinfo", ],  // Network
+    [ "csserror",    "cssparser",  null,         null,          ],  // CSS
+    [ "exception",   "jswarn",     null,         "jslog",       ],  // JS
+    [ "error",       "warn",       "info",       "log",         ],  // Web Developer
+    [ null,          null,         null,         null,          ],  // Input
+    [ null,          null,         null,         null,          ],  // Output
+    [ "secerror",    "secwarn",    null,         null,          ],  // Security
+    [ "servererror", "serverwarn", "serverinfo", "serverlog",   ],  // Server Logging
   ],
+  /* eslint-enable no-inline-comments */
+  /* eslint-enable max-len */
+  /* eslint-enable no-multi-spaces */
 
   // The fragment of a CSS class name that identifies each category.
   CATEGORY_CLASS_FRAGMENTS: [ "network", "cssparser", "exception", "console",
                               "input", "output", "security", "server" ],
 
   // The fragment of a CSS class name that identifies each severity.
   SEVERITY_CLASS_FRAGMENTS: [ "error", "warn", "info", "log" ],
 
@@ -567,100 +573,95 @@ Messages.BaseMessage.prototype = {
   destroy: function ()
   {
     // Destroy all widgets that have registered themselves in this.widgets
     for (let widget of this.widgets) {
       widget.destroy();
     }
     this.widgets.clear();
   }
-}; // Messages.BaseMessage.prototype
-
+};
 
 /**
  * The NavigationMarker is used to show a page load event.
  *
  * @constructor
  * @extends Messages.BaseMessage
  * @param object response
  *        The response received from the back end.
  * @param number timestamp
  *        The message date and time, milliseconds elapsed since 1 January 1970
  *        00:00:00 UTC.
  */
-Messages.NavigationMarker = function (response, timestamp)
-{
+Messages.NavigationMarker = function (response, timestamp) {
   Messages.BaseMessage.call(this);
 
   // Store the response packet received from the server. It might
   // be useful for extensions customizing the console output.
   this.response = response;
   this._url = response.url;
   this.textContent = "------ " + this._url;
   this.timestamp = timestamp;
 };
 
-Messages.NavigationMarker.prototype = Heritage.extend(Messages.BaseMessage.prototype,
-  {
+Messages.NavigationMarker.prototype = extend(Messages.BaseMessage.prototype, {
   /**
    * The address of the loading page.
    * @private
    * @type string
    */
-    _url: null,
+  _url: null,
 
   /**
    * Message timestamp.
    *
    * @type number
    *       Milliseconds elapsed since 1 January 1970 00:00:00 UTC.
    */
-    timestamp: 0,
-
-    _categoryCompat: COMPAT.CATEGORIES.NETWORK,
-    _severityCompat: COMPAT.SEVERITIES.LOG,
-    _categoryNameCompat: "network",
-    _severityNameCompat: "info",
-    _filterKeyCompat: "networkinfo",
+  timestamp: 0,
+
+  _categoryCompat: COMPAT.CATEGORIES.NETWORK,
+  _severityCompat: COMPAT.SEVERITIES.LOG,
+  _categoryNameCompat: "network",
+  _severityNameCompat: "info",
+  _filterKeyCompat: "networkinfo",
 
   /**
    * Prepare the DOM element for this message.
    * @return this
    */
-    render: function ()
-  {
-      if (this.element) {
-        return this;
-      }
-
-      let url = this._url;
-      let pos = url.indexOf("?");
-      if (pos > -1) {
-        url = url.substr(0, pos);
-      }
-
-      let doc = this.output.document;
-      let urlnode = doc.createElementNS(XHTML_NS, "a");
-      urlnode.className = "url";
-      urlnode.textContent = url;
-      urlnode.title = this._url;
-      urlnode.href = this._url;
-      urlnode.draggable = false;
-      this._addLinkCallback(urlnode);
-
-      let render = Messages.BaseMessage.prototype.render.bind(this);
-      render().element.appendChild(urlnode);
-      this.element.classList.add("navigation-marker");
-      this.element.url = this._url;
-      this.element.appendChild(doc.createTextNode("\n"));
-
+  render: function () {
+    if (this.element) {
       return this;
-    },
-  }); // Messages.NavigationMarker.prototype
-
+    }
+
+    let url = this._url;
+    let pos = url.indexOf("?");
+    if (pos > -1) {
+      url = url.substr(0, pos);
+    }
+
+    let doc = this.output.document;
+    let urlnode = doc.createElementNS(XHTML_NS, "a");
+    urlnode.className = "url";
+    urlnode.textContent = url;
+    urlnode.title = this._url;
+    urlnode.href = this._url;
+    urlnode.draggable = false;
+    this._addLinkCallback(urlnode);
+
+    let render = Messages.BaseMessage.prototype.render.bind(this);
+    render().element.appendChild(urlnode);
+    this.element.classList.add("navigation-marker");
+    this.element.url = this._url;
+    this.element.appendChild(doc.createTextNode("\n"));
+
+    return this;
+  },
+});
 
 /**
  * The Simple message is used to show any basic message in the Web Console.
  *
  * @constructor
  * @extends Messages.BaseMessage
  * @param string|Node|function message
  *        The message to display.
@@ -680,18 +681,17 @@ Messages.NavigationMarker.prototype = He
  *        and lineText.
  *        - stack: array that tells the message source stack.
  *        - className: (string) additional element class names for styling
  *        purposes.
  *        - private: (boolean) mark this as a private message.
  *        - filterDuplicates: (boolean) true if you do want this message to be
  *        filtered as a potential duplicate message, false otherwise.
  */
-Messages.Simple = function (message, options = {})
-{
+Messages.Simple = function (message, options = {}) {
   Messages.BaseMessage.call(this);
 
   this.category = options.category;
   this.severity = options.severity;
   this.location = options.location;
   this.stack = options.stack;
   this.timestamp = options.timestamp || Date.now();
   this.prefix = options.prefix;
@@ -701,374 +701,373 @@ Messages.Simple = function (message, opt
   this._className = options.className;
   this._link = options.link;
   this._linkCallback = options.linkCallback;
   this._filterDuplicates = options.filterDuplicates;
 
   this._onClickCollapsible = this._onClickCollapsible.bind(this);
 };
 
-Messages.Simple.prototype = Heritage.extend(Messages.BaseMessage.prototype,
-  {
+Messages.Simple.prototype = extend(Messages.BaseMessage.prototype, {
   /**
    * Message category.
    * @type string
    */
-    category: null,
+  category: null,
 
   /**
    * Message severity.
    * @type string
    */
-    severity: null,
+  severity: null,
 
   /**
    * Message source location. Properties: url, line, column, lineText.
    * @type object
    */
-    location: null,
+  location: null,
 
   /**
    * Holds the stackframes received from the server.
    *
    * @private
    * @type array
    */
-    stack: null,
+  stack: null,
 
   /**
    * Message prefix
    * @type string|null
    */
-    prefix: null,
+  prefix: null,
 
   /**
    * Tells if this message comes from a private browsing context.
    * @type boolean
    */
-    private: false,
+  private: false,
 
   /**
    * Custom class name for the DOM element of the message.
    * @private
    * @type string
    */
-    _className: null,
+  _className: null,
 
   /**
    * Message link - if this message is clicked then this URL opens in a new tab.
    * @private
    * @type string
    */
-    _link: null,
+  _link: null,
 
   /**
    * Message click event handler.
    * @private
    * @type function
    */
-    _linkCallback: null,
+  _linkCallback: null,
 
   /**
    * Tells if this message should be checked if it is a duplicate of another
    * message or not.
    */
-    _filterDuplicates: false,
+  _filterDuplicates: false,
 
   /**
    * The raw message displayed by this Message object. This can be a function,
    * DOM node or a string.
    *
    * @private
    * @type mixed
    */
-    _message: null,
-
-    _objectActors: null,
-    _groupDepthCompat: 0,
+  _message: null,
+
+  _objectActors: null,
+  _groupDepthCompat: 0,
 
   /**
    * Message timestamp.
    *
    * @type number
    *       Milliseconds elapsed since 1 January 1970 00:00:00 UTC.
    */
-    timestamp: 0,
-
-    get _categoryCompat() {
-      return this.category ?
+  timestamp: 0,
+
+  get _categoryCompat() {
+    return this.category ?
            COMPAT.CATEGORIES[this.category.toUpperCase()] : null;
-    },
-    get _severityCompat() {
-      return this.severity ?
+  },
+  get _severityCompat() {
+    return this.severity ?
            COMPAT.SEVERITIES[this.severity.toUpperCase()] : null;
-    },
-    get _categoryNameCompat() {
-      return this.category ?
+  },
+  get _categoryNameCompat() {
+    return this.category ?
            COMPAT.CATEGORY_CLASS_FRAGMENTS[this._categoryCompat] : null;
-    },
-    get _severityNameCompat() {
-      return this.severity ?
+  },
+  get _severityNameCompat() {
+    return this.severity ?
            COMPAT.SEVERITY_CLASS_FRAGMENTS[this._severityCompat] : null;
-    },
-
-    get _filterKeyCompat() {
-      return this._categoryCompat !== null && this._severityCompat !== null ?
+  },
+
+  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;
-    },
+    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.
    * @type boolean
    */
-    collapsible: false,
+  collapsible: false,
 
   /**
    * 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 ()
+  get collapsed() {
+    return this.collapsible && this.element && !this.element.hasAttribute("open");
+  },
+
+  _initRepeatID: function ()
   {
-      if (!this._filterDuplicates) {
-        return;
-      }
+    if (!this._filterDuplicates) {
+      return;
+    }
 
     // Add the properties we care about for identifying duplicate messages.
-      let rid = this._repeatID;
-      delete rid.uid;
-
-      rid.category = this.category;
-      rid.severity = this.severity;
-      rid.prefix = this.prefix;
-      rid.private = this.private;
-      rid.location = this.location;
-      rid.link = this._link;
-      rid.linkCallback = this._linkCallback + "";
-      rid.className = this._className;
-      rid.groupDepth = this._groupDepthCompat;
-      rid.textContent = "";
-    },
-
-    getRepeatID: function ()
+    let rid = this._repeatID;
+    delete rid.uid;
+
+    rid.category = this.category;
+    rid.severity = this.severity;
+    rid.prefix = this.prefix;
+    rid.private = this.private;
+    rid.location = this.location;
+    rid.link = this._link;
+    rid.linkCallback = this._linkCallback + "";
+    rid.className = this._className;
+    rid.groupDepth = this._groupDepthCompat;
+    rid.textContent = "";
+  },
+
+  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 ()
+    if (this._repeatID.uid) {
+      return JSON.stringify({ uid: this._repeatID.uid });
+    }
+
+    return JSON.stringify(this._repeatID);
+  },
+
+  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";
-      icon.title = l10n.getStr("severity." + this._severityNameCompat);
-      if (this.stack) {
-        icon.addEventListener("click", this._onClickCollapsible);
-      }
-
-      let prefixNode;
-      if (this.prefix) {
-        prefixNode = this.document.createElementNS(XHTML_NS, "span");
-        prefixNode.className = "prefix devtools-monospace";
-        prefixNode.textContent = this.prefix + ":";
-      }
+    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";
+    icon.title = l10n.getStr("severity." + this._severityNameCompat);
+    if (this.stack) {
+      icon.addEventListener("click", this._onClickCollapsible);
+    }
+
+    let prefixNode;
+    if (this.prefix) {
+      prefixNode = this.document.createElementNS(XHTML_NS, "span");
+      prefixNode.className = "prefix devtools-monospace";
+      prefixNode.textContent = this.prefix + ":";
+    }
 
     // Apply the current group by indenting appropriately.
     // TODO: remove this once bug 778766 is fixed.
-      let indent = this._groupDepthCompat * COMPAT.GROUP_INDENT;
-      let indentNode = this.document.createElementNS(XHTML_NS, "span");
-      indentNode.className = "indent";
-      indentNode.style.width = indent + "px";
-
-      let body = this._renderBody();
-      this._repeatID.textContent += "|" + body.textContent;
-
-      let repeatNode = this._renderRepeatNode();
-      let location = this._renderLocation();
-
-      Messages.BaseMessage.prototype.render.call(this);
-      if (this._className) {
-        this.element.className += " " + this._className;
-      }
-
-      this.element.appendChild(timestamp.element);
-      this.element.appendChild(indentNode);
-      this.element.appendChild(icon);
-      if (prefixNode) {
-        this.element.appendChild(prefixNode);
-      }
-
-      if (this.stack) {
-        let twisty = this.document.createElementNS(XHTML_NS, "a");
-        twisty.className = "theme-twisty";
-        twisty.href = "#";
-        twisty.title = l10n.getStr("messageToggleDetails");
-        twisty.addEventListener("click", this._onClickCollapsible);
-        this.element.appendChild(twisty);
-        this.collapsible = true;
-        this.element.setAttribute("collapsible", true);
-      }
-
-      this.element.appendChild(body);
-      if (repeatNode) {
-        this.element.appendChild(repeatNode);
-      }
-      if (location) {
-        this.element.appendChild(location);
-      }
-
-      this.element.appendChild(this.document.createTextNode("\n"));
-
-      this.element.clipboardText = this.element.textContent;
-
-      if (this.private) {
-        this.element.setAttribute("private", true);
-      }
+    let indent = this._groupDepthCompat * COMPAT.GROUP_INDENT;
+    let indentNode = this.document.createElementNS(XHTML_NS, "span");
+    indentNode.className = "indent";
+    indentNode.style.width = indent + "px";
+
+    let body = this._renderBody();
+    this._repeatID.textContent += "|" + body.textContent;
+
+    let repeatNode = this._renderRepeatNode();
+    let location = this._renderLocation();
+
+    Messages.BaseMessage.prototype.render.call(this);
+    if (this._className) {
+      this.element.className += " " + this._className;
+    }
+
+    this.element.appendChild(timestamp.element);
+    this.element.appendChild(indentNode);
+    this.element.appendChild(icon);
+    if (prefixNode) {
+      this.element.appendChild(prefixNode);
+    }
+
+    if (this.stack) {
+      let twisty = this.document.createElementNS(XHTML_NS, "a");
+      twisty.className = "theme-twisty";
+      twisty.href = "#";
+      twisty.title = l10n.getStr("messageToggleDetails");
+      twisty.addEventListener("click", this._onClickCollapsible);
+      this.element.appendChild(twisty);
+      this.collapsible = true;
+      this.element.setAttribute("collapsible", true);
+    }
+
+    this.element.appendChild(body);
+    if (repeatNode) {
+      this.element.appendChild(repeatNode);
+    }
+    if (location) {
+      this.element.appendChild(location);
+    }
+
+    this.element.appendChild(this.document.createTextNode("\n"));
+
+    this.element.clipboardText = this.element.textContent;
+
+    if (this.private) {
+      this.element.setAttribute("private", true);
+    }
 
     // TODO: handle object releasing in a more elegant way once all console
     // messages use the new API - bug 778766.
-      this.element._objectActors = this._objectActors;
-      this._objectActors = null;
-
-      return this;
-    },
+    this.element._objectActors = this._objectActors;
+    this._objectActors = null;
+
+    return this;
+  },
 
   /**
    * Render the message body DOM element.
    * @private
    * @return Element
    */
-    _renderBody: function ()
+  _renderBody: function ()
   {
-      let body = this.document.createElementNS(XHTML_NS, "span");
-      body.className = "message-body-wrapper message-body devtools-monospace";
-
-      let bodyInner = this.document.createElementNS(XHTML_NS, "span");
-      body.appendChild(bodyInner);
-
-      let anchor, container = bodyInner;
-      if (this._link || this._linkCallback) {
-        container = anchor = this.document.createElementNS(XHTML_NS, "a");
-        anchor.href = this._link || "#";
-        anchor.draggable = false;
-        this._addLinkCallback(anchor, this._linkCallback);
-        bodyInner.appendChild(anchor);
-      }
-
-      if (typeof this._message == "function") {
-        container.appendChild(this._message(this));
-      } else if (this._message instanceof Ci.nsIDOMNode) {
-        container.appendChild(this._message);
-      } else {
-        container.textContent = this._message;
-      }
-
-      if (this.stack) {
-        let stack = new Widgets.Stacktrace(this, this.stack).render().element;
-        body.appendChild(this.document.createTextNode("\n"));
-        body.appendChild(stack);
-      }
-
-      return body;
-    },
+    let body = this.document.createElementNS(XHTML_NS, "span");
+    body.className = "message-body-wrapper message-body devtools-monospace";
+
+    let bodyInner = this.document.createElementNS(XHTML_NS, "span");
+    body.appendChild(bodyInner);
+
+    let anchor, container = bodyInner;
+    if (this._link || this._linkCallback) {
+      container = anchor = this.document.createElementNS(XHTML_NS, "a");
+      anchor.href = this._link || "#";
+      anchor.draggable = false;
+      this._addLinkCallback(anchor, this._linkCallback);
+      bodyInner.appendChild(anchor);
+    }
+
+    if (typeof this._message == "function") {
+      container.appendChild(this._message(this));
+    } else if (this._message instanceof Ci.nsIDOMNode) {
+      container.appendChild(this._message);
+    } else {
+      container.textContent = this._message;
+    }
+
+    if (this.stack) {
+      let stack = new Widgets.Stacktrace(this, this.stack).render().element;
+      body.appendChild(this.document.createTextNode("\n"));
+      body.appendChild(stack);
+    }
+
+    return body;
+  },
 
   /**
    * 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;
-      repeatNode._uid = this.getRepeatID();
-      return repeatNode;
-    },
+    if (!this._filterDuplicates) {
+      return null;
+    }
+
+    let repeatNode = this.document.createElementNS(XHTML_NS, "span");
+    repeatNode.setAttribute("value", "1");
+    repeatNode.className = "message-repeats";
+    repeatNode.textContent = 1;
+    repeatNode._uid = this.getRepeatID();
+    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;
-      }
+    if (!this.location) {
+      return null;
+    }
+
+    let {url, line, column} = this.location;
+    if (IGNORED_SOURCE_URLS.indexOf(url) != -1) {
+      return null;
+    }
 
     // The ConsoleOutput owner is a WebConsoleFrame instance from webconsole.js.
     // TODO: move createLocationNode() into this file when bug 778766 is fixed.
-      return this.output.owner.createLocationNode({url: url,
+    return this.output.owner.createLocationNode({url: url,
                                                  line: line,
                                                  column: column});
-    },
+  },
 
   /**
    * 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();
-    },
+    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
+    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
@@ -1090,93 +1089,92 @@ Messages.Extended = function (messagePie
     this._quoteStrings = options.quoteStrings;
   }
 
   this._repeatID.quoteStrings = this._quoteStrings;
   this._repeatID.messagePieces = JSON.stringify(messagePieces);
   this._repeatID.actors = new Set(); // using a set to avoid duplicates
 };
 
-Messages.Extended.prototype = Heritage.extend(Messages.Simple.prototype,
-  {
+Messages.Extended.prototype = extend(Messages.Simple.prototype, {
   /**
    * The message pieces displayed by this message instance.
    * @private
    * @type array
    */
-    _messagePieces: null,
+  _messagePieces: null,
 
   /**
    * Boolean that tells if the strings displayed in this message are wrapped.
    * @private
    * @type boolean
    */
-    _quoteStrings: true,
-
-    getRepeatID: function ()
+  _quoteStrings: true,
+
+  getRepeatID: function ()
   {
-      if (this._repeatID.uid) {
-        return JSON.stringify({ uid: this._repeatID.uid });
-      }
+    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 ()
+    let actors = this._repeatID.actors;
+    this._repeatID.actors = [...actors];
+    let result = JSON.stringify(this._repeatID);
+    this._repeatID.actors = actors;
+    return result;
+  },
+
+  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);
-        }
-
-        let piece = this._messagePieces[i];
-        result.appendChild(this._renderBodyPiece(piece));
+    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);
       }
 
-      this._message = result;
-      this._messagePieces = null;
-      return Messages.Simple.prototype.render.call(this);
-    },
+      let piece = this._messagePieces[i];
+      result.appendChild(this._renderBodyPiece(piece));
+    }
+
+    this._message = result;
+    this._messagePieces = null;
+    return Messages.Simple.prototype.render.call(this);
+  },
 
   /**
    * 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);
-    },
+    if (piece instanceof Ci.nsIDOMNode) {
+      return piece;
+    }
+    if (typeof piece == "function") {
+      return piece(this);
+    }
+
+    return this._renderValueGrip(piece, options);
+  },
 
   /**
    * Render a grip that represents a value received from the server. This method
    * picks the appropriate widget to render the value with.
    *
    * @private
    * @param object grip
    *        The value grip received from the server.
@@ -1188,153 +1186,153 @@ Messages.Extended.prototype = Heritage.e
    *        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;
+    let isPrimitive = VariablesView.isPrimitive({ value: grip });
+    let isActorGrip = WebConsoleUtils.isActorGrip(grip);
+    let noStringQuotes = !this._quoteStrings;
+    if ("noStringQuotes" in options) {
+      noStringQuotes = options.noStringQuotes;
+    }
+
+    if (isActorGrip) {
+      this._repeatID.actors.add(grip.actor);
+
+      if (!isPrimitive) {
+        return this._renderObjectActor(grip, options);
       }
-
-      if (isActorGrip) {
-        this._repeatID.actors.add(grip.actor);
-
-        if (!isPrimitive) {
-          return this._renderObjectActor(grip, options);
-        }
-        if (grip.type == "longString") {
-          let widget = new Widgets.LongString(this, grip, options).render();
-          return widget.element;
-        }
+      if (grip.type == "longString") {
+        let widget = new Widgets.LongString(this, grip, options).render();
+        return widget.element;
       }
-
-      let unshortenedGrip = grip;
-      if (options.shorten) {
-        grip = this.shortenValueGrip(grip);
+    }
+
+    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)) {
+        let widget = new Widgets.URLString(this, grip, unshortenedGrip).render();
+        return widget.element;
       }
 
-      let result = this.document.createElementNS(XHTML_NS, "span");
-      if (isPrimitive) {
-        if (Widgets.URLString.prototype.containsURL.call(Widgets.URLString.prototype, grip)) {
-          let widget = new Widgets.URLString(this, grip, unshortenedGrip).render();
-          return widget.element;
-        }
-
-        let className = this.getClassNameForValueGrip(grip);
-        if (className) {
-          result.className = className;
-        }
-
-        result.textContent = VariablesView.getString(grip, {
-          noStringQuotes: noStringQuotes,
-          concise: options.concise,
-        });
-      } else {
-        result.textContent = grip;
+      let className = this.getClassNameForValueGrip(grip);
+      if (className) {
+        result.className = className;
       }
 
-      return result;
-    },
+      result.textContent = VariablesView.getString(grip, {
+        noStringQuotes: noStringQuotes,
+        concise: options.concise,
+      });
+    } else {
+      result.textContent = grip;
+    }
+
+    return result;
+  },
 
   /**
    * Shorten grips of the type string, leaves other grips unmodified.
    *
    * @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;
-        }
+    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;
       }
-
-      return shortVal;
-    },
+    }
+
+    return shortVal;
+  },
 
   /**
    * 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",
-        "null": "cm-atom",
-        "undefined": "cm-comment",
-        "symbol": "cm-atom"
-      };
-
-      let className = map[typeof grip];
-      if (!className && grip && grip.type) {
-        className = map[grip.type.toLowerCase()];
-      }
-      if (!className && grip && grip.class) {
-        className = map[grip.class.toLowerCase()];
-      }
-
-      return className;
-    },
+    let map = {
+      "number": "cm-number",
+      "longstring": "console-string",
+      "string": "console-string",
+      "regexp": "cm-string-2",
+      "boolean": "cm-atom",
+      "-infinity": "cm-atom",
+      "infinity": "cm-atom",
+      "null": "cm-atom",
+      "undefined": "cm-comment",
+      "symbol": "cm-atom"
+    };
+
+    let className = map[typeof grip];
+    if (!className && grip && grip.type) {
+      className = map[grip.type.toLowerCase()];
+    }
+    if (!className && grip && grip.class) {
+      className = map[grip.class.toLowerCase()];
+    }
+
+    return className;
+  },
 
   /**
    * Display an object actor with the appropriate renderer.
    *
    * @private
    * @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 = {})
+  _renderObjectActor: function (objectActor, options = {})
   {
-      let widget = Widgets.ObjectRenderers.byClass[objectActor.class];
-
-      let { preview } = objectActor;
-      if ((!widget || (widget.canRender && !widget.canRender(objectActor)))
+    let widget = Widgets.ObjectRenderers.byClass[objectActor.class];
+
+    let { preview } = objectActor;
+    if ((!widget || (widget.canRender && !widget.canRender(objectActor)))
         && preview
         && preview.kind) {
-        widget = Widgets.ObjectRenderers.byKind[preview.kind];
-      }
-
-      if (!widget || (widget.canRender && !widget.canRender(objectActor))) {
-        widget = Widgets.JSObject;
-      }
-
-      let instance = new widget(this, objectActor, options).render();
-      return instance.element;
-    },
-  }); // Messages.Extended.prototype
+      widget = Widgets.ObjectRenderers.byKind[preview.kind];
+    }
+
+    if (!widget || (widget.canRender && !widget.canRender(objectActor))) {
+      widget = Widgets.JSObject;
+    }
+
+    let instance = new widget(this, objectActor, options).render();
+    return instance.element;
+  },
+}); // Messages.Extended.prototype
 
 
 
 /**
  * The JavaScriptEvalOutput message.
  *
  * @constructor
  * @extends Messages.Extended
@@ -1419,165 +1417,164 @@ Messages.ConsoleGeneric = function (pack
   }
 
   this._repeatID.consoleApiLevel = packet.level;
   this._repeatID.styles = packet.styles;
   this.stack = this._repeatID.stacktrace = packet.stacktrace;
   this._styles = packet.styles || [];
 };
 
-Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
+Messages.ConsoleGeneric.prototype = extend(Messages.Extended.prototype, {
+  _styles: null,
+
+  _renderBodyPieceSeparator: function ()
   {
-    _styles: null,
-
-    _renderBodyPieceSeparator: function ()
-  {
-      return this.document.createTextNode(" ");
-    },
-
-    render: function ()
+    return this.document.createTextNode(" ");
+  },
+
+  render: function ()
   {
-      let msg = this.document.createElementNS(XHTML_NS, "span");
-      msg.className = "message-body devtools-monospace";
-
-      this._renderBodyPieces(msg);
-
-      let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
-      let location = Messages.Simple.prototype._renderLocation.call(this);
-      if (location) {
-        location.target = "jsdebugger";
-      }
-
-      let flex = this.document.createElementNS(XHTML_NS, "span");
-      flex.className = "message-flex-body";
-
-      flex.appendChild(msg);
-
-      if (repeatNode) {
-        flex.appendChild(repeatNode);
-      }
-      if (location) {
-        flex.appendChild(location);
-      }
-
-      let result = this.document.createDocumentFragment();
-      result.appendChild(flex);
-
-      this._message = result;
-      this._stacktrace = null;
-
-      Messages.Simple.prototype.render.call(this);
-
-      return this;
-    },
-
-    _renderBody: function ()
+    let msg = this.document.createElementNS(XHTML_NS, "span");
+    msg.className = "message-body devtools-monospace";
+
+    this._renderBodyPieces(msg);
+
+    let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
+    let location = Messages.Simple.prototype._renderLocation.call(this);
+    if (location) {
+      location.target = "jsdebugger";
+    }
+
+    let flex = this.document.createElementNS(XHTML_NS, "span");
+    flex.className = "message-flex-body";
+
+    flex.appendChild(msg);
+
+    if (repeatNode) {
+      flex.appendChild(repeatNode);
+    }
+    if (location) {
+      flex.appendChild(location);
+    }
+
+    let result = this.document.createDocumentFragment();
+    result.appendChild(flex);
+
+    this._message = result;
+    this._stacktrace = null;
+
+    Messages.Simple.prototype.render.call(this);
+
+    return this;
+  },
+
+  _renderBody: function ()
   {
-      let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
-      body.classList.remove("devtools-monospace", "message-body");
-      return body;
-    },
-
-    _renderBodyPieces: function (container)
+    let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
+    body.classList.remove("devtools-monospace", "message-body");
+    return body;
+  },
+
+  _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++) {
+    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());
-        }
-
-        let piece = this._messagePieces[i];
-        let style = this._styles[i];
+      if (i >= stylePieces) {
+        container.appendChild(this._renderBodyPieceSeparator());
+      }
+
+      let piece = this._messagePieces[i];
+      let style = this._styles[i];
 
       // No long string support.
-        lastStyle = (style && typeof style == "string") ?
+      lastStyle = (style && typeof style == "string") ?
                   this.cleanupStyle(style) : null;
 
-        container.appendChild(this._renderBodyPiece(piece, lastStyle));
-      }
-
-      this._messagePieces = null;
-      this._styles = null;
-    },
-
-    _renderBodyPiece: function (piece, style)
+      container.appendChild(this._renderBodyPiece(piece, lastStyle));
+    }
+
+    this._messagePieces = null;
+    this._styles = null;
+  },
+
+  _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 == Ci.nsIDOMNode.ELEMENT_NODE) {
-          elem.style = style;
-        } else {
-          let span = this.document.createElementNS(XHTML_NS, "span");
-          span.style = style;
-          span.appendChild(elem);
-          result = span;
-        }
+    let options = { noStringQuotes: true };
+    let elem = Messages.Extended.prototype._renderBodyPiece.call(this, piece, options);
+    let result = elem;
+
+    if (style) {
+      if (elem.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
+        elem.style = style;
+      } else {
+        let span = this.document.createElementNS(XHTML_NS, "span");
+        span.style = style;
+        span.appendChild(elem);
+        result = span;
       }
-
-      return result;
-    },
+    }
+
+    return result;
+  },
 
   // no-op for the message location and .repeats elements.
   // |this.render()| handles customized message output.
-    _renderLocation: function () { },
-    _renderRepeatNode: function () { },
+  _renderLocation: function () { },
+  _renderRepeatNode: function () { },
 
   /**
    * Given a style attribute value, return a cleaned up version of the string
    * such that:
    *
    * - no external URL is allowed to load. See RE_CLEANUP_STYLES.
    * - 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 =
+    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");
+    }
+    dummy.style = style;
+
+    let toRemove = [];
+    for (let i = 0; i < dummy.style.length; i++) {
+      let prop = dummy.style[i];
+      if (!RE_ALLOWED_STYLES.test(prop)) {
+        toRemove.push(prop);
       }
-      dummy.style = style;
-
-      let toRemove = [];
-      for (let i = 0; i < dummy.style.length; i++) {
-        let prop = dummy.style[i];
-        if (!RE_ALLOWED_STYLES.test(prop)) {
-          toRemove.push(prop);
-        }
-      }
-
-      for (let prop of toRemove) {
-        dummy.style.removeProperty(prop);
-      }
-
-      style = dummy.style.cssText;
-
-      dummy.style = "";
-
-      return style;
-    },
-  }); // Messages.ConsoleGeneric.prototype
+    }
+
+    for (let prop of toRemove) {
+      dummy.style.removeProperty(prop);
+    }
+
+    style = dummy.style.cssText;
+
+    dummy.style = "";
+
+    return style;
+  },
+}); // Messages.ConsoleGeneric.prototype
 
 /**
  * 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.
@@ -1600,121 +1597,120 @@ Messages.ConsoleTrace = function (packet
   this._renderStack = this._renderStack.bind(this);
   Messages.Simple.call(this, this._renderStack, options);
 
   this._repeatID.consoleApiLevel = packet.level;
   this._stacktrace = this._repeatID.stacktrace = packet.stacktrace;
   this._arguments = packet.arguments;
 };
 
-Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
-  {
+Messages.ConsoleTrace.prototype = extend(Messages.Simple.prototype, {
   /**
    * Holds the stackframes received from the server.
    *
    * @private
    * @type array
    */
-    _stacktrace: null,
+  _stacktrace: null,
 
   /**
    * Holds the arguments the content script passed to the console.trace()
    * method. This array is cleared when the message is initialized, and
    * associated actors are released.
    *
    * @private
    * @type array
    */
-    _arguments: null,
-
-    init: function ()
+  _arguments: null,
+
+  init: function ()
   {
-      let result = Messages.Simple.prototype.init.apply(this, arguments);
+    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);
-          }
+    if (Array.isArray(this._arguments)) {
+      for (let arg of this._arguments) {
+        if (WebConsoleUtils.isActorGrip(arg)) {
+          this.output._releaseObject(arg.actor);
         }
       }
-      this._arguments = null;
-
-      return result;
-    },
-
-    render: function ()
+    }
+    this._arguments = null;
+
+    return result;
+  },
+
+  render: function ()
   {
-      Messages.Simple.prototype.render.apply(this, arguments);
-      this.element.setAttribute("open", true);
-      return this;
-    },
+    Messages.Simple.prototype.render.apply(this, arguments);
+    this.element.setAttribute("open", true);
+    return this;
+  },
 
   /**
    * Render the stack frames.
    *
    * @private
    * @return DOMElement
    */
-    _renderStack: function ()
+  _renderStack: function ()
   {
-      let cmvar = this.document.createElementNS(XHTML_NS, "span");
-      cmvar.className = "cm-variable";
-      cmvar.textContent = "console";
-
-      let cmprop = this.document.createElementNS(XHTML_NS, "span");
-      cmprop.className = "cm-property";
-      cmprop.textContent = "trace";
-
-      let title = this.document.createElementNS(XHTML_NS, "span");
-      title.className = "message-body devtools-monospace";
-      title.appendChild(cmvar);
-      title.appendChild(this.document.createTextNode("."));
-      title.appendChild(cmprop);
-      title.appendChild(this.document.createTextNode("():"));
-
-      let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
-      let location = Messages.Simple.prototype._renderLocation.call(this);
-      if (location) {
-        location.target = "jsdebugger";
-      }
-
-      let widget = new Widgets.Stacktrace(this, this._stacktrace).render();
-
-      let body = this.document.createElementNS(XHTML_NS, "span");
-      body.className = "message-flex-body";
-      body.appendChild(title);
-      if (repeatNode) {
-        body.appendChild(repeatNode);
-      }
-      if (location) {
-        body.appendChild(location);
-      }
-      body.appendChild(this.document.createTextNode("\n"));
-
-      let frag = this.document.createDocumentFragment();
-      frag.appendChild(body);
-      frag.appendChild(widget.element);
-
-      return frag;
-    },
-
-    _renderBody: function ()
+    let cmvar = this.document.createElementNS(XHTML_NS, "span");
+    cmvar.className = "cm-variable";
+    cmvar.textContent = "console";
+
+    let cmprop = this.document.createElementNS(XHTML_NS, "span");
+    cmprop.className = "cm-property";
+    cmprop.textContent = "trace";
+
+    let title = this.document.createElementNS(XHTML_NS, "span");
+    title.className = "message-body devtools-monospace";
+    title.appendChild(cmvar);
+    title.appendChild(this.document.createTextNode("."));
+    title.appendChild(cmprop);
+    title.appendChild(this.document.createTextNode("():"));
+
+    let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
+    let location = Messages.Simple.prototype._renderLocation.call(this);
+    if (location) {
+      location.target = "jsdebugger";
+    }
+
+    let widget = new Widgets.Stacktrace(this, this._stacktrace).render();
+
+    let body = this.document.createElementNS(XHTML_NS, "span");
+    body.className = "message-flex-body";
+    body.appendChild(title);
+    if (repeatNode) {
+      body.appendChild(repeatNode);
+    }
+    if (location) {
+      body.appendChild(location);
+    }
+    body.appendChild(this.document.createTextNode("\n"));
+
+    let frag = this.document.createDocumentFragment();
+    frag.appendChild(body);
+    frag.appendChild(widget.element);
+
+    return frag;
+  },
+
+  _renderBody: function ()
   {
-      let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
-      body.classList.remove("devtools-monospace", "message-body");
-      return body;
-    },
+    let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
+    body.classList.remove("devtools-monospace", "message-body");
+    return body;
+  },
 
   // no-op for the message location and .repeats elements.
   // |this._renderStack| handles customized message output.
-    _renderLocation: function () { },
-    _renderRepeatNode: function () { },
-  }); // Messages.ConsoleTrace.prototype
+  _renderLocation: function () { },
+  _renderRepeatNode: function () { },
+}); // Messages.ConsoleTrace.prototype
 
 /**
  * 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.
@@ -1737,327 +1733,326 @@ Messages.ConsoleTable = function (packet
   this._populateTableData = this._populateTableData.bind(this);
   this._renderTable = this._renderTable.bind(this);
   Messages.Extended.call(this, [this._renderTable], options);
 
   this._repeatID.consoleApiLevel = packet.level;
   this._arguments = packet.arguments;
 };
 
-Messages.ConsoleTable.prototype = Heritage.extend(Messages.Extended.prototype,
-  {
+Messages.ConsoleTable.prototype = extend(Messages.Extended.prototype, {
   /**
    * Holds the arguments the content script passed to the console.table()
    * method.
    *
    * @private
    * @type array
    */
-    _arguments: null,
+  _arguments: null,
 
   /**
    * Array of objects that holds the data to log in the table.
    *
    * @private
    * @type array
    */
-    _data: null,
+  _data: null,
 
   /**
    * Key value pair of the id and display name for the columns in the table.
    * Refer to the TableWidget API.
    *
    * @private
    * @type object
    */
-    _columns: null,
+  _columns: null,
 
   /**
    * 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 ()
+  _populatePromise: null,
+
+  init: function ()
   {
-      let result = Messages.Extended.prototype.init.apply(this, arguments);
-      this._data = [];
-      this._columns = {};
-
-      this._populatePromise = this._populateTableData();
-
-      return result;
-    },
+    let result = Messages.Extended.prototype.init.apply(this, arguments);
+    this._data = [];
+    this._columns = {};
+
+    this._populatePromise = this._populateTableData();
+
+    return result;
+  },
 
   /**
    * 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;
-          }
+    if (columns.class == "Array") {
+      let items = columns.preview.items;
+
+      for (let item of items) {
+        if (typeof item == "string") {
+          this._columns[item] = item;
         }
-      } else if (typeof columns == "string" && columns) {
-        this._columns[columns] = columns;
       }
-    },
+    } else if (typeof columns == "string" && columns) {
+      this._columns[columns] = columns;
+    }
+  },
 
   /**
    * 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;
-      }
-
-      let data = this._arguments[0];
-      if (data.class != "Array" && data.class != "Object" &&
+    let deferred = promise.defer();
+
+    if (this._arguments.length <= 0) {
+      return;
+    }
+
+    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;
+    }
+
+    let hasColumnsArg = false;
+    if (this._arguments.length > 1) {
+      if (data.class == "Object" || data.class == "Array") {
+        this._columns["_index"] = l10n.getStr("table.index");
+      } else {
+        this._columns["_index"] = l10n.getStr("table.iterationIndex");
       }
 
-      let hasColumnsArg = false;
-      if (this._arguments.length > 1) {
-        if (data.class == "Object" || data.class == "Array") {
-          this._columns["_index"] = l10n.getStr("table.index");
-        } else {
-          this._columns["_index"] = l10n.getStr("table.iterationIndex");
-        }
-
-        this._setColumns(this._arguments[1]);
-        hasColumnsArg = true;
-      }
-
-      if (data.class == "Object" || data.class == "Array") {
+      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,
+      this.client = new ObjectClient(this.output.owner.jsterm.hud.proxy.client,
           data);
-        this.client.getPrototypeAndProperties(aResponse => {
-          let {ownProperties} = aResponse;
-          let rowCount = 0;
-          let columnCount = 0;
-
-          for (let index of Object.keys(ownProperties || {})) {
+      this.client.getPrototypeAndProperties(aResponse => {
+        let {ownProperties} = aResponse;
+        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 (data.class == "Array" && index == "length") {
+            continue;
+          }
+
+          if (!hasColumnsArg) {
+            this._columns["_index"] = l10n.getStr("table.index");
+          }
+
+          if (data.class == "Array") {
+            if (index == parseInt(index)) {
+              index = parseInt(index);
             }
-
-            if (!hasColumnsArg) {
-              this._columns["_index"] = l10n.getStr("table.index");
-            }
-
-            if (data.class == "Array") {
-              if (index == parseInt(index)) {
-                index = parseInt(index);
+          }
+
+          let property = ownProperties[index].value;
+          let item = { _index: index };
+
+          if (property.class == "Object" || property.class == "Array") {
+            let {preview} = property;
+            let entries = property.class == "Object" ?
+                preview.ownProperties : preview.items;
+
+            for (let key of Object.keys(entries)) {
+              let value = property.class == "Object" ?
+                  preview.ownProperties[key].value : preview.items[key];
+
+              item[key] = this._renderValueGrip(value, { concise: true });
+
+              if (!hasColumnsArg && !(key in this._columns) &&
+                  (++columnCount <= TABLE_COLUMN_MAX_ITEMS)) {
+                this._columns[key] = key;
               }
             }
-
-            let property = ownProperties[index].value;
-            let item = { _index: index };
-
-            if (property.class == "Object" || property.class == "Array") {
-              let {preview} = property;
-              let entries = property.class == "Object" ?
-                preview.ownProperties : preview.items;
-
-              for (let key of Object.keys(entries)) {
-                let value = property.class == "Object" ?
-                  preview.ownProperties[key].value : preview.items[key];
-
-                item[key] = this._renderValueGrip(value, { concise: true });
-
-                if (!hasColumnsArg && !(key in this._columns) &&
-                  (++columnCount <= TABLE_COLUMN_MAX_ITEMS)) {
-                  this._columns[key] = key;
-                }
-              }
-            } else {
+          } else {
             // Display the value for any non-object data input.
-              item["_value"] = this._renderValueGrip(property, { concise: true });
-
-              if (!hasColumnsArg && !("_value" in this._columns)) {
-                this._columns["_value"] = l10n.getStr("table.value");
-              }
-            }
-
-            this._data.push(item);
-
-            if (++rowCount == TABLE_ROW_MAX_ITEMS) {
-              break;
+            item["_value"] = this._renderValueGrip(property, { concise: true });
+
+            if (!hasColumnsArg && !("_value" in this._columns)) {
+              this._columns["_value"] = l10n.getStr("table.value");
             }
           }
 
-          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");
-        }
-
-        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 })
-          };
-
           this._data.push(item);
 
           if (++rowCount == TABLE_ROW_MAX_ITEMS) {
             break;
           }
         }
 
         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");
+      });
+    } 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");
+      }
+
+      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 })
+        };
+
+        this._data.push(item);
+
+        if (++rowCount == TABLE_ROW_MAX_ITEMS) {
+          break;
         }
-
-        let rowCount = 0;
-        for (let entry of entries) {
-          let item = {
-            _index : rowCount,
-            _value: this._renderValueGrip(entry, { concise: true })
-          };
-
-          this._data.push(item);
-
-          if (++rowCount == TABLE_ROW_MAX_ITEMS) {
-            break;
-          }
+      }
+
+      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");
+      }
+
+      let rowCount = 0;
+      for (let entry of entries) {
+        let item = {
+          _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 ()
+      deferred.resolve();
+    }
+
+    return deferred.promise;
+  },
+
+  render: function ()
   {
-      Messages.Extended.prototype.render.apply(this, arguments);
-      this.element.setAttribute("open", true);
-      return this;
-    },
+    Messages.Extended.prototype.render.apply(this, arguments);
+    this.element.setAttribute("open", true);
+    return this;
+  },
 
   /**
    * Render the table.
    *
    * @private
    * @return DOMElement
    */
-    _renderTable: function ()
+  _renderTable: function ()
   {
-      let cmvar = this.document.createElementNS(XHTML_NS, "span");
-      cmvar.className = "cm-variable";
-      cmvar.textContent = "console";
-
-      let cmprop = this.document.createElementNS(XHTML_NS, "span");
-      cmprop.className = "cm-property";
-      cmprop.textContent = "table";
-
-      let title = this.document.createElementNS(XHTML_NS, "span");
-      title.className = "message-body devtools-monospace";
-      title.appendChild(cmvar);
-      title.appendChild(this.document.createTextNode("."));
-      title.appendChild(cmprop);
-      title.appendChild(this.document.createTextNode("():"));
-
-      let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
-      let location = Messages.Simple.prototype._renderLocation.call(this);
-      if (location) {
-        location.target = "jsdebugger";
-      }
-
-      let body = this.document.createElementNS(XHTML_NS, "span");
-      body.className = "message-flex-body";
-      body.appendChild(title);
-      if (repeatNode) {
-        body.appendChild(repeatNode);
-      }
-      if (location) {
-        body.appendChild(location);
-      }
-      body.appendChild(this.document.createTextNode("\n"));
-
-      let result = this.document.createElementNS(XHTML_NS, "div");
-      result.appendChild(body);
-
-      if (this._populatePromise) {
-        this._populatePromise.then(() => {
-          if (this._data.length > 0) {
-            let widget = new Widgets.Table(this, this._data, this._columns).render();
-            result.appendChild(widget.element);
-          }
-
-          result.scrollIntoView();
-          this.output.owner.emit("messages-table-rendered");
+    let cmvar = this.document.createElementNS(XHTML_NS, "span");
+    cmvar.className = "cm-variable";
+    cmvar.textContent = "console";
+
+    let cmprop = this.document.createElementNS(XHTML_NS, "span");
+    cmprop.className = "cm-property";
+    cmprop.textContent = "table";
+
+    let title = this.document.createElementNS(XHTML_NS, "span");
+    title.className = "message-body devtools-monospace";
+    title.appendChild(cmvar);
+    title.appendChild(this.document.createTextNode("."));
+    title.appendChild(cmprop);
+    title.appendChild(this.document.createTextNode("():"));
+
+    let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
+    let location = Messages.Simple.prototype._renderLocation.call(this);
+    if (location) {
+      location.target = "jsdebugger";
+    }
+
+    let body = this.document.createElementNS(XHTML_NS, "span");
+    body.className = "message-flex-body";
+    body.appendChild(title);
+    if (repeatNode) {
+      body.appendChild(repeatNode);
+    }
+    if (location) {
+      body.appendChild(location);
+    }
+    body.appendChild(this.document.createTextNode("\n"));
+
+    let result = this.document.createElementNS(XHTML_NS, "div");
+    result.appendChild(body);
+
+    if (this._populatePromise) {
+      this._populatePromise.then(() => {
+        if (this._data.length > 0) {
+          let widget = new Widgets.Table(this, this._data, this._columns).render();
+          result.appendChild(widget.element);
+        }
+
+        result.scrollIntoView();
+        this.output.owner.emit("messages-table-rendered");
 
         // Release object actors
-          if (Array.isArray(this._arguments)) {
-            for (let arg of this._arguments) {
-              if (WebConsoleUtils.isActorGrip(arg)) {
-                this.output._releaseObject(arg.actor);
-              }
+        if (Array.isArray(this._arguments)) {
+          for (let arg of this._arguments) {
+            if (WebConsoleUtils.isActorGrip(arg)) {
+              this.output._releaseObject(arg.actor);
             }
           }
-          this._arguments = null;
-        });
-      }
-
-      return result;
-    },
-
-    _renderBody: function ()
+        }
+        this._arguments = null;
+      });
+    }
+
+    return result;
+  },
+
+  _renderBody: function ()
   {
-      let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
-      body.classList.remove("devtools-monospace", "message-body");
-      return body;
-    },
+    let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
+    body.classList.remove("devtools-monospace", "message-body");
+    return body;
+  },
 
   // no-op for the message location and .repeats elements.
   // |this._renderTable| handles customized message output.
-    _renderLocation: function () { },
-    _renderRepeatNode: function () { },
-  }); // Messages.ConsoleTable.prototype
+  _renderLocation: function () { },
+  _renderRepeatNode: function () { },
+}); // Messages.ConsoleTable.prototype
 
 var Widgets = {};
 
 /**
  * The base widget class.
  *
  * @constructor
  * @param object message
@@ -2180,37 +2175,36 @@ Widgets.BaseWidget.prototype = {
  *        The UNIX timestamp to display.
  */
 Widgets.MessageTimestamp = function (message, timestamp)
 {
   Widgets.BaseWidget.call(this, message);
   this.timestamp = timestamp;
 };
 
-Widgets.MessageTimestamp.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
-  {
+Widgets.MessageTimestamp.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The UNIX timestamp.
    * @type number
    */
-    timestamp: 0,
-
-    render: function ()
+  timestamp: 0,
+
+  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) + " ";
-
+    if (this.element) {
       return this;
-    },
-  }); // Widgets.MessageTimestamp.prototype
+    }
+
+    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
@@ -2222,128 +2216,127 @@ Widgets.MessageTimestamp.prototype = Her
  */
 Widgets.URLString = function (message, str, unshortenedStr)
 {
   Widgets.BaseWidget.call(this, message);
   this.str = str;
   this.unshortenedStr = unshortenedStr;
 };
 
-Widgets.URLString.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
-  {
+Widgets.URLString.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The string to format, which contains at least one valid URL.
    * @type string
    */
-    str: "",
-
-    render: function ()
+  str: "",
+
+  render: function ()
   {
-      if (this.element) {
-        return this;
-      }
+    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"
-      });
-      this.element.appendChild(this._renderText("\""));
+    this.element = this.el("span", {
+      class: "console-string"
+    });
+    this.element.appendChild(this._renderText("\""));
 
     // As we walk through the tokens of the source string, we make sure to preserve
     // the original whitespace that separated the tokens.
-      let tokens = this.str.split(/\s+/);
-      let textStart = 0;
-      let tokenStart;
-      for (let i = 0; i < tokens.length; i++) {
-        let token = tokens[i];
-        let unshortenedToken;
-        tokenStart = this.str.indexOf(token, textStart);
-        if (this._isURL(token)) {
+    let tokens = this.str.split(/\s+/);
+    let textStart = 0;
+    let tokenStart;
+    for (let i = 0; i < tokens.length; i++) {
+      let token = tokens[i];
+      let unshortenedToken;
+      tokenStart = this.str.indexOf(token, textStart);
+      if (this._isURL(token)) {
         // The last URL in the string might be shortened.  If so, get the
         // real URL so the rendered link can point to it.
-          if (i === tokens.length - 1 && this.unshortenedStr) {
-            unshortenedToken = this.unshortenedStr.slice(tokenStart).split(/\s+/, 1)[0];
-          }
-          this.element.appendChild(this._renderText(this.str.slice(textStart, tokenStart)));
-          textStart = tokenStart + token.length;
-          this.element.appendChild(this._renderURL(token, unshortenedToken));
+        if (i === tokens.length - 1 && this.unshortenedStr) {
+          unshortenedToken = this.unshortenedStr.slice(tokenStart).split(/\s+/, 1)[0];
         }
+        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)));
-      this.element.appendChild(this._renderText("\""));
-
-      return this;
-    },
+    this.element.appendChild(this._renderText(this.str.slice(textStart, this.str.length)));
+    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);
-    },
+    if (typeof grip != "string") {
+      return false;
+    }
+
+    let tokens = grip.split(/\s+/);
+    return tokens.some(this._isURL);
+  },
 
   /**
    * Determines whether a string token is a valid URL.
    *
    * @param string token
    *        The token.
    * @return boolean
    *         Whenther the token is a URL.
    */
-    _isURL: function (token) {
-      try {
-        let uri = URI.newURI(token, null, null);
-        let url = uri.QueryInterface(Ci.nsIURL);
-        return true;
-      } catch (e) {
-        return false;
-      }
-    },
+  _isURL: function (token) {
+    try {
+      let uri = URI.newURI(token, null, null);
+      let url = uri.QueryInterface(Ci.nsIURL);
+      return true;
+    } catch (e) {
+      return false;
+    }
+  },
 
   /**
    * Renders a string as a URL.
    *
    * @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);
-      return result;
-    },
-
-    _renderText: function (text) {
-      return this.el("span", text);
-    },
-  }); // Widgets.URLString.prototype
+    let unshortened = fullUrl || url;
+    let result = this.el("a", {
+      class: "url",
+      title: unshortened,
+      href: unshortened,
+      draggable: false
+    }, url);
+    this.message._addLinkCallback(result);
+    return result;
+  },
+
+  _renderText: function (text) {
+    return this.el("span", text);
+  },
+}); // Widgets.URLString.prototype
 
 /**
  * Widget used for displaying ObjectActors that have no specialised renderers.
  *
  * @constructor
  * @param object message
  *        The owning message.
  * @param object objectActor
@@ -2356,71 +2349,70 @@ Widgets.URLString.prototype = Heritage.e
 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 = Heritage.extend(Widgets.BaseWidget.prototype,
-  {
+Widgets.JSObject.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The ObjectActor displayed by the widget.
    * @type object
    */
-    objectActor: null,
-
-    render: function ()
+  objectActor: null,
+
+  render: function ()
   {
-      if (!this.element) {
-        this._render();
-      }
-
-      return this;
-    },
-
-    _render: function ()
+    if (!this.element) {
+      this._render();
+    }
+
+    return this;
+  },
+
+  _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 });
-    },
+    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,
+    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(" { ");
-    },
+    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(" }");
-    },
+    this._text(" }");
+  },
 
   /**
    * Render an object property.
    *
    * @param String key
    *        The property name.
    * @param Object value
    *        The property value, as an RDP grip.
@@ -2428,83 +2420,83 @@ Widgets.JSObject.prototype = Heritage.ex
    *        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 });
-        container.appendChild(valueElem);
-      }
-    },
+    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 });
+      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;
-        }
-      };
-
-      for (let key of Object.keys(ownProperties || {})) {
-        this._renderObjectProperty(key, getValue(ownProperties[key]), container,
+    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;
+      }
+    };
+
+    for (let key of Object.keys(ownProperties || {})) {
+      this._renderObjectProperty(key, getValue(ownProperties[key]), container,
                                  shown > 0 || needsComma,
                                  ownProperties[key].get || ownProperties[key].set);
-        shown++;
-      }
-
-      let ownPropertiesShown = shown;
-
-      for (let key of Object.keys(safeGetterValues || {})) {
-        this._renderObjectProperty(key, safeGetterValues[key].getterValue,
+      shown++;
+    }
+
+    let ownPropertiesShown = shown;
+
+    for (let key of Object.keys(safeGetterValues || {})) {
+      this._renderObjectProperty(key, safeGetterValues[key].getterValue,
                                  container, shown > 0 || needsComma);
-        shown++;
-      }
-
-      if (typeof preview.ownPropertiesLength == "number" &&
+      shown++;
+    }
+
+    if (typeof preview.ownPropertiesLength == "number" &&
         ownPropertiesShown < preview.ownPropertiesLength) {
-        this._text(", ");
-
-        let n = preview.ownPropertiesLength - ownPropertiesShown;
-        let str = VariablesView.stringifiers._getNMoreString(n);
-        this._anchor(str);
-      }
-    },
+      this._text(", ");
+
+      let n = preview.ownPropertiesLength - ownPropertiesShown;
+      let str = VariablesView.stringifiers._getNMoreString(n);
+      this._anchor(str);
+    }
+  },
 
   /**
    * Render an anchor with a given text content and link.
    *
    * @private
    * @param string text
    *        Text to show in the anchor.
    * @param object [options]
@@ -2516,131 +2508,131 @@ Widgets.JSObject.prototype = Heritage.ex
    *        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 (!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;
-
-      let anchor = this.el("a", {
-        class: options.className,
-        draggable: false,
-        href: options.href || "#",
-      }, text);
-
-      this.message._addLinkCallback(anchor, options.onClick);
-
-      anchor.addEventListener("contextmenu", options.onContextMenu.bind(this));
-
-      if (options.appendTo) {
-        options.appendTo.appendChild(anchor);
-      } else if (!("appendTo" in options) && this.element) {
-        this.element.appendChild(anchor);
-      }
-
-      return anchor;
-    },
-
-    openObjectInVariablesView: function ()
+      options.onClick = options.href ? this._onClickAnchor : this._onClick;
+    }
+
+    options.onContextMenu = options.onContextMenu || this._onContextMenu;
+
+    let anchor = this.el("a", {
+      class: options.className,
+      draggable: false,
+      href: options.href || "#",
+    }, text);
+
+    this.message._addLinkCallback(anchor, options.onClick);
+
+    anchor.addEventListener("contextmenu", options.onContextMenu.bind(this));
+
+    if (options.appendTo) {
+      options.appendTo.appendChild(anchor);
+    } else if (!("appendTo" in options) && this.element) {
+      this.element.appendChild(anchor);
+    }
+
+    return anchor;
+  },
+
+  openObjectInVariablesView: function ()
   {
-      this.output.openVariablesView({
-        label: VariablesView.getString(this.objectActor, { concise: true }),
-        objectActor: this.objectActor,
-        autofocus: true,
-      });
-    },
-
-    storeObjectInWindow: function ()
+    this.output.openVariablesView({
+      label: VariablesView.getString(this.objectActor, { concise: true }),
+      objectActor: this.objectActor,
+      autofocus: true,
+    });
+  },
+
+  storeObjectInWindow: function ()
   {
-      let evalString = `{ let i = 0;
+    let evalString = `{ let i = 0;
       while (this.hasOwnProperty("temp" + i) && i < 1000) {
         i++;
       }
       this["temp" + i] = _self;
       "temp" + i;
     }`;
-      let options = {
-        selectedObjectActor: this.objectActor.actor,
-      };
-
-      this.output.owner.jsterm.requestEvaluation(evalString, options).then((res) => {
-        this.output.owner.jsterm.focus();
-        this.output.owner.jsterm.setInputValue(res.result);
-      });
-    },
+    let options = {
+      selectedObjectActor: this.objectActor.actor,
+    };
+
+    this.output.owner.jsterm.requestEvaluation(evalString, options).then((res) => {
+      this.output.owner.jsterm.focus();
+      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) {
+    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;
-      let cmPopup = doc.getElementById("output-contextmenu");
-
-      let openInVarViewCmd = doc.getElementById("menu_openInVarView");
-      let openVarView = this.openObjectInVariablesView.bind(this);
-      openInVarViewCmd.addEventListener("command", openVarView);
-      openInVarViewCmd.removeAttribute("disabled");
-      cmPopup.addEventListener("popuphiding", function onPopupHiding() {
-        cmPopup.removeEventListener("popuphiding", onPopupHiding);
-        openInVarViewCmd.removeEventListener("command", openVarView);
-        openInVarViewCmd.setAttribute("disabled", "true");
-      });
+    let doc = ev.target.ownerDocument;
+    let cmPopup = doc.getElementById("output-contextmenu");
+
+    let openInVarViewCmd = doc.getElementById("menu_openInVarView");
+    let openVarView = this.openObjectInVariablesView.bind(this);
+    openInVarViewCmd.addEventListener("command", openVarView);
+    openInVarViewCmd.removeAttribute("disabled");
+    cmPopup.addEventListener("popuphiding", function onPopupHiding() {
+      cmPopup.removeEventListener("popuphiding", onPopupHiding);
+      openInVarViewCmd.removeEventListener("command", openVarView);
+      openInVarViewCmd.setAttribute("disabled", "true");
+    });
 
     // 'Store as global variable' command isn't supported on pre-44 servers,
     // so remove it from the menu in that case.
-      let storeInGlobalCmd = doc.getElementById("menu_storeAsGlobal");
-      if (!this.output.webConsoleClient.traits.selectedObjectActor) {
-        storeInGlobalCmd.remove();
-      } else if (storeInGlobalCmd) {
-        let storeObjectInWindow = this.storeObjectInWindow.bind(this);
-        storeInGlobalCmd.addEventListener("command", storeObjectInWindow);
-        storeInGlobalCmd.removeAttribute("disabled");
-        cmPopup.addEventListener("popuphiding", function onPopupHiding() {
-          cmPopup.removeEventListener("popuphiding", onPopupHiding);
-          storeInGlobalCmd.removeEventListener("command", storeObjectInWindow);
-          storeInGlobalCmd.setAttribute("disabled", "true");
-        });
-      }
-    },
+    let storeInGlobalCmd = doc.getElementById("menu_storeAsGlobal");
+    if (!this.output.webConsoleClient.traits.selectedObjectActor) {
+      storeInGlobalCmd.remove();
+    } else if (storeInGlobalCmd) {
+      let storeObjectInWindow = this.storeObjectInWindow.bind(this);
+      storeInGlobalCmd.addEventListener("command", storeObjectInWindow);
+      storeInGlobalCmd.removeAttribute("disabled");
+      cmPopup.addEventListener("popuphiding", function onPopupHiding() {
+        cmPopup.removeEventListener("popuphiding", onPopupHiding);
+        storeInGlobalCmd.removeEventListener("command", storeObjectInWindow);
+        storeInGlobalCmd.setAttribute("disabled", "true");
+      });
+    }
+  },
 
   /**
    * Add a string to the message.
    *
    * @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
+    target.appendChild(this.document.createTextNode(str));
+  },
+}); // Widgets.JSObject.prototype
 
 Widgets.ObjectRenderers = {};
 Widgets.ObjectRenderers.byKind = {};
 Widgets.ObjectRenderers.byClass = {};
 
 /**
  * Add an object renderer.
  *
@@ -2687,17 +2679,17 @@ Widgets.ObjectRenderers.add = function (
     return true;
   });
 
   if (extendObj === Widgets.JSObject) {
     proto._render = obj.render;
   }
 
   constructor.canRender = obj.canRender;
-  constructor.prototype = Heritage.extend(extendObj.prototype, proto);
+  constructor.prototype = extend(extendObj.prototype, proto);
 
   if (obj.byClass) {
     Widgets.ObjectRenderers.byClass[obj.byClass] = constructor;
   } 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.");
@@ -3489,127 +3481,126 @@ Widgets.LongString = function (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 = Heritage.extend(Widgets.BaseWidget.prototype,
-  {
+Widgets.LongString.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The LongStringActor displayed by the widget.
    * @type object
    */
-    longStringActor: null,
-
-    render: function ()
+  longStringActor: null,
+
+  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());
-
+    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());
+
+    return this;
+  },
 
   /**
    * 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,
-      });
-    },
+    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;
-    },
+    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);
-    },
+    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");
-
-      this._renderString(this.longStringActor.initial + response.substring);
-
-      this.output.owner.emit("new-messages", new Set([{
-        update: true,
-        node: this.message.element,
-        response: response,
-      }]));
-
-      let toIndex = Math.min(this.longStringActor.length, MAX_LONG_STRING_LENGTH);
-      if (toIndex != this.longStringActor.length) {
-        this._logWarningAboutStringTooLong();
-      }
-    },
+    if (response.error) {
+      console.error("LongString substring failure: " + response.error);
+      return;
+    }
+
+    this.element.lastChild.remove();
+    this.element.classList.remove("longString");
+
+    this._renderString(this.longStringActor.initial + response.substring);
+
+    this.output.owner.emit("new-messages", new Set([{
+      update: true,
+      node: this.message.element,
+      response: response,
+    }]));
+
+    let toIndex = Math.min(this.longStringActor.length, MAX_LONG_STRING_LENGTH);
+    if (toIndex != this.longStringActor.length) {
+      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
+    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
@@ -3619,89 +3610,88 @@ Widgets.LongString.prototype = Heritage.
  *        over the remote protocol.
  */
 Widgets.Stacktrace = function (message, stacktrace)
 {
   Widgets.BaseWidget.call(this, message);
   this.stacktrace = stacktrace;
 };
 
-Widgets.Stacktrace.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
-  {
+Widgets.Stacktrace.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * The stackframes received from the server.
    * @type array
    */
-    stacktrace: null,
-
-    render: function ()
+  stacktrace: null,
+
+  render: function ()
   {
-      if (this.element) {
-        return this;
+    if (this.element) {
+      return this;
+    }
+
+    let result = this.element = this.document.createElementNS(XHTML_NS, "ul");
+    result.className = "stacktrace devtools-monospace";
+
+    if (this.stacktrace) {
+      for (let frame of this.stacktrace) {
+        result.appendChild(this._renderFrame(frame));
       }
-
-      let result = this.element = this.document.createElementNS(XHTML_NS, "ul");
-      result.className = "stacktrace devtools-monospace";
-
-      if (this.stacktrace) {
-        for (let frame of this.stacktrace) {
-          result.appendChild(this._renderFrame(frame));
-        }
-      }
-
-      return this;
-    },
+    }
+
+    return this;
+  },
 
   /**
    * Render a frame object received from the server.
    *
    * @param object frame
    *        The stack frame to display. This object should have the following
    *        properties: functionName, filename and lineNumber.
    * @return DOMElement
    *         The DOM element to display for the given frame.
    */
-    _renderFrame: function (frame)
+  _renderFrame: function (frame)
   {
-      let fn = this.document.createElementNS(XHTML_NS, "span");
-      fn.className = "function";
-
-      let asyncCause = "";
-      if (frame.asyncCause) {
-        asyncCause =
+    let fn = this.document.createElementNS(XHTML_NS, "span");
+    fn.className = "function";
+
+    let asyncCause = "";
+    if (frame.asyncCause) {
+      asyncCause =
         l10n.getFormatStr("stacktrace.asyncStack", [frame.asyncCause]) + " ";
-      }
-
-      if (frame.functionName) {
-        let span = this.document.createElementNS(XHTML_NS, "span");
-        span.className = "cm-variable";
-        span.textContent = asyncCause + frame.functionName;
-        fn.appendChild(span);
-        fn.appendChild(this.document.createTextNode("()"));
-      } else {
-        fn.classList.add("cm-comment");
-        fn.textContent = asyncCause + l10n.getStr("stacktrace.anonymousFunction");
-      }
-
-      let location = this.output.owner.createLocationNode({url: frame.filename,
+    }
+
+    if (frame.functionName) {
+      let span = this.document.createElementNS(XHTML_NS, "span");
+      span.className = "cm-variable";
+      span.textContent = asyncCause + frame.functionName;
+      fn.appendChild(span);
+      fn.appendChild(this.document.createTextNode("()"));
+    } else {
+      fn.classList.add("cm-comment");
+      fn.textContent = asyncCause + l10n.getStr("stacktrace.anonymousFunction");
+    }
+
+    let location = this.output.owner.createLocationNode({url: frame.filename,
                                                         line: frame.lineNumber});
 
     // .devtools-monospace sets font-size to 80%, however .body already has
     // .devtools-monospace. If we keep it here, the location would be rendered
     // smaller.
-      location.classList.remove("devtools-monospace");
-
-      let elem = this.document.createElementNS(XHTML_NS, "li");
-      elem.appendChild(fn);
-      elem.appendChild(location);
-      elem.appendChild(this.document.createTextNode("\n"));
-
-      return elem;
-    },
-  }); // Widgets.Stacktrace.prototype
+    location.classList.remove("devtools-monospace");
+
+    let elem = this.document.createElementNS(XHTML_NS, "li");
+    elem.appendChild(fn);
+    elem.appendChild(location);
+    elem.appendChild(this.document.createTextNode("\n"));
+
+    return elem;
+  },
+}); // Widgets.Stacktrace.prototype
 
 
 /**
  * The table widget.
  *
  * @constructor
  * @extends Widgets.BaseWidget
  * @param object message
@@ -3714,52 +3704,51 @@ Widgets.Stacktrace.prototype = Heritage.
  */
 Widgets.Table = function (message, data, columns)
 {
   Widgets.BaseWidget.call(this, message);
   this.data = data;
   this.columns = columns;
 };
 
-Widgets.Table.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
-  {
+Widgets.Table.prototype = extend(Widgets.BaseWidget.prototype, {
   /**
    * Array of objects that holds the data to output in the table.
    * @type array
    */
-    data: null,
+  data: null,
 
   /**
    * Object containing the key value pair of the id and display name for
    * the columns in the table.
    * @type object
    */
-    columns: null,
-
-    render: function () {
-      if (this.element) {
-        return this;
-      }
-
-      let result = this.element = this.document.createElementNS(XHTML_NS, "div");
-      result.className = "consoletable devtools-monospace";
-
-      this.table = new TableWidget(result, {
-        initialColumns: this.columns,
-        uniqueId: "_index",
-        firstColumn: "_index"
-      });
-
-      for (let row of this.data) {
-        this.table.push(row);
-      }
-
+  columns: null,
+
+  render: function () {
+    if (this.element) {
       return this;
     }
-  }); // Widgets.Table.prototype
+
+    let result = this.element = this.document.createElementNS(XHTML_NS, "div");
+    result.className = "consoletable devtools-monospace";
+
+    this.table = new TableWidget(result, {
+      initialColumns: this.columns,
+      uniqueId: "_index",
+      firstColumn: "_index"
+    });
+
+    for (let row of this.data) {
+      this.table.push(row);
+    }
+
+    return this;
+  }
+}); // Widgets.Table.prototype
 
 function gSequenceId()
 {
   return gSequenceId.n++;
 }
 gSequenceId.n = 0;
 
 exports.ConsoleOutput = ConsoleOutput;
--- a/devtools/client/webconsole/hudservice.js
+++ b/devtools/client/webconsole/hudservice.js
@@ -4,20 +4,20 @@
  * 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 {Cc, Ci, Cu} = require("chrome");
 
 var WebConsoleUtils = require("devtools/shared/webconsole/utils").Utils;
-var Heritage = require("sdk/core/heritage");
+var { extend } = require("sdk/core/heritage");
 var {TargetFactory} = require("devtools/client/framework/target");
 var {Tools} = require("devtools/client/definitions");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 var promise = require("promise");
 var Services = require("Services");
 
 loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
 loader.lazyRequireGetter(this, "WebConsoleFrame", "devtools/client/webconsole/webconsole", true);
 loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
 loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
 loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true);
@@ -29,18 +29,17 @@ var l10n = new WebConsoleUtils.L10n(STRI
 
 const BROWSER_CONSOLE_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
 
 // The preference prefix for all of the Browser Console filters.
 const BROWSER_CONSOLE_FILTER_PREFS_PREFIX = "devtools.browserconsole.filter.";
 
 var gHudId = 0;
 
-// /////////////////////////////////////////////////////////////////////////
-// // The HUD service
+// The HUD service
 
 function HUD_SERVICE()
 {
   this.consoles = new Map();
   this.lastFinishedRequest = { callback: null };
 }
 
 HUD_SERVICE.prototype =
@@ -633,93 +632,92 @@ WebConsole.prototype = {
  *        The window of the browser console owner.
  */
 function BrowserConsole()
 {
   WebConsole.apply(this, arguments);
   this._telemetry = new Telemetry();
 }
 
-BrowserConsole.prototype = Heritage.extend(WebConsole.prototype,
-  {
-    _browserConsole: true,
-    _bc_init: null,
-    _bc_destroyer: null,
+BrowserConsole.prototype = extend(WebConsole.prototype, {
+  _browserConsole: true,
+  _bc_init: null,
+  _bc_destroyer: null,
 
-    $init: WebConsole.prototype.init,
+  $init: WebConsole.prototype.init,
 
   /**
    * Initialize the Browser Console instance.
    *
    * @return object
    *         A promise for the initialization.
    */
-    init: function BC_init()
+  init: function BC_init()
   {
-      if (this._bc_init) {
-        return this._bc_init;
-      }
+    if (this._bc_init) {
+      return this._bc_init;
+    }
 
-      this.ui._filterPrefsPrefix = BROWSER_CONSOLE_FILTER_PREFS_PREFIX;
+    this.ui._filterPrefsPrefix = BROWSER_CONSOLE_FILTER_PREFS_PREFIX;
 
-      let window = this.iframeWindow;
+    let window = this.iframeWindow;
 
     // Make sure that the closing of the Browser Console window destroys this
     // instance.
-      let onClose = () => {
-        window.removeEventListener("unload", onClose);
-        window.removeEventListener("focus", onFocus);
-        this.destroy();
-      };
-      window.addEventListener("unload", onClose);
+    let onClose = () => {
+      window.removeEventListener("unload", onClose);
+      window.removeEventListener("focus", onFocus);
+      this.destroy();
+    };
+    window.addEventListener("unload", onClose);
 
     // Make sure Ctrl-W closes the Browser Console window.
-      window.document.getElementById("cmd_close").removeAttribute("disabled");
+    window.document.getElementById("cmd_close").removeAttribute("disabled");
 
-      this._telemetry.toolOpened("browserconsole");
+    this._telemetry.toolOpened("browserconsole");
 
     // Create an onFocus handler just to display the dev edition promo.
     // This is to prevent race conditions in some environments.
     // Hook to display promotional Developer Edition doorhanger. Only displayed once.
-      let onFocus = () => showDoorhanger({ window, type: "deveditionpromo" });
-      window.addEventListener("focus", onFocus);
+    let onFocus = () => showDoorhanger({ window, type: "deveditionpromo" });
+    window.addEventListener("focus", onFocus);
 
-      this._bc_init = this.$init();
-      return this._bc_init;
-    },
+    this._bc_init = this.$init();
+    return this._bc_init;
+  },
 
-    $destroy: WebConsole.prototype.destroy,
+  $destroy: WebConsole.prototype.destroy,
 
   /**
    * Destroy the object.
    *
    * @return object
    *         A promise object that is resolved once the Browser Console is closed.
    */
-    destroy: function BC_destroy()
+  destroy: function BC_destroy()
   {
-      if (this._bc_destroyer) {
-        return this._bc_destroyer.promise;
-      }
+    if (this._bc_destroyer) {
+      return this._bc_destroyer.promise;
+    }
 
-      this._telemetry.toolClosed("browserconsole");
+    this._telemetry.toolClosed("browserconsole");
 
-      this._bc_destroyer = promise.defer();
+    this._bc_destroyer = promise.defer();
 
-      let chromeWindow = this.chromeWindow;
-      this.$destroy().then(() =>
+    let chromeWindow = this.chromeWindow;
+    this.$destroy().then(() =>
       this.target.client.close(() => {
         HUDService._browserConsoleID = null;
         chromeWindow.close();
         this._bc_destroyer.resolve(null);
       }));
 
-      return this._bc_destroyer.promise;
-    },
-  });
+    return this._bc_destroyer.promise;
+  },
+});
 
 const HUDService = new HUD_SERVICE();
 
 (() => {
   let methods = ["openWebConsole", "openBrowserConsole",
                  "toggleBrowserConsole", "getOpenWebConsole",
                  "getBrowserConsole", "getHudByWindow",
                  "openBrowserConsoleOrFocus", "getHudReferenceById"];
--- a/devtools/client/webconsole/new-console-output/test/components/head.js
+++ b/devtools/client/webconsole/new-console-output/test/components/head.js
@@ -8,17 +8,17 @@
 
 var { utils: Cu } = Components;
 
 Cu.import("resource://testing-common/Assert.jsm");
 
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
-var { Task } = require("resource://gre/modules/Task.jsm");
+var { Task } = require("devtools/shared/task");
 var { DebuggerServer } = require("devtools/server/main");
 var { DebuggerClient } = require("devtools/shared/client/main");
 
 const Services = require("Services");
 
 DevToolsUtils.testing = true;
 var { require: browserRequire } = BrowserLoader({
   baseURI: "resource://devtools/client/webconsole/",
--- a/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_01.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_01.js
@@ -4,17 +4,18 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejections should be fixed.
 
 "use strict";
 
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed(null);
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.toolbox is null");
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed(
+  "TypeError: this.toolbox is null");
 
 // Test the webconsole output for various types of DOM Nodes.
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-console-output-dom-elements.html";
 
 var inputTests = [
   {
@@ -50,19 +51,19 @@ var inputTests = [
     printOutput: "[object HTMLParagraphElement]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testNodeList()",
-    output: "NodeList [ <html>, <head>, <meta>, <title>, " +
-            "<body#body-id.body-class>, <p>, <p#lots-of-attributes>, <iframe>, " +
-            "<div.some.classname.here.with.more.classnames.here>, <script> ]",
+    output: "NodeList [ <p>, <p#lots-of-attributes>, <iframe>, " +
+            "<div.some.classname.here.with.more.classnames.here>, " +
+            "<svg>, <clipPath>, <rect>, <script> ]",
     printOutput: "[object NodeList]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testNodeInIframe()",
@@ -70,17 +71,18 @@ var inputTests = [
     printOutput: "[object HTMLParagraphElement]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testLotsOfAttributes()",
-    output: '<p id="lots-of-attributes" a="" b="" c="" d="" e="" f="" g="" h="" i="" j="" k="" l="" m="" n="">',
+    output: '<p id="lots-of-attributes" a="" b="" c="" d="" e="" f="" g="" ' +
+            'h="" i="" j="" k="" l="" m="" n="">',
     printOutput: "[object HTMLParagraphElement]",
     inspectable: true,
     noClick: true,
     inspectorIcon: true
   },
 
   {
     input: "testDocumentFragment()",
--- a/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_04.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_04.js
@@ -15,16 +15,20 @@ const TEST_DATA = [
   {
     // The first test shouldn't be returning the body element as this is the
     // default selected node, so re-selecting it won't fire the
     // inspector-updated event
     input: "testNode()",
     output: '<p some-attribute="some-value">'
   },
   {
+    input: "testSvgNode()",
+    output: '<clipPath>'
+  },
+  {
     input: "testBodyNode()",
     output: '<body class="body-class" id="body-id">'
   },
   {
     input: "testNodeInIframe()",
     output: "<p>"
   },
   {
--- a/devtools/client/webconsole/test/test-console-output-dom-elements.html
+++ b/devtools/client/webconsole/test/test-console-output-dom-elements.html
@@ -16,16 +16,21 @@
     console output message:
     "The character encoding of a framed document was not declared. The document may appear different if viewed without the document framing it."
     This wouldn't be a big deal, but when we look for a "<p>" in our `waitForMessage` helper,
     this extra encoding warning line contains the data URI source, returning a message
     that was unexpected
   -->
   <iframe src="data:text/html;charset=US-ASCII,<p>hello from iframe</p>"></iframe>
   <div class="some       classname      here      with       more classnames here"></div>
+  <svg>
+    <clipPath>
+      <rect x="0" y="0" width="10" height="5"></rect>
+    </clipPath>
+  </svg>
   <script type="text/javascript">
 function testBodyNode() {
   return document.body;
 }
 
 function testDocumentElement() {
   return document.documentElement;
 }
@@ -37,18 +42,22 @@ function testLotsOfAttributes() {
 function testDocument() {
   return document;
 }
 
 function testNode() {
   return document.querySelector("p");
 }
 
+function testSvgNode() {
+  return document.querySelector("clipPath");
+}
+
 function testNodeList() {
-  return document.querySelectorAll("*");
+  return document.querySelectorAll("body *");
 }
 
 function testNodeInIframe() {
   return document.querySelector("iframe").contentWindow.document.querySelector("p");
 }
 
 function testDocumentFragment() {
   var frag = document.createDocumentFragment();
--- a/devtools/client/webide/content/webide.js
+++ b/devtools/client/webide/content/webide.js
@@ -1,18 +1,16 @@
 /* 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/. */
 
 var Cc = Components.classes;
 var Cu = Components.utils;
 var Ci = Components.interfaces;
 
-Cu.import("resource://gre/modules/Task.jsm");
-
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
 const {Toolbox} = require("devtools/client/framework/toolbox");
 const Services = require("Services");
 const {AppProjects} = require("devtools/client/webide/modules/app-projects");
 const {Connection} = require("devtools/shared/client/connection-manager");
 const {AppManager} = require("devtools/client/webide/modules/app-manager");
@@ -21,16 +19,17 @@ const promise = require("promise");
 const ProjectEditor = require("devtools/client/projecteditor/lib/projecteditor");
 const {GetAvailableAddons} = require("devtools/client/webide/modules/addons");
 const {getJSON} = require("devtools/client/shared/getjson");
 const utils = require("devtools/client/webide/modules/utils");
 const Telemetry = require("devtools/client/shared/telemetry");
 const {RuntimeScanners} = require("devtools/client/webide/modules/runtimes");
 const {showDoorhanger} = require("devtools/client/shared/doorhanger");
 const {Simulators} = require("devtools/client/webide/modules/simulators");
+const {Task} = require("devtools/shared/task");
 
 const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
 
 const HTML = "http://www.w3.org/1999/xhtml";
 const HELP_URL = "https://developer.mozilla.org/docs/Tools/WebIDE/Troubleshooting";
 
 const MAX_ZOOM = 1.4;
 const MIN_ZOOM = 0.6;
--- a/devtools/client/webide/modules/app-manager.js
+++ b/devtools/client/webide/modules/app-manager.js
@@ -13,17 +13,17 @@ const {TextEncoder, OS} = Cu.import("res
 const {AppProjects} = require("devtools/client/webide/modules/app-projects");
 const TabStore = require("devtools/client/webide/modules/tab-store");
 const {AppValidator} = require("devtools/client/webide/modules/app-validator");
 const {ConnectionManager, Connection} = require("devtools/shared/client/connection-manager");
 const {AppActorFront} = require("devtools/shared/apps/app-actor-front");
 const {getDeviceFront} = require("devtools/server/actors/device");
 const {getPreferenceFront} = require("devtools/server/actors/preference");
 const {getSettingsFront} = require("devtools/server/actors/settings");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const {RuntimeScanners, RuntimeTypes} = require("devtools/client/webide/modules/runtimes");
 const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 const Telemetry = require("devtools/client/shared/telemetry");
 const {ProjectBuilding} = require("./build");
 
 const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
 
 var AppManager = exports.AppManager = {
--- a/devtools/client/webide/modules/app-validator.js
+++ b/devtools/client/webide/modules/app-validator.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 var {Ci, Cu, CC} = require("chrome");
 const promise = require("promise");
 
 const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
 const Services = require("Services");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 var XMLHttpRequest = CC("@mozilla.org/xmlextras/xmlhttprequest;1");
 var strings = Services.strings.createBundle("chrome://devtools/locale/app-manager.properties");
 
 function AppValidator({ type, location }) {
   this.type = type;
   this.location = location;
   this.errors = [];
   this.warnings = [];
--- a/devtools/client/webide/modules/build.js
+++ b/devtools/client/webide/modules/build.js
@@ -1,16 +1,16 @@
 /* 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/. */
 
 const {Cu, Cc, Ci} = require("chrome");
 
 const promise = require("promise");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 const { TextDecoder, OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
 const Subprocess = require("sdk/system/child_process/subprocess");
 
 const ProjectBuilding = exports.ProjectBuilding = {
   fetchPackageManifest: Task.async(function* (project) {
     let manifestPath = OS.Path.join(project.location, "package.json");
     let exists = yield OS.File.exists(manifestPath);
     if (!exists) {
--- a/devtools/client/webide/modules/project-list.js
+++ b/devtools/client/webide/modules/project-list.js
@@ -4,17 +4,17 @@
 
 const {Cu} = require("chrome");
 
 const Services = require("Services");
 const {AppProjects} = require("devtools/client/webide/modules/app-projects");
 const {AppManager} = require("devtools/client/webide/modules/app-manager");
 const promise = require("promise");
 const EventEmitter = require("devtools/shared/event-emitter");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const utils = require("devtools/client/webide/modules/utils");
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
 
 var ProjectList;
 
 module.exports = ProjectList = function (win, parentWindow) {
--- a/devtools/client/webide/modules/runtime-list.js
+++ b/devtools/client/webide/modules/runtime-list.js
@@ -4,17 +4,17 @@
 
 const {Cu} = require("chrome");
 
 const Services = require("Services");
 const {AppManager} = require("devtools/client/webide/modules/app-manager");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {RuntimeScanners, WiFiScanner} = require("devtools/client/webide/modules/runtimes");
 const {Devices} = Cu.import("resource://devtools/shared/apps/Devices.jsm");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const utils = require("devtools/client/webide/modules/utils");
 
 const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
 
 var RuntimeList;
 
 module.exports = RuntimeList = function (window, parentWindow) {
   EventEmitter.decorate(this);
--- a/devtools/client/webide/modules/simulators.js
+++ b/devtools/client/webide/modules/simulators.js
@@ -1,15 +1,15 @@
 /* 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/. */
 
 const { Cu } = require("chrome");
 const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 loader.lazyRequireGetter(this, "ConnectionManager", "devtools/shared/client/connection-manager", true);
 loader.lazyRequireGetter(this, "AddonSimulatorProcess", "devtools/client/webide/modules/simulator-process", true);
 loader.lazyRequireGetter(this, "OldAddonSimulatorProcess", "devtools/client/webide/modules/simulator-process", true);
 loader.lazyRequireGetter(this, "CustomSimulatorProcess", "devtools/client/webide/modules/simulator-process", true);
 const asyncStorage = require("devtools/shared/async-storage");
 const EventEmitter = require("devtools/shared/event-emitter");
 const promise = require("promise");
 const Services = require("Services");
--- a/devtools/client/webide/modules/tab-store.js
+++ b/devtools/client/webide/modules/tab-store.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const { Cu } = require("chrome");
 
 const { TargetFactory } = require("devtools/client/framework/target");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { Connection } = require("devtools/shared/client/connection-manager");
 const promise = require("promise");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 
 const _knownTabStores = new WeakMap();
 
 var TabStore;
 
 module.exports = TabStore = function (connection) {
   // If we already know about this connection,
   // let's re-use the existing store.
--- a/devtools/client/webide/test/head.js
+++ b/devtools/client/webide/test/head.js
@@ -6,17 +6,17 @@
 var {utils: Cu, classes: Cc, interfaces: Ci} = Components;
 
 Cu.import("resource://gre/modules/FileUtils.jsm");
 
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const {gDevTools} = require("devtools/client/framework/devtools");
 const promise = require("promise");
 const Services = require("Services");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const {AppProjects} = require("devtools/client/webide/modules/app-projects");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 DevToolsUtils.testing = true;
 
 var TEST_BASE;
 if (window.location === "chrome://browser/content/browser.xul") {
   TEST_BASE = "chrome://mochitests/content/browser/devtools/client/webide/test/";
 } else {
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -22,17 +22,17 @@
  * - WebAnimation spec:
  *   http://w3c.github.io/web-animations/
  * - WebAnimation WebIDL files:
  *   /dom/webidl/Animation*.webidl
  */
 
 const {Cu} = require("chrome");
 const promise = require("promise");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const protocol = require("devtools/shared/protocol");
 const {ActorClass, Actor, FrontClass, Front,
        Arg, method, RetVal, types} = protocol;
 // Make sure the nodeActor type is know here.
 const {NodeActor} = require("devtools/server/actors/inspector");
 const events = require("sdk/event/core");
 
 // Types of animations.
--- a/devtools/server/actors/gcli.js
+++ b/devtools/server/actors/gcli.js
@@ -1,15 +1,15 @@
 /* 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 { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const {
   method, Arg, Option, RetVal, Front, FrontClass, Actor, ActorClass
 } = require("devtools/shared/protocol");
 const events = require("sdk/event/core");
 const { createSystem } = require("gcli/system");
 
 /**
  * Manage remote connections that want to talk to GCLI
--- a/devtools/server/actors/heap-snapshot-file.js
+++ b/devtools/server/actors/heap-snapshot-file.js
@@ -2,21 +2,21 @@
  * 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 protocol = require("devtools/shared/protocol");
 const { method, Arg } = protocol;
 const Services = require("Services");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "DevToolsUtils",
                          "devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "OS", "resource://gre/modules/osfile.jsm", true);
-loader.lazyRequireGetter(this, "Task", "resource://gre/modules/Task.jsm", true);
 loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
                          "devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
 
 /**
  * The HeapSnapshotFileActor handles transferring heap snapshot files from the
  * server to the client. This has to be a global actor in the parent process
  * because child processes are sandboxed and do not have access to the file
  * system.
--- a/devtools/server/actors/highlighters.css
+++ b/devtools/server/actors/highlighters.css
@@ -153,17 +153,16 @@
   white-space: nowrap;
   direction: ltr;
   text-align: center;
   padding-bottom: 1px;
 }
 
 :-moz-native-anonymous .box-model-nodeinfobar-tagname {
   color: hsl(285,100%,75%);
-  text-transform: lowercase;
 }
 
 :-moz-native-anonymous .box-model-nodeinfobar-id {
   color: hsl(103,46%,54%);
 }
 
 :-moz-native-anonymous .box-model-nodeinfobar-classes,
 :-moz-native-anonymous .box-model-nodeinfobar-pseudo-classes {
--- a/devtools/server/actors/highlighters/box-model.js
+++ b/devtools/server/actors/highlighters/box-model.js
@@ -7,16 +7,17 @@
 const { extend } = require("sdk/core/heritage");
 const { AutoRefreshHighlighter } = require("./auto-refresh");
 const {
   CanvasFrameAnonymousContentHelper,
   getBindingElementAndPseudo, hasPseudoClassLock, getComputedStyle,
   createSVGNode, createNode, isNodeValid } = require("./utils/markup");
 const { getCurrentZoom,
   setIgnoreLayoutChanges } = require("devtools/shared/layout/utils");
+const inspector = require("devtools/server/actors/inspector");
 
 // Note that the order of items in this array is important because it is used
 // for drawing the BoxModelHighlighter's path elements correctly.
 const BOX_MODEL_REGIONS = ["margin", "border", "padding", "content"];
 const BOX_MODEL_SIDES = ["top", "right", "bottom", "left"];
 // Width of boxmodelhighlighter guides
 const GUIDE_STROKE_WIDTH = 1;
 // How high is the nodeinfobar (px).
@@ -638,28 +639,28 @@ BoxModelHighlighter.prototype = extend(A
     }
 
     guide.removeAttribute("hidden");
 
     return true;
   },
 
   /**
-   * Update node information (tagName#id.class)
+   * Update node information (displayName#id.class)
    */
   _updateInfobar: function () {
     if (!this.currentNode) {
       return;
     }
 
     let {bindingElement: node, pseudo} =
         getBindingElementAndPseudo(this.currentNode);
 
     // Update the tag, id, classes, pseudo-classes and dimensions
-    let tagName = node.tagName;
+    let displayName = inspector.getNodeDisplayName(node);
 
     let id = node.id ? "#" + node.id : "";
 
     let classList = (node.classList || []).length
                     ? "." + [...node.classList].join(".")
                     : "";
 
     let pseudos = PSEUDO_CLASSES.filter(pseudo => {
@@ -670,17 +671,17 @@ BoxModelHighlighter.prototype = extend(A
       pseudos += ":" + pseudo;
     }
 
     let rect = this._getOuterQuad("border").bounds;
     let dim = parseFloat(rect.width.toPrecision(6)) +
               " \u00D7 " +
               parseFloat(rect.height.toPrecision(6));
 
-    this.getElement("nodeinfobar-tagname").setTextContent(tagName);
+    this.getElement("nodeinfobar-tagname").setTextContent(displayName);
     this.getElement("nodeinfobar-id").setTextContent(id);
     this.getElement("nodeinfobar-classes").setTextContent(classList);
     this.getElement("nodeinfobar-pseudo-classes").setTextContent(pseudos);
     this.getElement("nodeinfobar-dimensions").setTextContent(dim);
 
     this._moveInfobar();
   },
 
--- a/devtools/server/actors/inspector.js
+++ b/devtools/server/actors/inspector.js
@@ -51,17 +51,17 @@
  */
 
 const {Cc, Ci, Cu} = require("chrome");
 const Services = require("Services");
 const protocol = require("devtools/shared/protocol");
 const {Arg, Option, method, RetVal, types} = protocol;
 const {LongStringActor} = require("devtools/server/actors/string");
 const promise = require("promise");
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 const object = require("sdk/util/object");
 const events = require("sdk/event/core");
 const {Class} = require("sdk/core/heritage");
 const {WalkerSearch} = require("devtools/server/actors/utils/walker-search");
 const {PageStyleActor, getFontPreviewData} = require("devtools/server/actors/styles");
 const {
   HighlighterActor,
   CustomHighlighterActor,
@@ -177,16 +177,30 @@ var gInspectingNode = null;
 
 // We expect this function to be called from the child.js frame script
 // when it receives the node to be inspected over the message manager.
 exports.setInspectingNode = function (val) {
   gInspectingNode = val;
 };
 
 /**
+ * Returns the properly cased version of the node's tag name, which can be
+ * used when displaying said name in the UI.
+ *
+ * @param  {Node} rawNode
+ *         Node for which we want the display name
+ * @return {String}
+ *         Properly cased version of the node tag name
+ */
+const getNodeDisplayName = function (rawNode) {
+  return (rawNode.prefix ? rawNode.prefix + ":" : "") + rawNode.localName;
+};
+exports.getNodeDisplayName = getNodeDisplayName;
+
+/**
  * Server side of the node actor.
  */
 var NodeActor = exports.NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
   initialize: function (walker, node) {
     protocol.Actor.prototype.initialize.call(this, null);
     this.walker = walker;
     this.rawNode = node;
     this._eventParsers = new EventParsers().parsers;
@@ -238,16 +252,17 @@ var NodeActor = exports.NodeActor = prot
 
     let form = {
       actor: this.actorID,
       baseURI: this.rawNode.baseURI,
       parent: parentNode ? parentNode.actorID : undefined,
       nodeType: this.rawNode.nodeType,
       namespaceURI: this.rawNode.namespaceURI,
       nodeName: this.rawNode.nodeName,
+      displayName: getNodeDisplayName(this.rawNode),
       numChildren: this.numChildren,
       singleTextChild: singleTextChild ? singleTextChild.form() : undefined,
 
       // doctype attributes
       name: this.rawNode.name,
       publicId: this.rawNode.publicId,
       systemId: this.rawNode.systemId,
 
@@ -1631,17 +1646,17 @@ var WalkerActor = protocol.ActorClassWit
 
       case "tag":
         if (!query) {
           nodes = this._multiFrameQuerySelectorAll("*");
         } else {
           nodes = this._multiFrameQuerySelectorAll(query);
         }
         for (let node of nodes) {
-          let tag = node.tagName.toLowerCase();
+          let tag = node.localName;
           sugs.tags.set(tag, (sugs.tags.get(tag)|0) + 1);
         }
         for (let [tag, count] of sugs.tags) {
           if ((new RegExp("^" + completing + ".*", "i")).test(tag)) {
             result.push([tag, count, selectorState]);
           }
         }
 
@@ -1658,17 +1673,17 @@ var WalkerActor = protocol.ActorClassWit
         }
 
         break;
 
       case "null":
         nodes = this._multiFrameQuerySelectorAll(query);
         for (let node of nodes) {
           sugs.ids.set(node.id, (sugs.ids.get(node.id)|0) + 1);
-          let tag = node.tagName.toLowerCase();
+          let tag = node.localName;
           sugs.tags.set(tag, (sugs.tags.get(tag)|0) + 1);
           for (let className of node.classList) {
             sugs.classes.set(className, (sugs.classes.get(className)|0) + 1);
           }
         }
         for (let [tag, count] of sugs.tags) {
           tag && result.push([tag, count]);
         }
--- a/devtools/server/actors/memory.js
+++ b/devtools/server/actors/memory.js
@@ -4,23 +4,23 @@
 
 "use strict";
 
 const { Cc, Ci, Cu, components } = require("chrome");
 const protocol = require("devtools/shared/protocol");
 const { method, RetVal, Arg, types } = protocol;
 const { Memory } = require("devtools/server/performance/memory");
 const { actorBridge } = require("devtools/server/actors/common");
+const { Task } = require("devtools/shared/task");
 loader.lazyRequireGetter(this, "events", "sdk/event/core");
 loader.lazyRequireGetter(this, "StackFrameCache",
                          "devtools/server/actors/utils/stack", true);
 loader.lazyRequireGetter(this, "FileUtils",
                          "resource://gre/modules/FileUtils.jsm", true);
 loader.lazyRequireGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm", true);
-loader.lazyRequireGetter(this, "Task", "resource://gre/modules/Task.jsm", true);
 loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
                          "devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
 loader.lazyRequireGetter(this, "ThreadSafeChromeUtils");
 
 types.addDictType("AllocationsRecordingOptions", {
   // The probability we sample any given allocation when recording
   // allocations. Must be between 0.0 and 1.0. Defaults to 1.0, or sampling
   // every allocation.
--- a/devtools/server/actors/performance.js
+++ b/devtools/server/actors/performance.js
@@ -1,17 +1,17 @@
 /* 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 { Cu } = require("chrome");
 const protocol = require("devtools/shared/protocol");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { Actor, custom, method, RetVal, Arg, Option, types, preEvent } = protocol;
 const { actorBridge } = require("devtools/server/actors/common");
 const { PerformanceRecordingActor, PerformanceRecordingFront } = require("devtools/server/actors/performance-recording");
 
 loader.lazyRequireGetter(this, "events", "sdk/event/core");
 loader.lazyRequireGetter(this, "extend", "sdk/util/object", true);
 
 loader.lazyRequireGetter(this, "PerformanceRecorder",
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -8,20 +8,20 @@ const {Cc, Ci} = require("chrome");
 const events = require("sdk/event/core");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {DebuggerServer} = require("devtools/server/main");
 const Services = require("Services");
 const promise = require("promise");
 const {isWindowIncluded} = require("devtools/shared/layout/utils");
 const specs = require("devtools/shared/specs/storage");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
 loader.lazyImporter(this, "Sqlite", "resource://gre/modules/Sqlite.jsm");
-loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm", "Task");
 
 var gTrackedMessageManager = new Map();
 
 // Maximum number of cookies/local storage key-value-pairs that can be sent
 // over the wire to the client in one request.
 const MAX_STORE_OBJECT_COUNT = 50;
 // Delay for the batch job that sends the accumulated update packets to the
 // client (ms).
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -5,17 +5,17 @@
 "use strict";
 
 const {Cc, Ci} = require("chrome");
 const promise = require("promise");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {getDefinedGeometryProperties} = require("devtools/server/actors/highlighters/geometry-editor");
 const {parseDeclarations} = require("devtools/client/shared/css-parsing-utils");
-const {Task} = require("resource://gre/modules/Task.jsm");
+const {Task} = require("devtools/shared/task");
 const events = require("sdk/event/core");
 
 // This will also add the "stylesheet" actor type for protocol.js to recognize
 const {UPDATE_PRESERVING_RULES, UPDATE_GENERAL} = require("devtools/server/actors/stylesheets");
 const {pageStyleSpec, styleRuleSpec} = require("devtools/shared/specs/styles");
 
 loader.lazyRequireGetter(this, "CSS", "CSS");
 loader.lazyGetter(this, "CssLogic", () => require("devtools/shared/inspector/css-logic").CssLogic);
@@ -886,17 +886,17 @@ var PageStyleActor = protocol.ActorClass
     let rawNode = node.rawNode;
 
     let selector;
     if (rawNode.id) {
       selector = "#" + CSS.escape(rawNode.id);
     } else if (rawNode.className) {
       selector = "." + [...rawNode.classList].map(c => CSS.escape(c)).join(".");
     } else {
-      selector = rawNode.tagName.toLowerCase();
+      selector = rawNode.localName;
     }
 
     if (pseudoClasses && pseudoClasses.length > 0) {
       selector += pseudoClasses.join("");
     }
 
     let index = sheet.insertRule(selector + " {}", cssRules.length);
 
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -5,19 +5,19 @@
 "use strict";
 
 var { components, Cc, Ci, Cu } = require("chrome");
 var Services = require("Services");
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
 
 const promise = require("promise");
+const {Task} = require("devtools/shared/task");
 const events = require("sdk/event/core");
 const protocol = require("devtools/shared/protocol");
 const {Arg, Option, method, RetVal, types} = protocol;
 const {LongStringActor, ShortLongString} = require("devtools/server/actors/string");
 const {fetch} = require("devtools/shared/DevToolsUtils");
 const {listenOnce} = require("devtools/shared/async-utils");
 const {originalSourceSpec, mediaRuleSpec, styleSheetSpec,
        styleSheetsSpec} = require("devtools/shared/specs/stylesheets");
--- a/devtools/server/performance/profiler.js
+++ b/devtools/server/performance/profiler.js
@@ -5,17 +5,17 @@
 
 const { Cc, Ci, Cu } = require("chrome");
 const Services = require("Services");
 const { Class } = require("sdk/core/heritage");
 loader.lazyRequireGetter(this, "events", "sdk/event/core");
 loader.lazyRequireGetter(this, "EventTarget", "sdk/event/target", true);
 loader.lazyRequireGetter(this, "DevToolsUtils", "devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm", true);
-loader.lazyRequireGetter(this, "Task", "resource://gre/modules/Task.jsm", true);
+loader.lazyRequireGetter(this, "Task", "devtools/shared/task", true);
 
 // Events piped from system observers to Profiler instances.
 const PROFILER_SYSTEM_EVENTS = [
   "console-api-profiler",
   "profiler-started",
   "profiler-stopped"
 ];
 
--- a/devtools/server/performance/recorder.js
+++ b/devtools/server/performance/recorder.js
@@ -1,15 +1,15 @@
 /* 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 { Cc, Ci, Cu, Cr } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "Services");
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "extend",
   "sdk/util/object", true);
 loader.lazyRequireGetter(this, "Class",
   "sdk/core/heritage", true);
 loader.lazyRequireGetter(this, "EventTarget",
--- a/devtools/server/performance/timeline.js
+++ b/devtools/server/performance/timeline.js
@@ -20,17 +20,17 @@
  *   timeline.on("markers", function(markers) {...})
  */
 
 const { Ci, Cu } = require("chrome");
 const { Class } = require("sdk/core/heritage");
 // Be aggressive about lazy loading, as this will run on every
 // toolbox startup
 loader.lazyRequireGetter(this, "events", "sdk/event/core");
-loader.lazyRequireGetter(this, "Task", "resource://gre/modules/Task.jsm", true);
+loader.lazyRequireGetter(this, "Task", "devtools/shared/task", true);
 loader.lazyRequireGetter(this, "Memory", "devtools/server/performance/memory", true);
 loader.lazyRequireGetter(this, "Framerate", "devtools/server/performance/framerate", true);
 loader.lazyRequireGetter(this, "StackFrameCache", "devtools/server/actors/utils/stack", true);
 loader.lazyRequireGetter(this, "EventTarget", "sdk/event/target", true);
 
 // How often do we pull markers from the docShells, and therefore, how often do
 // we send events to the front (knowing that when there are no markers in the
 // docShell, no event is sent).
--- a/devtools/server/tests/mochitest/director-helpers.js
+++ b/devtools/server/tests/mochitest/director-helpers.js
@@ -13,17 +13,17 @@ SimpleTest.registerCleanupFunction(funct
   Services.prefs.clearUserPref("dom.mozBrowserFramesEnabled");
 });
 
 const { DirectorRegistry,
         DirectorRegistryFront } = require("devtools/server/actors/director-registry");
 
 const { DirectorManagerFront } = require("devtools/server/actors/director-manager");
 
-const {Task} = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 /** *********************************
  *  director helpers functions
  **********************************/
 
 function* newConnectedDebuggerClient(opts) {
   var transport = DebuggerServer.connectPipe();
   var client = new DebuggerClient(transport);
--- a/devtools/server/tests/mochitest/inspector-helpers.js
+++ b/devtools/server/tests/mochitest/inspector-helpers.js
@@ -1,14 +1,14 @@
 var Cu = Components.utils;
 
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const {DebuggerClient} = require("devtools/shared/client/main");
 const {DebuggerServer} = require("devtools/server/main");
-Cu.import("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 const Services = require("Services");
 const promise = require("promise");
 const {_documentWalker} = require("devtools/server/actors/inspector");
 
 // Always log packets when running tests.
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 SimpleTest.registerCleanupFunction(function () {
--- a/devtools/server/tests/mochitest/memory-helpers.js
+++ b/devtools/server/tests/mochitest/memory-helpers.js
@@ -1,14 +1,14 @@
 var Cu = Components.utils;
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 
-Cu.import("resource://gre/modules/Task.jsm");
 var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
+const { Task } = require("devtools/shared/task");
 var Services = require("Services");
 var { DebuggerClient } = require("devtools/shared/client/main");
 var { DebuggerServer } = require("devtools/server/main");
 
 var { MemoryFront } = require("devtools/server/actors/memory");
 
 // Always log packets when running tests.
 Services.prefs.setBoolPref("devtools.debugger.log", true);
--- a/devtools/server/tests/mochitest/memprof-helpers.js
+++ b/devtools/server/tests/mochitest/memprof-helpers.js
@@ -1,20 +1,20 @@
 var Cu = Components.utils;
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 
-var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
 var { require } =
   Cu.import("resource://devtools/shared/Loader.jsm", {});
 
 var Services = require("Services");
 var { DebuggerClient } = require("devtools/shared/client/main");
 var { DebuggerServer } = require("devtools/server/main");
 var { MemprofFront } = require("devtools/server/actors/memprof");
+var { Task } = require("devtools/shared/task");
 
 // Always log packets when running tests.
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 SimpleTest.registerCleanupFunction(function () {
   Services.prefs.clearUserPref("devtools.debugger.log");
 });
 
 function startServerAndGetSelectedTabMemprof() {
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -6,17 +6,17 @@ var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 var CC = Components.Constructor;
 
 const { require, loader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const { worker } = Cu.import("resource://devtools/shared/worker/loader.js", {});
 const promise = require("promise");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 
 const Services = require("Services");
 // Always log packets when running tests. runxpcshelltests.py will throw
 // the output away anyway, unless you give it the --verbose flag.
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 // Enable remote debugging for the relevant tests.
 Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
 
--- a/devtools/shared/async-utils.js
+++ b/devtools/shared/async-utils.js
@@ -9,17 +9,17 @@
  * run by Tasks. An async function returns a Promise for the resolution of the
  * function. When the function returns, the promise is resolved with the
  * returned value. If it throws the promise rejects with the thrown error.
  *
  * See Task documentation at https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Task.jsm.
  */
 
 var {Cu} = require("chrome");
-var {Task} = require("resource://gre/modules/Task.jsm");
+var {Task} = require("devtools/shared/task");
 var Promise = require("promise");
 
 /**
  * Create an async function that only executes once per instance of an object.
  * Once called on a given object, the same promise will be returned for any
  * future calls for that object.
  *
  * @param Function func
--- a/devtools/shared/client/connection-manager.js
+++ b/devtools/shared/client/connection-manager.js
@@ -7,19 +7,17 @@
 "use strict";
 
 const {Cc, Ci, Cu, Cr} = require("chrome");
 const EventEmitter = require("devtools/shared/event-emitter");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { DebuggerServer } = require("devtools/server/main");
 const { DebuggerClient } = require("devtools/shared/client/main");
 const Services = require("Services");
-
-DevToolsUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 const REMOTE_TIMEOUT = "devtools.debugger.remote-timeout";
 
 /**
  * Connection Manager.
  *
  * To use this module:
  * const {ConnectionManager} = require("devtools/shared/client/connection-manager");
--- a/devtools/shared/fronts/inspector.js
+++ b/devtools/shared/fronts/inspector.js
@@ -18,17 +18,17 @@ const {
 const { makeInfallible } = require("devtools/shared/DevToolsUtils");
 const {
   inspectorSpec,
   nodeSpec,
   nodeListSpec,
   walkerSpec
 } = require("devtools/shared/specs/inspector");
 const promise = require("promise");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { Class } = require("sdk/core/heritage");
 const events = require("sdk/event/core");
 const object = require("sdk/util/object");
 
 const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
 
 /**
  * Convenience API for building a list of attribute modifications
@@ -205,16 +205,22 @@ const NodeFront = FrontClassWithSpec(nod
     return this._form.nodeType;
   },
   get namespaceURI() {
     return this._form.namespaceURI;
   },
   get nodeName() {
     return this._form.nodeName;
   },
+  get displayName() {
+    let {displayName, nodeName} = this._form;
+
+    // Keep `nodeName.toLowerCase()` for backward compatibility
+    return displayName || nodeName.toLowerCase();
+  },
   get doctypeString() {
     return "<!DOCTYPE " + this._form.name +
      (this._form.publicId ? " PUBLIC \"" + this._form.publicId + "\"" : "") +
      (this._form.systemId ? " \"" + this._form.systemId + "\"" : "") +
      ">";
   },
 
   get baseURI() {
--- a/devtools/shared/fronts/styles.js
+++ b/devtools/shared/fronts/styles.js
@@ -10,17 +10,17 @@ const {
   custom,
   preEvent
 } = require("devtools/shared/protocol");
 const {
   pageStyleSpec,
   styleRuleSpec
 } = require("devtools/shared/specs/styles");
 const promise = require("promise");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const { Class } = require("sdk/core/heritage");
 
 loader.lazyGetter(this, "RuleRewriter", () => {
   return require("devtools/client/shared/css-parsing-utils").RuleRewriter;
 });
 
 /**
  * PageStyleFront, the front object for the PageStyleActor
--- a/devtools/shared/fronts/stylesheets.js
+++ b/devtools/shared/fronts/stylesheets.js
@@ -10,17 +10,17 @@ const {
 } = require("devtools/shared/indentation");
 const {
   originalSourceSpec,
   mediaRuleSpec,
   styleSheetSpec,
   styleSheetsSpec
 } = require("devtools/shared/specs/stylesheets");
 const promise = require("promise");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 const events = require("sdk/event/core");
 
 /**
  * The client-side counterpart for an OriginalSourceActor.
  */
 const OriginalSourceFront = FrontClassWithSpec(originalSourceSpec, {
   initialize: function (client, form) {
     Front.prototype.initialize.call(this, client, form);
--- a/devtools/shared/gcli/commands/screenshot.js
+++ b/devtools/shared/gcli/commands/screenshot.js
@@ -5,19 +5,19 @@
 "use strict";
 
 const { Cc, Ci, Cr } = require("chrome");
 const l10n = require("gcli/l10n");
 const Services = require("Services");
 const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
 const { getRect } = require("devtools/shared/layout/utils");
 const promise = require("promise");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyImporter(this, "Downloads", "resource://gre/modules/Downloads.jsm");
-loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm");
 loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
 loader.lazyImporter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
 loader.lazyImporter(this, "PrivateBrowsingUtils",
                           "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
                            .getService(Ci.nsIStringBundleService)
                            .createBundle("chrome://branding/locale/brand.properties")
--- a/devtools/shared/gcli/source/lib/gcli/util/host.js
+++ b/devtools/shared/gcli/source/lib/gcli/util/host.js
@@ -15,17 +15,17 @@
  */
 
 'use strict';
 
 var Cc = require('chrome').Cc;
 var Ci = require('chrome').Ci;
 var URL = require('sdk/url').URL;
 
-var Task = require('resource://gre/modules/Task.jsm').Task;
+var { Task } = require("devtools/shared/task");
 
 var util = require('./util');
 
 function Highlighter(document) {
   this._document = document;
   this._nodes = util.createEmptyNodeList(this._document);
 }
 
--- a/devtools/shared/heapsnapshot/tests/unit/head_heapsnapshot.js
+++ b/devtools/shared/heapsnapshot/tests/unit/head_heapsnapshot.js
@@ -9,17 +9,17 @@ var Cu = Components.utils;
 var Cr = Components.results;
 var CC = Components.Constructor;
 
 const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const { Match } = Cu.import("resource://test/Match.jsm", {});
 const { Census } = Cu.import("resource://test/Census.jsm", {});
 const { addDebuggerToGlobal } =
   Cu.import("resource://gre/modules/jsdebugger.jsm", {});
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const HeapAnalysesClient =
   require("devtools/shared/heapsnapshot/HeapAnalysesClient");
 const Services = require("Services");
 const { censusReportToCensusTreeNode } = require("devtools/shared/heapsnapshot/census-tree-node");
 const CensusUtils = require("devtools/shared/heapsnapshot/CensusUtils");
 const DominatorTreeNode = require("devtools/shared/heapsnapshot/DominatorTreeNode");
--- a/devtools/shared/moz.build
+++ b/devtools/shared/moz.build
@@ -48,10 +48,11 @@ DevToolsModules(
     'event-emitter.js',
     'event-parsers.js',
     'indentation.js',
     'Loader.jsm',
     'Parser.jsm',
     'path.js',
     'protocol.js',
     'system.js',
+    'task.js',
     'ThreadSafeDevToolsUtils.js',
 )
--- a/devtools/shared/qrcode/tests/mochitest/test_decode.html
+++ b/devtools/shared/qrcode/tests/mochitest/test_decode.html
@@ -8,17 +8,17 @@ Test decoding a simple message
   <title>Test decoding a simple message</title>
 
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="application/javascript;version=1.8">
 window.onload = function() {
   const { utils: Cu } = Components;
   const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
-  const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+  const { Task } = require("devtools/shared/task");
   const promise = require("promise");
 
   const QR = require("devtools/shared/qrcode/index");
 
   SimpleTest.waitForExplicitFinish();
 
   const testImage =
     "data:image/gif;base64,R0lGODdhOgA6AIAAAAAAAP///ywAAAAAOgA6AAAC" +
--- a/devtools/shared/security/auth.js
+++ b/devtools/shared/security/auth.js
@@ -12,18 +12,17 @@ var promise = require("promise");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var { dumpn, dumpv } = DevToolsUtils;
 loader.lazyRequireGetter(this, "prompt",
   "devtools/shared/security/prompt");
 loader.lazyRequireGetter(this, "cert",
   "devtools/shared/security/cert");
 loader.lazyRequireGetter(this, "asyncStorage",
   "devtools/shared/async-storage");
-DevToolsUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 /**
  * A simple enum-like object with keys mirrored to values.
  * This makes comparison to a specfic value simpler without having to repeat and
  * mis-type the value.
  */
 function createEnum(obj) {
   for (let key in obj) {
--- a/devtools/shared/security/socket.js
+++ b/devtools/shared/security/socket.js
@@ -42,18 +42,17 @@ DevToolsUtils.defineLazyGetter(this, "ce
          .getService(Ci.nsICertOverrideService);
 });
 
 DevToolsUtils.defineLazyGetter(this, "nssErrorsService", () => {
   return Cc["@mozilla.org/nss_errors_service;1"]
          .getService(Ci.nsINSSErrorsService);
 });
 
-DevToolsUtils.defineLazyModuleGetter(this, "Task",
-  "resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 var DebuggerSocket = {};
 
 /**
  * Connects to a debugger server socket.
  *
  * @param host string
  *        The host name or IP address of the debugger server.
--- a/devtools/shared/security/tests/unit/head_dbg.js
+++ b/devtools/shared/security/tests/unit/head_dbg.js
@@ -6,17 +6,17 @@ var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 var CC = Components.Constructor;
 
 const { require } =
   Cu.import("resource://devtools/shared/Loader.jsm", {});
 const promise = require("promise");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 
 const Services = require("Services");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const xpcInspector = require("xpcInspector");
 const { DebuggerServer } = require("devtools/server/main");
 const { DebuggerClient } = require("devtools/shared/client/main");
 
 // We do not want to log packets by default, because in some tests,
--- a/devtools/shared/system.js
+++ b/devtools/shared/system.js
@@ -1,15 +1,15 @@
 /* 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 { Cc, Ci, Cu } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm");
+const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "Services");
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "OS", "resource://gre/modules/commonjs/node/os.js");
 loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
 loader.lazyRequireGetter(this, "AppConstants",
   "resource://gre/modules/AppConstants.jsm", true);
 loader.lazyGetter(this, "screenManager", () => {
copy from toolkit/modules/Task.jsm
copy to devtools/shared/task.js
--- a/toolkit/modules/Task.jsm
+++ b/devtools/shared/task.js
@@ -1,39 +1,40 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
 /* 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";
 
-this.EXPORTED_SYMBOLS = [
-  "Task"
-];
+/* eslint-disable spaced-comment */
+/* globals StopIteration */
 
 /**
  * This module implements a subset of "Task.js" <http://taskjs.org/>.
+ * It is a copy of toolkit/modules/Task.jsm.  Please try not to
+ * diverge the API here.
  *
  * Paraphrasing from the Task.js site, tasks make sequential, asynchronous
  * operations simple, using the power of JavaScript's "yield" operator.
  *
  * Tasks are built upon generator functions and promises, documented here:
  *
  * <https://developer.mozilla.org/en/JavaScript/Guide/Iterators_and_Generators>
  * <http://wiki.commonjs.org/wiki/Promises/A>
  *
  * The "Task.spawn" function takes a generator function and starts running it as
  * a task.  Every time the task yields a promise, it waits until the promise is
  * fulfilled.  "Task.spawn" returns a promise that is resolved when the task
  * completes successfully, or is rejected if an exception occurs.
  *
  * -----------------------------------------------------------------------------
  *
- * Cu.import("resource://gre/modules/Task.jsm");
+ * const {Task} = require("devtools/shared/task");
  *
  * Task.spawn(function* () {
  *
  *   // This is our task. Let's create a promise object, wait on it and capture
  *   // its resolution value.
  *   let myPromise = getPromiseResolvedOnTimeoutWithValue(1000, "Value");
  *   let result = yield myPromise;
  *
@@ -81,43 +82,34 @@ this.EXPORTED_SYMBOLS = [
  *   spawn a task from it, regardless of whether it is an asynchronous generator
  *   or a synchronous function.  This comes in handy when iterating over
  *   function lists where some items have been converted to tasks and some not.
  */
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Globals
 
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-// For now, we're worried about add-ons using Tasks with CPOWs, so we'll
-// permit them in this scope, but this support will go away soon.
-Cu.permitCPOWsInScope(this);
-
-Cu.import("resource://gre/modules/Promise.jsm");
+const Promise = require("promise");
 
 // The following error types are considered programmer errors, which should be
 // reported (possibly redundantly) so as to let programmers fix their code.
-const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"];
+const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError",
+                          "TypeError"];
 
 /**
  * The Task currently being executed
  */
 var gCurrentTask = null;
 
 /**
  * If `true`, capture stacks whenever entering a Task and rewrite the
  * stack any exception thrown through a Task.
  */
 var gMaintainStack = false;
 
-
 /**
  * Iterate through the lines of a string.
  *
  * @return Iterator<string>
  */
 function* linesOf(string) {
   let reLine = /([^\r\n])+/g;
   let match;
@@ -128,49 +120,49 @@ function* linesOf(string) {
 
 /**
  * Detect whether a value is a generator.
  *
  * @param aValue
  *        The value to identify.
  * @return A boolean indicating whether the value is a generator.
  */
-function isGenerator(aValue) {
-  return Object.prototype.toString.call(aValue) == "[object Generator]";
+function isGenerator(value) {
+  return Object.prototype.toString.call(value) == "[object Generator]";
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Task
 
 /**
  * This object provides the public module functions.
  */
 this.Task = {
   /**
    * Creates and starts a new task.
    *
-   * @param aTask
+   * @param task
    *        - If you specify a generator function, it is called with no
    *          arguments to retrieve the associated iterator.  The generator
    *          function is a task, that is can yield promise objects to wait
    *          upon.
    *        - If you specify the iterator returned by a generator function you
    *          called, the generator function is also executed as a task.  This
    *          allows you to call the function with arguments.
    *        - If you specify a function that is not a generator, it is called
    *          with no arguments, and its return value is used to resolve the
    *          returned promise.
    *        - If you specify anything else, you get a promise that is already
    *          resolved with the specified value.
    *
    * @return A promise object where you can register completion callbacks to be
    *         called when the task terminates.
    */
-  spawn: function Task_spawn(aTask) {
-    return createAsyncFunction(aTask).call(undefined);
+  spawn: function (task) {
+    return createAsyncFunction(task).call(undefined);
   },
 
   /**
    * Create and return an 'async function' that starts a new task.
    *
    * This is similar to 'spawn' except that it doesn't immediately start
    * the task, it binds the task to the async function's 'this' object and
    * arguments, and it requires the task to be a function.
@@ -196,56 +188,56 @@ this.Task = {
    *     return yield sendGreeting(this.message.replace(/NAME/, name));
    *   })
    * };
    *
    * While maintaining identical semantics:
    *
    * greeter.greet("Mitchell").then((reply) => { ... }); // behaves the same
    *
-   * @param aTask
+   * @param task
    *        The task function to start.
    *
    * @return A function that starts the task function and returns its promise.
    */
-  async: function Task_async(aTask) {
-    if (typeof(aTask) != "function") {
-      throw new TypeError("aTask argument must be a function");
+  async: function (task) {
+    if (typeof (task) != "function") {
+      throw new TypeError("task argument must be a function");
     }
 
-    return createAsyncFunction(aTask);
+    return createAsyncFunction(task);
   },
 
   /**
    * Constructs a special exception that, when thrown inside a legacy generator
    * function (non-star generator), allows the associated task to be resolved
    * with a specific value.
    *
    * Example: throw new Task.Result("Value");
    */
-  Result: function Task_Result(aValue) {
-    this.value = aValue;
+  Result: function (value) {
+    this.value = value;
   }
 };
 
-function createAsyncFunction(aTask) {
+function createAsyncFunction(task) {
   let asyncFunction = function () {
-    let result = aTask;
-    if (aTask && typeof(aTask) == "function") {
-      if (aTask.isAsyncFunction) {
+    let result = task;
+    if (task && typeof (task) == "function") {
+      if (task.isAsyncFunction) {
         throw new TypeError(
           "Cannot use an async function in place of a promise. " +
           "You should either invoke the async function first " +
           "or use 'Task.spawn' instead of 'Task.async' to start " +
           "the Task and return its promise.");
       }
 
       try {
         // Let's call into the function ourselves.
-        result = aTask.apply(this, arguments);
+        result = task.apply(this, arguments);
       } catch (ex) {
         if (ex instanceof Task.Result) {
           return Promise.resolve(ex.value);
         }
         return Promise.reject(ex);
       }
     }
 
@@ -295,55 +287,54 @@ TaskImpl.prototype = {
   /**
    * Whether this Task is using a star generator.
    */
   _isStarGenerator: false,
 
   /**
    * Main execution routine, that calls into the generator function.
    *
-   * @param aSendResolved
+   * @param sendResolved
    *        If true, indicates that we should continue into the generator
    *        function regularly (if we were waiting on a promise, it was
    *        resolved). If true, indicates that we should cause an exception to
    *        be thrown into the generator function (if we were waiting on a
    *        promise, it was rejected).
-   * @param aSendValue
+   * @param sendValue
    *        Resolution result or rejection exception, if any.
    */
-  _run: function TaskImpl_run(aSendResolved, aSendValue) {
-
+  _run: function (sendResolved, sendValue) {
     try {
       gCurrentTask = this;
 
       if (this._isStarGenerator) {
         try {
-          let result = aSendResolved ? this._iterator.next(aSendValue)
-                                     : this._iterator.throw(aSendValue);
+          let result = sendResolved ? this._iterator.next(sendValue)
+                                    : this._iterator.throw(sendValue);
 
           if (result.done) {
             // The generator function returned.
             this.deferred.resolve(result.value);
           } else {
             // The generator function yielded.
             this._handleResultValue(result.value);
           }
         } catch (ex) {
           // The generator function failed with an uncaught exception.
           this._handleException(ex);
         }
       } else {
         try {
-          let yielded = aSendResolved ? this._iterator.send(aSendValue)
-                                      : this._iterator.throw(aSendValue);
+          let yielded = sendResolved ? this._iterator.send(sendValue)
+                                     : this._iterator.throw(sendValue);
           this._handleResultValue(yielded);
         } catch (ex) {
           if (ex instanceof Task.Result) {
-            // The generator function threw the special exception that allows it to
-            // return a specific value on resolution.
+            // The generator function threw the special exception that
+            // allows it to return a specific value on resolution.
             this.deferred.resolve(ex.value);
           } else if (ex instanceof StopIteration) {
             // The generator function terminated with no specific result.
             this.deferred.resolve(undefined);
           } else {
             // The generator function failed with an uncaught exception.
             this._handleException(ex);
           }
@@ -372,107 +363,101 @@ TaskImpl.prototype = {
         gCurrentTask = null;
       }
     }
   },
 
   /**
    * Handle a value yielded by a generator.
    *
-   * @param aValue
+   * @param value
    *        The yielded value to handle.
    */
-  _handleResultValue: function TaskImpl_handleResultValue(aValue) {
+  _handleResultValue: function (value) {
     // If our task yielded an iterator resulting from calling another
     // generator function, automatically spawn a task from it, effectively
     // turning it into a promise that is fulfilled on task completion.
-    if (isGenerator(aValue)) {
-      aValue = Task.spawn(aValue);
+    if (isGenerator(value)) {
+      value = Task.spawn(value);
     }
 
-    if (aValue && typeof(aValue.then) == "function") {
+    if (value && typeof (value.then) == "function") {
       // We have a promise object now. When fulfilled, call again into this
       // function to continue the task, with either a resolution or rejection
       // condition.
-      aValue.then(this._run.bind(this, true),
+      value.then(this._run.bind(this, true),
                   this._run.bind(this, false));
     } else {
       // If our task yielded a value that is not a promise, just continue and
       // pass it directly as the result of the yield statement.
-      this._run(true, aValue);
+      this._run(true, value);
     }
   },
 
   /**
    * Handle an uncaught exception thrown from a generator.
    *
-   * @param aException
+   * @param exception
    *        The uncaught exception to handle.
    */
-  _handleException: function TaskImpl_handleException(aException) {
-
+  _handleException: function (exception) {
     gCurrentTask = this;
 
-    if (aException && typeof aException == "object" && "stack" in aException) {
-
-      let stack = aException.stack;
+    if (exception && typeof exception == "object" && "stack" in exception) {
+      let stack = exception.stack;
 
       if (gMaintainStack &&
-          aException._capturedTaskStack != this._stack &&
+          exception._capturedTaskStack != this._stack &&
           typeof stack == "string") {
-
         // Rewrite the stack for more readability.
 
         let bottomStack = this._stack;
-        let topStack = stack;
 
         stack = Task.Debugging.generateReadableStack(stack);
 
-        aException.stack = stack;
+        exception.stack = stack;
 
-        // If aException is reinjected in the same task and rethrown,
+        // If exception is reinjected in the same task and rethrown,
         // we don't want to perform the rewrite again.
-        aException._capturedTaskStack = bottomStack;
+        exception._capturedTaskStack = bottomStack;
       } else if (!stack) {
         stack = "Not available";
       }
 
-      if ("name" in aException &&
-          ERRORS_TO_REPORT.indexOf(aException.name) != -1) {
-
+      if ("name" in exception &&
+          ERRORS_TO_REPORT.indexOf(exception.name) != -1) {
         // We suspect that the exception is a programmer error, so we now
         // display it using dump().  Note that we do not use Cu.reportError as
         // we assume that this is a programming error, so we do not want end
         // users to see it. Also, if the programmer handles errors correctly,
         // they will either treat the error or log them somewhere.
 
         dump("*************************\n");
         dump("A coding exception was thrown and uncaught in a Task.\n\n");
-        dump("Full message: " + aException + "\n");
-        dump("Full stack: " + aException.stack + "\n");
+        dump("Full message: " + exception + "\n");
+        dump("Full stack: " + exception.stack + "\n");
         dump("*************************\n");
       }
     }
 
-    this.deferred.reject(aException);
+    this.deferred.reject(exception);
   },
 
   get callerStack() {
     // Cut `this._stack` at the last line of the first block that
-    // contains Task.jsm, keep the tail.
+    // contains task.js, keep the tail.
     for (let [line, index] of linesOf(this._stack || "")) {
-      if (line.indexOf("/Task.jsm:") == -1) {
+      if (line.indexOf("/task.js:") == -1) {
         return this._stack.substring(index);
       }
     }
     return "";
   }
 };
 
-
 Task.Debugging = {
 
   /**
    * Control stack rewriting.
    *
    * If `true`, any exception thrown from a Task will be rewritten to
    * provide a human-readable stack trace. Otherwise, stack traces will
    * be left unchanged.
@@ -485,42 +470,45 @@ Task.Debugging = {
    */
   get maintainStack() {
     return gMaintainStack;
   },
   set maintainStack(x) {
     if (!x) {
       gCurrentTask = null;
     }
-    return gMaintainStack = x;
+    gMaintainStack = x;
+    return x;
   },
 
   /**
    * Generate a human-readable stack for an error raised in
    * a Task.
    *
    * @param {string} topStack The stack provided by the error.
    * @param {string=} prefix Optionally, a prefix for each line.
    */
-  generateReadableStack: function(topStack, prefix = "") {
+  generateReadableStack: function (topStack, prefix = "") {
     if (!gCurrentTask) {
       return topStack;
     }
 
-    // Cut `topStack` at the first line that contains Task.jsm, keep the head.
+    // Cut `topStack` at the first line that contains task.js, keep the head.
     let lines = [];
     for (let [line] of linesOf(topStack)) {
-      if (line.indexOf("/Task.jsm:") != -1) {
+      if (line.indexOf("/task.js:") != -1) {
         break;
       }
       lines.push(prefix + line);
     }
     if (!prefix) {
       lines.push(gCurrentTask.callerStack);
     } else {
       for (let [line] of linesOf(gCurrentTask.callerStack)) {
         lines.push(prefix + line);
       }
     }
 
     return lines.join("\n");
   }
 };
+
+exports.Task = Task;
--- a/devtools/shared/tests/mochitest/test_eventemitter_basic.html
+++ b/devtools/shared/tests/mochitest/test_eventemitter_basic.html
@@ -21,17 +21,17 @@
     <script type="application/javascript;version=1.8">
       "use strict";
 
       const { utils: Cu } = Components;
       const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
       const promise = require("promise");
       const { EventEmitter } =
         Cu.import("resource://devtools/shared/event-emitter.js", {});
-      const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+      const { Task } = require("devtools/shared/task");
 
       SimpleTest.waitForExplicitFinish();
 
       testEmitter();
       testEmitter({});
 
       Task.spawn(testPromise)
           .then(null, ok.bind(null, false))
--- a/devtools/shared/tests/unit/test_async-utils.js
+++ b/devtools/shared/tests/unit/test_async-utils.js
@@ -1,15 +1,15 @@
 /* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test async-utils.js
 
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+const {Task} = require("devtools/shared/task");
 // |const| will not work because
 // it will make the Promise object immutable before assigning.
 // Using Object.defineProperty() instead.
 Object.defineProperty(this, "Promise", {
   value: require("promise"),
   writable: false, configurable: false
 });
 const {asyncOnce, promiseInvoke, promiseCall} = require("devtools/shared/async-utils");
--- a/devtools/shared/transport/tests/unit/head_dbg.js
+++ b/devtools/shared/transport/tests/unit/head_dbg.js
@@ -6,17 +6,17 @@ var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 var CC = Components.Constructor;
 
 const { require } =
   Cu.import("resource://devtools/shared/Loader.jsm", {});
 const promise = require("promise");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+const { Task } = require("devtools/shared/task");
 
 const Services = require("Services");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 
 // We do not want to log packets by default, because in some tests,
 // we can be sending large amounts of data. The test harness has
 // trouble dealing with logging all the data, and we end up with
 // intermittent time outs (e.g. bug 775924).
--- a/devtools/shared/webconsole/test/common.js
+++ b/devtools/shared/webconsole/test/common.js
@@ -5,24 +5,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 
-const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
-
 // This gives logging to stdout for tests
 var {console} = Cu.import("resource://gre/modules/Console.jsm", {});
 
 var {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var Services = require("Services");
 var WebConsoleUtils = require("devtools/shared/webconsole/utils").Utils;
+var {Task} = require("devtools/shared/task");
 
 var ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
                           .getService(Ci.nsIConsoleAPIStorage);
 var {DebuggerServer} = require("devtools/server/main");
 var {DebuggerClient, ObjectClient} = require("devtools/shared/client/main");
 
 var {ConsoleServiceListener, ConsoleAPIListener} =
   require("devtools/shared/webconsole/utils");
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -312,17 +312,17 @@ public class BrowserApp extends GeckoApp
             (BrowserAppDelegate) new AddToHomeScreenPromotion(),
             (BrowserAppDelegate) new ScreenshotDelegate(),
             (BrowserAppDelegate) new BookmarkStateChangeDelegate(),
             (BrowserAppDelegate) new ReaderViewBookmarkPromotion(),
             (BrowserAppDelegate) new ContentNotificationsDelegate()
     ));
 
     @NonNull
-    private SearchEngineManager searchEngineManager; // Contains reference to Context - DO NOT LEAK!
+    private SearchEngineManager mSearchEngineManager; // Contains reference to Context - DO NOT LEAK!
 
     private TelemetryDispatcher mTelemetryDispatcher;
     private final SessionMeasurements mSessionMeasurements = new SessionMeasurements();
 
     private boolean mHasResumed;
 
     @Override
     public View onCreateView(final String name, final Context context, final AttributeSet attrs) {
@@ -697,17 +697,17 @@ public class BrowserApp extends GeckoApp
 
         final GeckoProfile profile = getProfile();
 
         // We want to upload the telemetry core ping as soon after startup as possible. It relies on the
         // Distribution being initialized. If you move this initialization, ensure it plays well with telemetry.
         final Distribution distribution = Distribution.init(this);
         distribution.addOnDistributionReadyCallback(new DistributionStoreCallback(this, profile.getName()));
 
-        searchEngineManager = new SearchEngineManager(this, distribution);
+        mSearchEngineManager = new SearchEngineManager(this, distribution);
         mTelemetryDispatcher = new TelemetryDispatcher(profile.getDir().getAbsolutePath());
 
         // Init suggested sites engine in BrowserDB.
         final SuggestedSites suggestedSites = new SuggestedSites(appContext, distribution);
         final BrowserDB db = profile.getDB();
         db.setSuggestedSites(suggestedSites);
 
         JavaAddonManager.getInstance().init(appContext);
@@ -1087,17 +1087,17 @@ public class BrowserApp extends GeckoApp
 
         // We don't upload in onCreate because that's only called when the Activity needs to be instantiated
         // and it's possible the system will never free the Activity from memory.
         //
         // We don't upload in onResume/onPause because that will be called each time the Activity is obscured,
         // including by our own Activities/dialogs, and there is no reason to upload each time we're unobscured.
         //
         // So we're left with onStart/onStop.
-        searchEngineManager.getEngine(new UploadTelemetryCorePingCallback(BrowserApp.this));
+        mSearchEngineManager.getEngine(new UploadTelemetryCorePingCallback(BrowserApp.this));
 
         for (final BrowserAppDelegate delegate : delegates) {
             delegate.onStart(this);
         }
     }
 
     @Override
     public void onStop() {
@@ -1388,17 +1388,17 @@ public class BrowserApp extends GeckoApp
             mAccountsHelper.uninit();
             mAccountsHelper = null;
         }
 
         if (mZoomedView != null) {
             mZoomedView.destroy();
         }
 
-        searchEngineManager.unregisterListeners();
+        mSearchEngineManager.unregisterListeners();
 
         EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
             "Gecko:DelayedStartup",
             "Menu:Open",
             "Menu:Update",
             "LightweightTheme:Update",
             "Search:Keyword",
             "Prompt:ShowTop");