Bug 1273941 - replace uses of promise.defer in devtools/client/framework; r=jryans
authorTom Tromey <tom@tromey.com>
Thu, 09 Jun 2016 09:04:58 -0600
changeset 302531 65a02c905ec6c6265944085e4dcf72b8184ba029
parent 302530 c93918e6463ac250d76f11f0e93aa76d9f740237
child 302532 be8fdffc3665b30242dbe639818f19ed320455ad
push id30364
push userkwierso@gmail.com
push dateFri, 24 Jun 2016 20:31:56 +0000
treeherdermozilla-central@9dac1358aaad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1273941
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1273941 - replace uses of promise.defer in devtools/client/framework; r=jryans MozReview-Commit-ID: GwgbcXOmvtK
devtools/client/framework/attach-thread.js
devtools/client/framework/devtools-browser.js
devtools/client/framework/devtools.js
devtools/client/framework/target.js
devtools/client/framework/test/browser_devtools_api.js
devtools/client/framework/test/browser_devtools_api_destroy.js
devtools/client/framework/test/browser_source-location-02.js
devtools/client/framework/test/browser_toolbox_options.js
devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
devtools/client/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js
devtools/client/framework/test/browser_toolbox_sidebar.js
devtools/client/framework/test/browser_toolbox_sidebar_events.js
devtools/client/framework/test/browser_toolbox_tool_remote_reopen.js
devtools/client/framework/test/browser_toolbox_window_title_changes.js
devtools/client/framework/test/head.js
devtools/client/framework/test/helper_disable_cache.js
devtools/client/framework/test/shared-head.js
devtools/client/framework/test/shared-redux-head.js
devtools/client/framework/toolbox-hosts.js
devtools/client/framework/toolbox-options.js
devtools/client/framework/toolbox.js
devtools/client/memory/test/unit/head.js
--- a/devtools/client/framework/attach-thread.js
+++ b/devtools/client/framework/attach-thread.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/. */
 
 const {Cc, Ci, Cu} = require("chrome");
 const Services = require("Services");
-const promise = require("promise");
+const defer = require("devtools/shared/defer");
 
 function l10n(name) {
   const bundle = Services.strings.createBundle("chrome://devtools/locale/toolbox.properties");
   try {
     return bundle.GetStringFromName(name);
   } catch (e) {
     throw new Error("Failed loading l10n string: " + name);
   }
@@ -37,17 +37,17 @@ function handleThreadState(toolbox, even
       toolbox.selectTool("jsdebugger");
     }
   } else if (event === "resumed") {
     toolbox.unhighlightTool("jsdebugger");
   }
 }
 
 function attachThread(toolbox) {
-  let deferred = promise.defer();
+  let deferred = defer();
 
   let target = toolbox.target;
   let { form: { chromeDebugger, actor } } = target;
   let threadOptions = {
     useSourceMaps: Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled"),
     autoBlackBox: Services.prefs.getBoolPref("devtools.debugger.auto-black-box")
   };
 
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -10,16 +10,17 @@
  *
  * This module is loaded lazily by devtools-clhandler.js, once the first
  * browser window is ready (i.e. fired browser-delayed-startup-finished event)
  **/
 
 const {Cc, Ci, Cu} = require("chrome");
 const Services = require("Services");
 const promise = require("promise");
+const defer = require("devtools/shared/defer");
 const Telemetry = require("devtools/client/shared/telemetry");
 const { gDevTools } = require("./devtools");
 const { when: unload } = require("sdk/system/unload");
 
 // Load target and toolbox lazily as they need gDevTools to be fully initialized
 loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
 loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true);
 loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
@@ -232,17 +233,17 @@ var gDevToolsBrowser = exports.gDevTools
       DebuggerServer.init();
       DebuggerServer.addBrowserActors();
     }
     DebuggerServer.allowChromeProcess = true;
 
     let transport = DebuggerServer.connectPipe();
     let client = new DebuggerClient(transport);
 
-    let deferred = promise.defer();
+    let deferred = defer();
     client.connect().then(() => {
       client.mainRoot.listProcesses(response => {
         // Do nothing if there is only one process, the parent process.
         let contentProcesses = response.processes.filter(p => (!p.parent));
         if (contentProcesses.length < 1) {
           let msg = bundle.GetStringFromName("toolbox.noContentProcess.message");
           Services.prompt.alert(null, "", msg);
           deferred.reject("No content processes available.");
@@ -369,17 +370,17 @@ var gDevToolsBrowser = exports.gDevTools
   isWebIDEWidgetInstalled: function () {
     let widgetWrapper = CustomizableUI.getWidget("webide-button");
     return !!(widgetWrapper && widgetWrapper.provider == CustomizableUI.PROVIDER_API);
   },
 
   /**
    * The deferred promise will be resolved by WebIDE's UI.init()
    */
-  isWebIDEInitialized: promise.defer(),
+  isWebIDEInitialized: defer(),
 
   /**
    * Uninstall WebIDE widget
    */
   uninstallWebIDEWidget: function () {
     if (this.isWebIDEWidgetInstalled()) {
       CustomizableUI.removeWidgetFromArea("webide-button");
     }
--- a/devtools/client/framework/devtools.js
+++ b/devtools/client/framework/devtools.js
@@ -1,16 +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 Services = require("Services");
 const promise = require("promise");
+const defer = require("devtools/shared/defer");
 
 // Load gDevToolsBrowser toolbox lazily as they need gDevTools to be fully initialized
 loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true);
 loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true);
 
 const {defaultTools: DefaultTools, defaultThemes: DefaultThemes} =
   require("devtools/client/definitions");
 const EventEmitter = require("devtools/shared/event-emitter");
@@ -388,17 +389,17 @@ DevTools.prototype = {
    *        The type of host (bottom, window, side)
    * @param {object} hostOptions
    *        Options for host specifically
    *
    * @return {Toolbox} toolbox
    *        The toolbox that was opened
    */
   showToolbox: function (target, toolId, hostType, hostOptions) {
-    let deferred = promise.defer();
+    let deferred = defer();
 
     let toolbox = this._toolboxes.get(target);
     if (toolbox) {
 
       let hostPromise = (hostType != null && toolbox.hostType != hostType) ?
           toolbox.switchHost(hostType) :
           promise.resolve(null);
 
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -1,16 +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 { Ci } = require("chrome");
 const promise = require("promise");
+const defer = require("devtools/shared/defer");
 const EventEmitter = require("devtools/shared/event-emitter");
 const Services = require("Services");
 const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
 
 loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/main", true);
 
@@ -182,17 +183,17 @@ TabTarget.prototype = {
    * }
    */
   getActorDescription: function (actorName) {
     if (!this.client) {
       throw new Error("TabTarget#getActorDescription() can only be called on " +
                       "remote tabs.");
     }
 
-    let deferred = promise.defer();
+    let deferred = defer();
 
     if (this._protocolDescription &&
         this._protocolDescription.types[actorName]) {
       deferred.resolve(this._protocolDescription.types[actorName]);
     } else {
       this.client.mainRoot.protocolDescription(description => {
         this._protocolDescription = description;
         deferred.resolve(description.types[actorName]);
@@ -364,17 +365,17 @@ TabTarget.prototype = {
    * for tools that support the Remote Debugging Protocol even for local
    * connections.
    */
   makeRemote: function () {
     if (this._remote) {
       return this._remote.promise;
     }
 
-    this._remote = promise.defer();
+    this._remote = defer();
 
     if (this.isLocalTab) {
       // Since a remote protocol connection will be made, let's start the
       // DebuggerServer here, once and for all tools.
       if (!DebuggerServer.initialized) {
         DebuggerServer.init();
         DebuggerServer.addBrowserActors();
       }
@@ -548,17 +549,17 @@ TabTarget.prototype = {
    */
   destroy: function () {
     // If several things call destroy then we give them all the same
     // destruction promise so we're sure to destroy only once
     if (this._destroyer) {
       return this._destroyer.promise;
     }
 
-    this._destroyer = promise.defer();
+    this._destroyer = defer();
 
     // Before taking any action, notify listeners that destruction is imminent.
     this.emit("close");
 
     if (this._tab) {
       this._teardownListeners();
     }
 
@@ -617,17 +618,17 @@ TabTarget.prototype = {
     let id = this._tab ? this._tab : (this._form && this._form.actor);
     return `TabTarget:${id}`;
   },
 
   /**
    * @see TabActor.prototype.onResolveLocation
    */
   resolveLocation(loc) {
-    let deferred = promise.defer();
+    let deferred = defer();
 
     this.client.request(Object.assign({
       to: this._form.actor,
       type: "resolveLocation",
     }, loc), deferred.resolve);
 
     return deferred.promise;
   },
--- a/devtools/client/framework/test/browser_devtools_api.js
+++ b/devtools/client/framework/test/browser_devtools_api.js
@@ -232,17 +232,17 @@ function DevToolPanel(iframeWindow, tool
   let textNode = doc.createTextNode("Some Tool");
 
   label.appendChild(textNode);
   doc.body.appendChild(label);*/
 }
 
 DevToolPanel.prototype = {
   open: function () {
-    let deferred = promise.defer();
+    let deferred = defer();
 
     executeSoon(() => {
       this._isReady = true;
       this.emit("ready");
       deferred.resolve(this);
     });
 
     return deferred.promise;
@@ -258,11 +258,11 @@ DevToolPanel.prototype = {
 
   get isReady() {
     return this._isReady;
   },
 
   _isReady: false,
 
   destroy: function DTI_destroy() {
-    return promise.defer(null);
+    return defer(null);
   },
 };
--- a/devtools/client/framework/test/browser_devtools_api_destroy.js
+++ b/devtools/client/framework/test/browser_devtools_api_destroy.js
@@ -12,17 +12,17 @@ function test() {
 function runTests(aTab) {
   let toolDefinition = {
     id: "testTool",
     visibilityswitch: "devtools.testTool.enabled",
     isTargetSupported: () => true,
     url: "about:blank",
     label: "someLabel",
     build: function (iframeWindow, toolbox) {
-      let deferred = promise.defer();
+      let deferred = defer();
       executeSoon(() => {
         deferred.resolve({
           target: toolbox.target,
           toolbox: toolbox,
           isReady: true,
           destroy: function () {},
         });
       });
--- a/devtools/client/framework/test/browser_source-location-02.js
+++ b/devtools/client/framework/test/browser_source-location-02.js
@@ -85,17 +85,17 @@ function createScript(url) {
     script.setAttribute("src", "${url}");
     document.body.appendChild(script);
   `;
   return evalInDebuggee(mm, command);
 }
 
 function waitForSourceShown(debuggerPanel, url) {
   let { panelWin } = debuggerPanel;
-  let deferred = promise.defer();
+  let deferred = defer();
 
   info(`Waiting for source ${url} to be shown in the debugger...`);
   panelWin.on(panelWin.EVENTS.SOURCE_SHOWN, function onSourceShown(_, source) {
     let sourceUrl = source.url || source.introductionUrl;
 
     if (sourceUrl.includes(url)) {
       panelWin.off(panelWin.EVENTS.SOURCE_SHOWN, onSourceShown);
       info(`Source shown for ${url}`);
--- a/devtools/client/framework/test/browser_toolbox_options.js
+++ b/devtools/client/framework/test/browser_toolbox_options.js
@@ -111,17 +111,17 @@ function* testSelect(select) {
   is(select.options[select.selectedIndex].value, GetPref(pref),
     "select starts out selected");
 
   for (let option of options) {
     if (options.indexOf(option) === select.selectedIndex) {
       continue;
     }
 
-    let deferred = promise.defer();
+    let deferred = defer();
     gDevTools.once("pref-changed", (event, data) => {
       if (data.pref == pref) {
         ok(true, "Correct pref was changed");
         is(GetPref(pref), option.value, "Preference been switched for " + pref);
       } else {
         ok(false, "Pref " + pref + " was not changed correctly");
       }
       deferred.resolve();
@@ -131,17 +131,17 @@ function* testSelect(select) {
     let changeEvent = new Event("change");
     select.dispatchEvent(changeEvent);
 
     yield deferred.promise;
   }
 }
 
 function* testMouseClick(node, prefValue) {
-  let deferred = promise.defer();
+  let deferred = defer();
 
   let pref = node.getAttribute("data-pref");
   gDevTools.once("pref-changed", (event, data) => {
     if (data.pref == pref) {
       ok(true, "Correct pref was changed");
       is(data.oldValue, prefValue, "Previous value is correct for " + pref);
       is(data.newValue, !prefValue, "New value is correct for " + pref);
     } else {
@@ -213,17 +213,17 @@ function* testToggleTools() {
   yield toggleTool(firstTool);
   yield toggleTool(middleTool);
   yield toggleTool(middleTool);
   yield toggleTool(lastTool);
   yield toggleTool(lastTool);
 }
 
 function* toggleTool(node) {
-  let deferred = promise.defer();
+  let deferred = defer();
 
   let toolId = node.getAttribute("id");
   if (node.checked) {
     gDevTools.once("tool-unregistered",
       checkUnregistered.bind(null, toolId, deferred));
   } else {
     gDevTools.once("tool-registered",
       checkRegistered.bind(null, toolId, deferred));
--- a/devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
@@ -21,17 +21,17 @@ function test() {
       .then(cleanup, errorHandler);
   }, true);
 
   content.location = "data:text/html;charset=utf8,test for dynamically " +
                      "registering and unregistering tools";
 }
 
 function testPrefsAreRespectedWhenReopeningToolbox() {
-  let deferred = promise.defer();
+  let deferred = defer();
   let target = TargetFactory.forTab(gBrowser.selectedTab);
 
   info("Closing toolbox to test after reopening");
   gDevTools.closeToolbox(target).then(() => {
     let tabTarget = TargetFactory.forTab(gBrowser.selectedTab);
     gDevTools.showToolbox(tabTarget)
       .then(testSelectTool)
       .then(() => {
@@ -40,17 +40,17 @@ function testPrefsAreRespectedWhenReopen
         deferred.resolve();
       });
   });
 
   return deferred.promise;
 }
 
 function testSelectTool(devtoolsToolbox) {
-  let deferred = promise.defer();
+  let deferred = defer();
   info("Selecting the options panel");
 
   toolbox = devtoolsToolbox;
   doc = toolbox.doc;
   toolbox.once("options-selected", (event, tool) => {
     ok(true, "Options panel selected via selectTool method");
     panelWin = tool.panelWin;
     deferred.resolve();
--- a/devtools/client/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js
+++ b/devtools/client/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js
@@ -82,17 +82,17 @@ function toggleServiceWorkersTestingChec
   }
 
   cbx.click();
 
   return promise.resolve();
 }
 
 function reload() {
-  let deferred = promise.defer();
+  let deferred = defer();
 
   gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
     gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
     deferred.resolve();
   }, true);
 
   executeInContent("devtools:test:reload", {}, {}, false);
   return deferred.promise;
--- a/devtools/client/framework/test/browser_toolbox_sidebar.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar.js
@@ -25,17 +25,17 @@ function test() {
 
   let toolDefinition = {
     id: "fakeTool4242",
     visibilityswitch: "devtools.fakeTool4242.enabled",
     url: toolURL,
     label: "FAKE TOOL!!!",
     isTargetSupported: () => true,
     build: function (iframeWindow, toolbox) {
-      let deferred = promise.defer();
+      let deferred = defer();
       executeSoon(() => {
         deferred.resolve({
           target: toolbox.target,
           toolbox: toolbox,
           isReady: true,
           destroy: function () {},
           panelDoc: iframeWindow.document,
         });
--- a/devtools/client/framework/test/browser_toolbox_sidebar_events.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar_events.js
@@ -20,17 +20,17 @@ function test() {
 
   let toolDefinition = {
     id: "testTool1072208",
     visibilityswitch: "devtools.testTool1072208.enabled",
     url: toolURL,
     label: "Test tool",
     isTargetSupported: () => true,
     build: function (iframeWindow, toolbox) {
-      let deferred = promise.defer();
+      let deferred = defer();
       executeSoon(() => {
         deferred.resolve({
           target: toolbox.target,
           toolbox: toolbox,
           isReady: true,
           destroy: function () {},
           panelDoc: iframeWindow.document,
         });
--- a/devtools/client/framework/test/browser_toolbox_tool_remote_reopen.js
+++ b/devtools/client/framework/test/browser_toolbox_tool_remote_reopen.js
@@ -60,31 +60,31 @@ function runTools(target) {
       ok(panel.isReady, toolId + " panel should be ready");
     }
 
     yield toolbox.destroy();
   });
 }
 
 function getClient() {
-  let deferred = promise.defer();
+  let deferred = defer();
 
   if (!DebuggerServer.initialized) {
     DebuggerServer.init();
     DebuggerServer.addBrowserActors();
   }
 
   let transport = DebuggerServer.connectPipe();
   let client = new DebuggerClient(transport);
 
   return client.connect().then(() => client);
 }
 
 function getTarget(client) {
-  let deferred = promise.defer();
+  let deferred = defer();
 
   client.listTabs(tabList => {
     let target = TargetFactory.forRemoteTab({
       client: client,
       form: tabList.tabs[tabList.selected],
       chrome: false
     });
     deferred.resolve(target);
--- a/devtools/client/framework/test/browser_toolbox_window_title_changes.js
+++ b/devtools/client/framework/test/browser_toolbox_window_title_changes.js
@@ -32,26 +32,26 @@ function test() {
       .then(checkTitle.bind(null, NAME_1, URL_1, "toolbox undocked"))
 
     // switch to different tool and check title
       .then(() => toolbox.selectTool(TOOL_ID_2))
       .then(checkTitle.bind(null, NAME_1, URL_1, "tool changed"))
 
     // navigate to different local url and check title
       .then(function () {
-        let deferred = promise.defer();
+        let deferred = defer();
         target.once("navigate", () => deferred.resolve());
         gBrowser.loadURI(URL_2);
         return deferred.promise;
       })
       .then(checkTitle.bind(null, NAME_2, URL_2, "url changed"))
 
     // navigate to a real url and check title
       .then(() => {
-        let deferred = promise.defer();
+        let deferred = defer();
         target.once("navigate", () => deferred.resolve());
         gBrowser.loadURI(URL_3);
         return deferred.promise;
       })
       .then(checkTitle.bind(null, NAME_3, URL_3, "url changed"))
 
     // destroy toolbox, create new one hosted in a window (with a
     // different tool id), and check title
--- a/devtools/client/framework/test/head.js
+++ b/devtools/client/framework/test/head.js
@@ -51,17 +51,17 @@ function getSourceActor(aSources, aURL) 
 
 /**
  * Open a Scratchpad window.
  *
  * @return nsIDOMWindow
  *         The new window object that holds Scratchpad.
  */
 function* openScratchpadWindow() {
-  let { promise: p, resolve } = promise.defer();
+  let { promise: p, resolve } = defer();
   let win = ScratchpadManager.openScratchpad();
 
   yield once(win, "load");
 
   win.Scratchpad.addObserver({
     onReady: function () {
       win.Scratchpad.removeObserver(this);
       resolve(win);
@@ -77,17 +77,17 @@ function* openScratchpadWindow() {
  * @return {Promise} A promise that resolves to the response data when the
  * message has been received
  */
 function waitForContentMessage(name) {
   info("Expecting message " + name + " from content");
 
   let mm = gBrowser.selectedBrowser.messageManager;
 
-  let def = promise.defer();
+  let def = defer();
   mm.addMessageListener(name, function onMessage(msg) {
     mm.removeMessageListener(name, onMessage);
     def.resolve(msg.data);
   });
   return def.promise;
 }
 
 /**
--- a/devtools/client/framework/test/helper_disable_cache.js
+++ b/devtools/client/framework/test/helper_disable_cache.js
@@ -83,17 +83,17 @@ function* setDisableCacheCheckboxChecked
 
     // We need to wait for all checkboxes to be updated and the docshells to
     // apply the new cache settings.
     yield waitForTick();
   }
 }
 
 function reloadTab(tabX) {
-  let def = promise.defer();
+  let def = defer();
   let browser = gBrowser.selectedBrowser;
 
   // once() doesn't work here so we use a standard handler instead.
   browser.addEventListener("load", function onLoad() {
     browser.removeEventListener("load", onLoad, true);
     info("Reloaded tab " + tabX.title);
     def.resolve();
   }, true);
--- a/devtools/client/framework/test/shared-head.js
+++ b/devtools/client/framework/test/shared-head.js
@@ -198,17 +198,17 @@ function synthesizeKeyShortcut(key, targ
  *        Number of deliveries to wait for.
  * @param {Boolean} useCapture
  *        Optional, for addEventListener/removeEventListener
  * @return A promise that resolves when the event has been handled
  */
 function waitForNEvents(target, eventName, numTimes, useCapture = false) {
   info("Waiting for event: '" + eventName + "' on " + target + ".");
 
-  let deferred = promise.defer();
+  let deferred = defer();
   let count = 0;
 
   for (let [add, remove] of [
     ["addEventListener", "removeEventListener"],
     ["addListener", "removeListener"],
     ["on", "off"]
   ]) {
     if ((add in target) && (remove in target)) {
@@ -257,31 +257,31 @@ function loadHelperScript(filePath) {
   Services.scriptloader.loadSubScript(testDir + "/" + filePath, this);
 }
 
 /**
  * Wait for a tick.
  * @return {Promise}
  */
 function waitForTick() {
-  let deferred = promise.defer();
+  let deferred = defer();
   executeSoon(deferred.resolve);
   return deferred.promise;
 }
 
 /**
  * This shouldn't be used in the tests, but is useful when writing new tests or
  * debugging existing tests in order to introduce delays in the test steps
  *
  * @param {Number} ms
  *        The time to wait
  * @return A promise that resolves when the time is passed
  */
 function wait(ms) {
-  let def = promise.defer();
+  let def = defer();
   content.setTimeout(def.resolve, ms);
   return def.promise;
 }
 
 /**
  * Open the toolbox in a given tab.
  * @param {XULNode} tab The tab the toolbox should be opened in.
  * @param {String} toolId Optional. The ID of the tool to be selected.
@@ -408,17 +408,17 @@ function evalInDebuggee(mm, script) {
  *        Function to invoke on popupshown event.
  * @param function onHidden
  *        Function to invoke on popuphidden event.
  * @return object
  *         A Promise object that is resolved after the popuphidden event
  *         callback is invoked.
  */
 function waitForContextMenu(popup, button, onShown, onHidden) {
-  let deferred = promise.defer();
+  let deferred = defer();
 
   function onPopupShown() {
     info("onPopupShown");
     popup.removeEventListener("popupshown", onPopupShown);
 
     onShown && onShown();
 
     // Use executeSoon() to get out of the popupshown event.
--- a/devtools/client/framework/test/shared-redux-head.js
+++ b/devtools/client/framework/test/shared-redux-head.js
@@ -2,17 +2,17 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 /* eslint no-unused-vars: [2, {"vars": "local"}] */
 /* import-globals-from ./shared-head.js */
-// Currently this file expects "promise" to be imported into scope.
+// Currently this file expects "defer" to be imported into scope.
 
 // Common utility functions for working with Redux stores.  The file is meant
 // to be safe to load in both mochitest and xpcshell environments.
 
 /**
  * A logging function that can be used from xpcshell and browser mochitest
  * environments.
  */
@@ -33,17 +33,17 @@ function commonLog(message) {
  *        The Redux store being used.
  * @param function predicate
  *        A function that returns true when the store has reached the expected
  *        state.
  * @return Promise
  *         Resolved once the store reaches the expected state.
  */
 function waitUntilState(store, predicate) {
-  let deferred = promise.defer();
+  let deferred = defer();
   let unsubscribe = store.subscribe(check);
 
   commonLog(`Waiting for state predicate "${predicate}"`);
   function check() {
     if (predicate(store.getState())) {
       commonLog(`Found state predicate "${predicate}"`);
       unsubscribe();
       deferred.resolve();
@@ -61,17 +61,17 @@ function waitUntilState(store, predicate
  * @param Store store
  *        The Redux store being used.
  * @param string actionType
  *        The expected action to wait for.
  * @return Promise
  *         Resolved once the expected action is emitted by the store.
  */
 function waitUntilAction(store, actionType) {
-  let deferred = promise.defer();
+  let deferred = defer();
   let unsubscribe = store.subscribe(check);
   let history = store.history;
   let index = history.length;
 
   commonLog(`Waiting for action "${actionType}"`);
   function check() {
     let action = history[index++];
     if (action && action.type === actionType) {
--- a/devtools/client/framework/toolbox-hosts.js
+++ b/devtools/client/framework/toolbox-hosts.js
@@ -3,16 +3,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 EventEmitter = require("devtools/shared/event-emitter");
 const promise = require("promise");
+const defer = require("devtools/shared/defer");
 const Services = require("Services");
 const {DOMHelpers} = require("resource://devtools/client/shared/DOMHelpers.jsm");
 
 loader.lazyRequireGetter(this, "system", "devtools/shared/system");
 
 /* A host should always allow this much space for the page to be displayed.
  * There is also a min-height on the browser, but we still don't want to set
  * frame.height to be larger than that, since it can cause problems with
@@ -48,17 +49,17 @@ BottomHost.prototype = {
   type: "bottom",
 
   heightPref: "devtools.toolbox.footer.height",
 
   /**
    * Create a box at the bottom of the host tab.
    */
   create: function () {
-    let deferred = promise.defer();
+    let deferred = defer();
 
     let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
     let ownerDocument = gBrowser.ownerDocument;
     this._nbox = gBrowser.getNotificationBox(this.hostTab.linkedBrowser);
 
     this._splitter = ownerDocument.createElement("splitter");
     this._splitter.setAttribute("class", "devtools-horizontal-splitter");
 
@@ -189,17 +190,17 @@ SidebarHost.prototype = {
   type: "side",
 
   widthPref: "devtools.toolbox.sidebar.width",
 
   /**
    * Create a box in the sidebar of the host tab.
    */
   create: function () {
-    let deferred = promise.defer();
+    let deferred = defer();
 
     let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
     let ownerDocument = gBrowser.ownerDocument;
     this._sidebar = gBrowser.getSidebarContainer(this.hostTab.linkedBrowser);
 
     this._splitter = ownerDocument.createElement("splitter");
     this._splitter.setAttribute("class", "devtools-side-splitter");
 
@@ -272,17 +273,17 @@ WindowHost.prototype = {
   type: "window",
 
   WINDOW_URL: "chrome://devtools/content/framework/toolbox-window.xul",
 
   /**
    * Create a new xul window to contain the toolbox.
    */
   create: function () {
-    let deferred = promise.defer();
+    let deferred = defer();
 
     let flags = "chrome,centerscreen,resizable,dialog=no";
     let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank",
                                      flags, null);
 
     let frameLoad = () => {
       win.removeEventListener("load", frameLoad, true);
       win.focus();
--- a/devtools/client/framework/toolbox-options.js
+++ b/devtools/client/framework/toolbox-options.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 Services = require("Services");
-const promise = require("promise");
+const defer = require("devtools/shared/defer");
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.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");
@@ -391,17 +391,17 @@ OptionsPanel.prototype = {
     this.target.activeTab.reconfigure(options);
   },
 
   destroy: function () {
     if (this.destroyPromise) {
       return this.destroyPromise;
     }
 
-    let deferred = promise.defer();
+    let deferred = defer();
     this.destroyPromise = deferred.promise;
 
     this._removeListeners();
 
     if (this.target.activeTab) {
       this.disableJSNode.removeEventListener("click", this._disableJSClicked);
       // FF41+ automatically cleans up state in actor on disconnect
       if (!this.target.activeTab.traits.noTabReconfigureOnClose) {
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -9,16 +9,17 @@ const SPLITCONSOLE_ENABLED_PREF = "devto
 const SPLITCONSOLE_HEIGHT_PREF = "devtools.toolbox.splitconsoleHeight";
 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";
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
 var {Cc, Ci, Cu} = require("chrome");
 var promise = require("promise");
+var defer = require("devtools/shared/defer");
 var Services = require("Services");
 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");
@@ -229,17 +230,17 @@ Toolbox.prototype = {
    * like to select the tool right away.
    *
    * @param  {String} id
    *         The id of the panel, for example "jsdebugger".
    * @returns Promise
    *          A promise that resolves once the panel is ready.
    */
   getPanelWhenReady: function (id) {
-    let deferred = promise.defer();
+    let deferred = defer();
     let panel = this.getPanel(id);
     if (panel) {
       deferred.resolve(panel);
     } else {
       this.on(id + "-ready", (e, panel) => {
         deferred.resolve(panel);
       });
     }
@@ -359,17 +360,17 @@ Toolbox.prototype = {
   },
 
   /**
    * Open the toolbox
    */
   open: function () {
     return Task.spawn(function* () {
       let iframe = yield this._host.create();
-      let domReady = promise.defer();
+      let domReady = defer();
 
       // Prevent reloading the document when the toolbox is opened in a tab
       let location = iframe.contentWindow.location.href;
       if (!location.startsWith(this._URL)) {
         iframe.setAttribute("src", this._URL);
       } else {
         // Update the URL so that onceDOMReady watch for the right url.
         this._URL = location;
@@ -1184,17 +1185,17 @@ Toolbox.prototype = {
    */
   loadTool: function (id) {
     if (id === "inspector" && !this._inspector) {
       return this.initInspector().then(() => {
         return this.loadTool(id);
       });
     }
 
-    let deferred = promise.defer();
+    let deferred = defer();
     let iframe = this.doc.getElementById("toolbox-panel-iframe-" + id);
 
     if (iframe) {
       let panel = this._toolPanels.get(id);
       if (panel) {
         deferred.resolve(panel);
       } else {
         this.once(id + "-ready", panel => {
@@ -1252,17 +1253,17 @@ Toolbox.prototype = {
         gDevTools.emit(id + "-build", this, panel);
         this.emit(id + "-build", panel);
 
         // The panel can implement an 'open' method for asynchronous
         // initialization sequence.
         if (typeof panel.open == "function") {
           built = panel.open();
         } else {
-          let buildDeferred = promise.defer();
+          let buildDeferred = defer();
           buildDeferred.resolve(panel);
           built = buildDeferred.promise;
         }
       }
 
       // Wait till the panel is fully ready and fire 'ready' events.
       promise.resolve(built).then((panel) => {
         this._toolPanels.set(id, panel);
@@ -2183,17 +2184,17 @@ Toolbox.prototype = {
     if (!this.target.hasActor("profiler")) {
       return;
     }
 
     if (this._performanceFrontConnection) {
       return this._performanceFrontConnection.promise;
     }
 
-    this._performanceFrontConnection = promise.defer();
+    this._performanceFrontConnection = defer();
     this._performance = createPerformanceFront(this._target);
     yield this.performance.connect();
 
     // Emit an event when connected, but don't wait on startup for this.
     this.emit("profiler-connected");
 
     this.performance.on("*", this._onPerformanceFrontEvent);
     this._performanceFrontConnection.resolve(this.performance);
--- a/devtools/client/memory/test/unit/head.js
+++ b/devtools/client/memory/test/unit/head.js
@@ -12,16 +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 defer = require("devtools/shared/defer");
 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);