Bug 1346009 - Convert 'defer' to 'new Promise' in client/webide; r=tromey
authorMatt R <matthieu.rigolot@gmail.com>
Sat, 20 May 2017 13:31:10 +0100
changeset 412310 1d250422890a24fd71f473e457009a2257726da8
parent 412309 e603b83ca39530ab7eccb6f2e999905ecb209e1a
child 412311 5a12c5e3eac314f257c595f0605f0302f12a6057
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstromey
bugs1346009
milestone55.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 1346009 - Convert 'defer' to 'new Promise' in client/webide; r=tromey MozReview-Commit-ID: 1adrD8A96Dx
devtools/client/webide/modules/addons.js
devtools/client/webide/modules/app-manager.js
devtools/client/webide/modules/app-projects.js
devtools/client/webide/modules/app-validator.js
devtools/client/webide/modules/build.js
devtools/client/webide/modules/project-list.js
devtools/client/webide/modules/simulator-process.js
devtools/client/webide/modules/simulators.js
devtools/client/webide/modules/tab-store.js
devtools/client/webide/test/browser_tabs.js
devtools/client/webide/test/head.js
devtools/client/webide/test/test_addons.html
devtools/client/webide/test/test_autoconnect_runtime.html
devtools/client/webide/test/test_basic.html
devtools/client/webide/test/test_fullscreenToolbox.html
devtools/client/webide/test/test_runtime.html
devtools/client/webide/test/test_simulators.html
devtools/client/webide/test/test_toolbox.html
--- a/devtools/client/webide/modules/addons.js
+++ b/devtools/client/webide/modules/addons.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 promise = require("promise");
 const {AddonManager} = require("resource://gre/modules/AddonManager.jsm");
 const Services = require("Services");
 const {getJSON} = require("devtools/client/shared/getjson");
 const EventEmitter = require("devtools/shared/event-emitter");
 
 const ADDONS_URL = "devtools.webide.addonsURL";
 
 var SIMULATOR_LINK = Services.prefs.getCharPref("devtools.webide.simulatorAddonsURL");
@@ -46,34 +45,34 @@ addonsListener.onUninstalled = (updatedA
     }
   });
 };
 AddonManager.addAddonListener(addonsListener);
 
 var GetAvailableAddons_promise = null;
 var GetAvailableAddons = exports.GetAvailableAddons = function () {
   if (!GetAvailableAddons_promise) {
-    let deferred = promise.defer();
-    GetAvailableAddons_promise = deferred.promise;
-    let addons = {
-      simulators: [],
-      adb: null
-    };
-    getJSON(ADDONS_URL).then(json => {
-      for (let stability in json) {
-        for (let version of json[stability]) {
-          addons.simulators.push(new SimulatorAddon(stability, version));
+    GetAvailableAddons_promise = new Promise((resolve, reject) => {
+      let addons = {
+        simulators: [],
+        adb: null
+      };
+      getJSON(ADDONS_URL).then(json => {
+        for (let stability in json) {
+          for (let version of json[stability]) {
+            addons.simulators.push(new SimulatorAddon(stability, version));
+          }
         }
-      }
-      addons.adb = new ADBAddon();
-      addons.adapters = new AdaptersAddon();
-      deferred.resolve(addons);
-    }, e => {
-      GetAvailableAddons_promise = null;
-      deferred.reject(e);
+        addons.adb = new ADBAddon();
+        addons.adapters = new AdaptersAddon();
+        resolve(addons);
+      }, e => {
+        GetAvailableAddons_promise = null;
+        reject(e);
+      });
     });
   }
   return GetAvailableAddons_promise;
 };
 
 exports.ForgetAddonsList = function () {
   GetAvailableAddons_promise = null;
 };
--- a/devtools/client/webide/modules/app-manager.js
+++ b/devtools/client/webide/modules/app-manager.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/. */
 
 const {Cu} = require("chrome");
 
-const promise = require("promise");
 const {TargetFactory} = require("devtools/client/framework/target");
 const Services = require("Services");
 const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
 const EventEmitter = require("devtools/shared/event-emitter");
 const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
 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");
@@ -272,17 +271,17 @@ var AppManager = exports.AppManager = {
     if (this.selectedProject.type !== "tab") {
       return;
     }
     this.selectedProject = null;
   },
 
   reloadTab: function () {
     if (this.selectedProject && this.selectedProject.type != "tab") {
-      return promise.reject("tried to reload non-tab project");
+      return Promise.reject("tried to reload non-tab project");
     }
     return this.getTarget().then(target => {
       target.activeTab.reload();
     }, console.error.bind(console));
   },
 
   getTarget: function () {
     if (this.selectedProject.type == "mainProcess") {
@@ -308,31 +307,31 @@ var AppManager = exports.AppManager = {
     }
 
     if (this.selectedProject.type == "tab") {
       return this.tabStore.getTargetForTab();
     }
 
     let app = this._getProjectFront(this.selectedProject);
     if (!app) {
-      return promise.reject("Can't find app front for selected project");
+      return Promise.reject("Can't find app front for selected project");
     }
 
     return Task.spawn(function* () {
       // Once we asked the app to launch, the app isn't necessary completely loaded.
       // launch request only ask the app to launch and immediatly returns.
       // We have to keep trying to get app tab actors required to create its target.
 
       for (let i = 0; i < 10; i++) {
         try {
           return yield app.getTarget();
         } catch (e) {}
-        let deferred = promise.defer();
-        setTimeout(deferred.resolve, 500);
-        yield deferred.promise;
+        return new Promise(resolve => {
+          setTimeout(resolve, 500);
+        });
       }
 
       AppManager.reportError("error_cantConnectToApp", app.manifest.manifestURL);
       throw new Error("can't connect to app");
     });
   },
 
   getProjectManifestURL: function (project) {
@@ -455,71 +454,71 @@ var AppManager = exports.AppManager = {
   get selectedRuntime() {
     return this._selectedRuntime;
   },
 
   connectToRuntime: function (runtime) {
 
     if (this.connected && this.selectedRuntime === runtime) {
       // Already connected
-      return promise.resolve();
+      return Promise.resolve();
     }
 
-    let deferred = promise.defer();
-
-    this.disconnectRuntime().then(() => {
-      this.selectedRuntime = runtime;
+    let deferred = new Promise((resolve, reject) => {
+      this.disconnectRuntime().then(() => {
+        this.selectedRuntime = runtime;
 
-      let onConnectedOrDisconnected = () => {
-        this.connection.off(Connection.Events.CONNECTED, onConnectedOrDisconnected);
-        this.connection.off(Connection.Events.DISCONNECTED, onConnectedOrDisconnected);
-        if (this.connected) {
-          deferred.resolve();
-        } else {
-          deferred.reject();
+        let onConnectedOrDisconnected = () => {
+          this.connection.off(Connection.Events.CONNECTED, onConnectedOrDisconnected);
+          this.connection.off(Connection.Events.DISCONNECTED, onConnectedOrDisconnected);
+          if (this.connected) {
+            resolve();
+          } else {
+            reject();
+          }
+        };
+        this.connection.on(Connection.Events.CONNECTED, onConnectedOrDisconnected);
+        this.connection.on(Connection.Events.DISCONNECTED, onConnectedOrDisconnected);
+        try {
+          // Reset the connection's state to defaults
+          this.connection.resetOptions();
+          // Only watch for errors here.  Final resolution occurs above, once
+          // we've reached the CONNECTED state.
+          this.selectedRuntime.connect(this.connection)
+                              .then(null, e => reject(e));
+        } catch (e) {
+          reject(e);
         }
-      };
-      this.connection.on(Connection.Events.CONNECTED, onConnectedOrDisconnected);
-      this.connection.on(Connection.Events.DISCONNECTED, onConnectedOrDisconnected);
-      try {
-        // Reset the connection's state to defaults
-        this.connection.resetOptions();
-        // Only watch for errors here.  Final resolution occurs above, once
-        // we've reached the CONNECTED state.
-        this.selectedRuntime.connect(this.connection)
-                            .then(null, e => deferred.reject(e));
-      } catch (e) {
-        deferred.reject(e);
-      }
-    }, deferred.reject);
+      }, reject);
+    });
 
     // Record connection result in telemetry
     let logResult = result => {
       this._telemetry.log("DEVTOOLS_WEBIDE_CONNECTION_RESULT", result);
       if (runtime.type) {
         this._telemetry.log("DEVTOOLS_WEBIDE_" + runtime.type +
                             "_CONNECTION_RESULT", result);
       }
     };
-    deferred.promise.then(() => logResult(true), () => logResult(false));
+    deferred.then(() => logResult(true), () => logResult(false));
 
     // If successful, record connection time in telemetry
-    deferred.promise.then(() => {
+    deferred.then(() => {
       const timerId = "DEVTOOLS_WEBIDE_CONNECTION_TIME_SECONDS";
       this._telemetry.startTimer(timerId);
       this.connection.once(Connection.Events.STATUS_CHANGED, () => {
         this._telemetry.stopTimer(timerId);
       });
     }).catch(() => {
       // Empty rejection handler to silence uncaught rejection warnings
       // |connectToRuntime| caller should listen for rejections.
       // Bug 1121100 may find a better way to silence these.
     });
 
-    return deferred.promise;
+    return deferred;
   },
 
   _recordRuntimeInfo: Task.async(function* () {
     if (!this.connected) {
       return;
     }
     let runtime = this.selectedRuntime;
     this._telemetry.logKeyed("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE",
@@ -565,35 +564,36 @@ var AppManager = exports.AppManager = {
     if (!this._listTabsResponse) {
       return null;
     }
     return getPreferenceFront(this.connection.client, this._listTabsResponse);
   },
 
   disconnectRuntime: function () {
     if (!this.connected) {
-      return promise.resolve();
+      return Promise.resolve();
     }
-    let deferred = promise.defer();
-    this.connection.once(Connection.Events.DISCONNECTED, () => deferred.resolve());
-    this.connection.disconnect();
-    return deferred.promise;
+
+    return new Promise(resolve => {
+      this.connection.once(Connection.Events.DISCONNECTED, () => resolve());
+      this.connection.disconnect();
+    });
   },
 
   launchRuntimeApp: function () {
     if (this.selectedProject && this.selectedProject.type != "runtimeApp") {
-      return promise.reject("attempting to launch a non-runtime app");
+      return Promise.reject("attempting to launch a non-runtime app");
     }
     let app = this._getProjectFront(this.selectedProject);
     return app.launch();
   },
 
   launchOrReloadRuntimeApp: function () {
     if (this.selectedProject && this.selectedProject.type != "runtimeApp") {
-      return promise.reject("attempting to launch / reload a non-runtime app");
+      return Promise.reject("attempting to launch / reload a non-runtime app");
     }
     let app = this._getProjectFront(this.selectedProject);
     if (!app.running) {
       return app.launch();
     } else {
       return app.reload();
     }
   },
@@ -602,27 +602,27 @@ var AppManager = exports.AppManager = {
     return !!this._appsFront;
   },
 
   installAndRunProject: function () {
     let project = this.selectedProject;
 
     if (!project || (project.type != "packaged" && project.type != "hosted")) {
       console.error("Can't install project. Unknown type of project.");
-      return promise.reject("Can't install");
+      return Promise.reject("Can't install");
     }
 
     if (!this._listTabsResponse) {
       this.reportError("error_cantInstallNotFullyConnected");
-      return promise.reject("Can't install");
+      return Promise.reject("Can't install");
     }
 
     if (!this._appsFront) {
       console.error("Runtime doesn't have a webappsActor");
-      return promise.reject("Can't install");
+      return Promise.reject("Can't install");
     }
 
     return Task.spawn(function* () {
       let self = AppManager;
 
       // Package and validate project
       yield self.packageProject(project);
       yield self.validateAndUpdateProject(project);
@@ -630,17 +630,17 @@ var AppManager = exports.AppManager = {
       if (project.errorsCount > 0) {
         self.reportError("error_cantInstallValidationErrors");
         return;
       }
 
       let installPromise;
 
       if (project.type != "packaged" && project.type != "hosted") {
-        return promise.reject("Don't know how to install project");
+        return Promise.reject("Don't know how to install project");
       }
 
       let response;
       if (project.type == "packaged") {
         let packageDir = yield ProjectBuilding.getPackageDir(project);
         console.log("Installing app from " + packageDir);
 
         response = yield self._appsFront.installPackaged(packageDir,
@@ -669,41 +669,42 @@ var AppManager = exports.AppManager = {
       // Addons don't have any document to load (yet?)
       // So that there is no need to run them, installing is enough
       if (project.manifest.manifest_version || project.manifest.role === "addon") {
         return;
       }
 
       let {app} = response;
       if (!app.running) {
-        let deferred = promise.defer();
-        self.on("app-manager-update", function onUpdate(event, what) {
-          if (what == "project-started") {
-            self.off("app-manager-update", onUpdate);
-            deferred.resolve();
-          }
+        let deferred = new Promise(resolve => {
+          self.on("app-manager-update", function onUpdate(event, what) {
+            if (what == "project-started") {
+              self.off("app-manager-update", onUpdate);
+              resolve();
+            }
+          });
         });
         yield app.launch();
-        yield deferred.promise;
+        yield deferred;
       } else {
         yield app.reload();
       }
     });
   },
 
   stopRunningApp: function () {
     let app = this._getProjectFront(this.selectedProject);
     return app.close();
   },
 
   /* PROJECT VALIDATION */
 
   validateAndUpdateProject: function (project) {
     if (!project) {
-      return promise.reject();
+      return Promise.reject();
     }
 
     return Task.spawn(function* () {
 
       let packageDir = yield ProjectBuilding.getPackageDir(project);
       let validation = new AppValidator({
         type: project.type,
         // Build process may place the manifest in a non-root directory
@@ -818,17 +819,17 @@ var AppManager = exports.AppManager = {
     this.update("runtime-details");
     this.update("runtime-list");
   },
 
   /* MANIFEST UTILS */
 
   writeManifest: function (project) {
     if (project.type != "packaged") {
-      return promise.reject("Not a packaged app");
+      return Promise.reject("Not a packaged app");
     }
 
     if (!project.manifest) {
       project.manifest = {};
     }
 
     let folder = project.location;
     let manifestPath = OS.Path.join(folder, "manifest.webapp");
--- a/devtools/client/webide/modules/app-projects.js
+++ b/devtools/client/webide/modules/app-projects.js
@@ -1,14 +1,13 @@
 /* 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, Cr} = require("chrome");
-const promise = require("promise");
 
 const EventEmitter = require("devtools/shared/event-emitter");
 const {generateUUID} = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
 const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
 
 /**
  * IndexedDB wrapper that just save project objects
  *
@@ -16,155 +15,145 @@ const {FileUtils} = Cu.import("resource:
  * a unique `location` object.
  */
 
 const IDB = {
   _db: null,
   databaseName: "AppProjects",
 
   open: function () {
-    let deferred = promise.defer();
-
-    let request = indexedDB.open(IDB.databaseName, 5);
-    request.onerror = function (event) {
-      deferred.reject("Unable to open AppProjects indexedDB: " +
-                      this.error.name + " - " + this.error.message);
-    };
-    request.onupgradeneeded = function (event) {
-      let db = event.target.result;
-      db.createObjectStore("projects", { keyPath: "location" });
-    };
+    return new Promise((resolve, reject) => {
+      let request = indexedDB.open(IDB.databaseName, 5);
+      request.onerror = function (event) {
+        reject("Unable to open AppProjects indexedDB: " +
+                        this.error.name + " - " + this.error.message);
+      };
+      request.onupgradeneeded = function (event) {
+        let db = event.target.result;
+        db.createObjectStore("projects", { keyPath: "location" });
+      };
 
-    request.onsuccess = function () {
-      let db = IDB._db = request.result;
-      let objectStore = db.transaction("projects").objectStore("projects");
-      let projects = [];
-      let toRemove = [];
-      objectStore.openCursor().onsuccess = function (event) {
-        let cursor = event.target.result;
-        if (cursor) {
-          if (cursor.value.location) {
+      request.onsuccess = function () {
+        let db = IDB._db = request.result;
+        let objectStore = db.transaction("projects").objectStore("projects");
+        let projects = [];
+        let toRemove = [];
+        objectStore.openCursor().onsuccess = function (event) {
+          let cursor = event.target.result;
+          if (cursor) {
+            if (cursor.value.location) {
 
-            // We need to make sure this object has a `.location` property.
-            // The UI depends on this property.
-            // This should not be needed as we make sure to register valid
-            // projects, but in the past (before bug 924568), we might have
-            // registered invalid objects.
+              // We need to make sure this object has a `.location` property.
+              // The UI depends on this property.
+              // This should not be needed as we make sure to register valid
+              // projects, but in the past (before bug 924568), we might have
+              // registered invalid objects.
 
 
-            // We also want to make sure the location is valid.
-            // If the location doesn't exist, we remove the project.
+              // We also want to make sure the location is valid.
+              // If the location doesn't exist, we remove the project.
 
-            try {
-              let file = FileUtils.File(cursor.value.location);
-              if (file.exists()) {
-                projects.push(cursor.value);
-              } else {
-                toRemove.push(cursor.value.location);
-              }
-            } catch (e) {
-              if (e.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH) {
-                // A URL
-                projects.push(cursor.value);
+              try {
+                let file = FileUtils.File(cursor.value.location);
+                if (file.exists()) {
+                  projects.push(cursor.value);
+                } else {
+                  toRemove.push(cursor.value.location);
+                }
+              } catch (e) {
+                if (e.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH) {
+                  // A URL
+                  projects.push(cursor.value);
+                }
               }
             }
-          }
-          cursor.continue();
-        } else {
-          let removePromises = [];
-          for (let location of toRemove) {
-            removePromises.push(IDB.remove(location));
+            cursor.continue();
+          } else {
+            let removePromises = [];
+            for (let location of toRemove) {
+              removePromises.push(IDB.remove(location));
+            }
+            Promise.all(removePromises).then(() => {
+              resolve(projects);
+            });
           }
-          promise.all(removePromises).then(() => {
-            deferred.resolve(projects);
-          });
-        }
+        };
       };
-    };
-
-    return deferred.promise;
+    });
   },
 
   add: function (project) {
-    let deferred = promise.defer();
-
-    if (!project.location) {
-      // We need to make sure this object has a `.location` property.
-      deferred.reject("Missing location property on project object.");
-    } else {
-      let transaction = IDB._db.transaction(["projects"], "readwrite");
-      let objectStore = transaction.objectStore("projects");
-      let request = objectStore.add(project);
-      request.onerror = function (event) {
-        deferred.reject("Unable to add project to the AppProjects indexedDB: " +
-                        this.error.name + " - " + this.error.message);
-      };
-      request.onsuccess = function () {
-        deferred.resolve();
-      };
-    }
-
-    return deferred.promise;
+    return new Promise((resolve, reject) => {
+      if (!project.location) {
+        // We need to make sure this object has a `.location` property.
+        reject("Missing location property on project object.");
+      } else {
+        let transaction = IDB._db.transaction(["projects"], "readwrite");
+        let objectStore = transaction.objectStore("projects");
+        let request = objectStore.add(project);
+        request.onerror = function (event) {
+          reject("Unable to add project to the AppProjects indexedDB: " +
+                 this.error.name + " - " + this.error.message);
+        };
+        request.onsuccess = function () {
+          resolve();
+        };
+      }
+    });
   },
 
   update: function (project) {
-    let deferred = promise.defer();
-
-    var transaction = IDB._db.transaction(["projects"], "readwrite");
-    var objectStore = transaction.objectStore("projects");
-    var request = objectStore.put(project);
-    request.onerror = function (event) {
-      deferred.reject("Unable to update project to the AppProjects indexedDB: " +
-                      this.error.name + " - " + this.error.message);
-    };
-    request.onsuccess = function () {
-      deferred.resolve();
-    };
-
-    return deferred.promise;
+    return new Promise((resolve, reject) => {
+      var transaction = IDB._db.transaction(["projects"], "readwrite");
+      var objectStore = transaction.objectStore("projects");
+      var request = objectStore.put(project);
+      request.onerror = function (event) {
+        reject("Unable to update project to the AppProjects indexedDB: " +
+               this.error.name + " - " + this.error.message);
+      };
+      request.onsuccess = function () {
+        resolve();
+      };
+    });
   },
 
   remove: function (location) {
-    let deferred = promise.defer();
-
-    let request = IDB._db.transaction(["projects"], "readwrite")
+    return new Promise((resolve, reject) => {
+      let request = IDB._db.transaction(["projects"], "readwrite")
                     .objectStore("projects")
                     .delete(location);
-    request.onsuccess = function (event) {
-      deferred.resolve();
-    };
-    request.onerror = function () {
-      deferred.reject("Unable to delete project to the AppProjects indexedDB: " +
-                      this.error.name + " - " + this.error.message);
-    };
-
-    return deferred.promise;
+      request.onsuccess = function (event) {
+        resolve();
+      };
+      request.onerror = function () {
+        reject("Unable to delete project to the AppProjects indexedDB: " +
+               this.error.name + " - " + this.error.message);
+      };
+    });
   }
 };
 
-var loadDeferred = promise.defer();
-
-loadDeferred.resolve(IDB.open().then(function (projects) {
+var loadDeferred = IDB.open().then(function (projects) {
   AppProjects.projects = projects;
   AppProjects.emit("ready", projects);
-}));
+});
 
 const AppProjects = {
   load: function () {
-    return loadDeferred.promise;
+    return loadDeferred;
   },
 
   addPackaged: function (folder) {
     let file = FileUtils.File(folder.path);
     if (!file.exists()) {
-      return promise.reject("path doesn't exist");
+      return Promise.reject("path doesn't exist");
     }
     let existingProject = this.get(folder.path);
     if (existingProject) {
-      return promise.reject("Already added");
+      return Promise.reject("Already added");
     }
     let project = {
       type: "packaged",
       location: folder.path,
       // We need a unique id, that is the app origin,
       // in order to identify the app when being installed on the device.
       // The packaged app local path is a valid id, but only on the client.
       // This origin will be used to generate the true id of an app:
@@ -177,17 +166,17 @@ const AppProjects = {
       this.projects.push(project);
       return project;
     });
   },
 
   addHosted: function (manifestURL) {
     let existingProject = this.get(manifestURL);
     if (existingProject) {
-      return promise.reject("Already added");
+      return Promise.reject("Already added");
     }
     let project = {
       type: "hosted",
       location: manifestURL
     };
     return IDB.add(project).then(() => {
       this.projects.push(project);
       return project;
--- a/devtools/client/webide/modules/app-validator.js
+++ b/devtools/client/webide/modules/app-validator.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";
 
 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} = 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 }) {
@@ -59,127 +58,122 @@ AppValidator.prototype._getPackagedManif
   let manifestFile = this._getPackagedManifestFile();
   if (!manifestFile) {
     return null;
   }
   return Services.io.newFileURI(manifestFile).spec;
 };
 
 AppValidator.checkManifest = function (manifestURL) {
-  let deferred = promise.defer();
-  let error;
+  return new Promise((resolve, reject) => {
+    let error;
 
-  let req = new XMLHttpRequest();
-  req.overrideMimeType("text/plain");
+    let req = new XMLHttpRequest();
+    req.overrideMimeType("text/plain");
 
-  try {
-    req.open("GET", manifestURL, true);
-    req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
-  } catch (e) {
-    error = strings.formatStringFromName("validator.invalidManifestURL", [manifestURL], 1);
-    deferred.reject(error);
-    return deferred.promise;
-  }
-
-  req.onload = function () {
-    let manifest = null;
     try {
-      manifest = JSON.parse(req.responseText);
+      req.open("GET", manifestURL, true);
+      req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
     } catch (e) {
-      error = strings.formatStringFromName("validator.invalidManifestJSON", [e, manifestURL], 2);
-      deferred.reject(error);
+      error = strings.formatStringFromName("validator.invalidManifestURL", [manifestURL], 1);
+      return reject(error);
     }
 
-    deferred.resolve({manifest, manifestURL});
-  };
+    req.onload = function () {
+      let manifest = null;
+      try {
+        manifest = JSON.parse(req.responseText);
+      } catch (e) {
+        error = strings.formatStringFromName("validator.invalidManifestJSON", [e, manifestURL], 2);
+        reject(error);
+      }
 
-  req.onerror = function () {
-    error = strings.formatStringFromName("validator.noAccessManifestURL", [req.statusText, manifestURL], 2);
-    deferred.reject(error);
-  };
+      resolve({manifest, manifestURL});
+    };
 
-  try {
-    req.send(null);
-  } catch (e) {
-    error = strings.formatStringFromName("validator.noAccessManifestURL", [e, manifestURL], 2);
-    deferred.reject(error);
-  }
+    req.onerror = function () {
+      error = strings.formatStringFromName("validator.noAccessManifestURL", [req.statusText, manifestURL], 2);
+      reject(error);
+    };
 
-  return deferred.promise;
+    try {
+      req.send(null);
+    } catch (e) {
+      error = strings.formatStringFromName("validator.noAccessManifestURL", [e, manifestURL], 2);
+      reject(error);
+    }
+  });
 };
 
 AppValidator.findManifestAtOrigin = function (manifestURL) {
   let fixedManifest = Services.io.newURI(manifestURL).prePath + "/manifest.webapp";
   return AppValidator.checkManifest(fixedManifest);
 };
 
 AppValidator.findManifestPath = function (manifestURL) {
-  let deferred = promise.defer();
-
-  if (manifestURL.endsWith("manifest.webapp")) {
-    deferred.reject();
-  } else {
-    let fixedManifest = manifestURL + "/manifest.webapp";
-    deferred.resolve(AppValidator.checkManifest(fixedManifest));
-  }
-
-  return deferred.promise;
+  return new Promise((resolve, reject) => {
+    if (manifestURL.endsWith("manifest.webapp")) {
+      reject();
+    } else {
+      let fixedManifest = manifestURL + "/manifest.webapp";
+      resolve(AppValidator.checkManifest(fixedManifest));
+    }
+  });
 };
 
 AppValidator.checkAlternateManifest = function (manifestURL) {
   return Task.spawn(function* () {
     let result;
     try {
       result = yield AppValidator.findManifestPath(manifestURL);
     } catch (e) {
       result = yield AppValidator.findManifestAtOrigin(manifestURL);
     }
 
     return result;
   });
 };
 
 AppValidator.prototype._fetchManifest = function (manifestURL) {
-  let deferred = promise.defer();
-  this.manifestURL = manifestURL;
+  return new Promise(resolve => {
+    this.manifestURL = manifestURL;
 
-  AppValidator.checkManifest(manifestURL)
-              .then(({manifest, manifestURL}) => {
-                deferred.resolve(manifest);
-              }, error => {
-                AppValidator.checkAlternateManifest(manifestURL)
-                            .then(({manifest, manifestURL}) => {
-                              this.manifestURL = manifestURL;
-                              deferred.resolve(manifest);
-                            }, () => {
-                              this.error(error);
-                              deferred.resolve(null);
-                            });
-              });
-
-  return deferred.promise;
+    AppValidator.checkManifest(manifestURL)
+                .then(({manifest, manifestURL}) => {
+                  resolve(manifest);
+                }, error => {
+                  AppValidator.checkAlternateManifest(manifestURL)
+                              .then(({manifest, manifestURL}) => {
+                                this.manifestURL = manifestURL;
+                                resolve(manifest);
+                              }, () => {
+                                this.error(error);
+                                resolve(null);
+                              });
+                });
+  });
 };
 
 AppValidator.prototype._getManifest = function () {
   let manifestURL;
   if (this.type == "packaged") {
     manifestURL = this._getPackagedManifestURL();
     if (!manifestURL)
-      return promise.resolve(null);
+      return Promise.resolve(null);
   } else if (this.type == "hosted") {
     manifestURL = this.location;
     try {
       Services.io.newURI(manifestURL);
     } catch (e) {
       this.error(strings.formatStringFromName("validator.invalidHostedManifestURL", [manifestURL, e.message], 2));
-      return promise.resolve(null);
+      return Promise.resolve(null);
     }
   } else {
     this.error(strings.formatStringFromName("validator.invalidProjectType", [this.type], 1));
-    return promise.resolve(null);
+    return Promise.resolve(null);
   }
   return this._fetchManifest(manifestURL);
 };
 
 AppValidator.prototype.validateManifest = function (manifest) {
   if (!manifest.name) {
     this.error(strings.GetStringFromName("validator.missNameManifestProperty"));
   }
@@ -196,67 +190,63 @@ AppValidator.prototype._getOriginURL = f
     let manifestURL = Services.io.newURI(this.manifestURL);
     return Services.io.newURI(".", null, manifestURL).spec;
   } else if (this.type == "hosted") {
     return Services.io.newURI(this.location).prePath;
   }
 };
 
 AppValidator.prototype.validateLaunchPath = function (manifest) {
-  let deferred = promise.defer();
-  // The launch_path field has to start with a `/`
-  if (manifest.launch_path && manifest.launch_path[0] !== "/") {
-    this.error(strings.formatStringFromName("validator.nonAbsoluteLaunchPath", [manifest.launch_path], 1));
-    deferred.resolve();
-    return deferred.promise;
-  }
-  let origin = this._getOriginURL();
-  let path;
-  if (this.type == "packaged") {
-    path = "." + (manifest.launch_path || "/index.html");
-  } else if (this.type == "hosted") {
-    path = manifest.launch_path || "/";
-  }
-  let indexURL;
-  try {
-    indexURL = Services.io.newURI(path, null, Services.io.newURI(origin)).spec;
-  } catch (e) {
-    this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [origin + path], 1));
-    deferred.resolve();
-    return deferred.promise;
-  }
+  return new Promise(resolve => {
+    // The launch_path field has to start with a `/`
+    if (manifest.launch_path && manifest.launch_path[0] !== "/") {
+      this.error(strings.formatStringFromName("validator.nonAbsoluteLaunchPath", [manifest.launch_path], 1));
+      resolve();
+    }
+    let origin = this._getOriginURL();
+    let path;
+    if (this.type == "packaged") {
+      path = "." + (manifest.launch_path || "/index.html");
+    } else if (this.type == "hosted") {
+      path = manifest.launch_path || "/";
+    }
+    let indexURL;
+    try {
+      indexURL = Services.io.newURI(path, null, Services.io.newURI(origin)).spec;
+    } catch (e) {
+      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [origin + path], 1));
+      return resolve();
+    }
 
-  let req = new XMLHttpRequest();
-  req.overrideMimeType("text/plain");
-  try {
-    req.open("HEAD", indexURL, true);
-    req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
-  } catch (e) {
-    this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
-    deferred.resolve();
-    return deferred.promise;
-  }
-  req.onload = () => {
-    if (req.status >= 400)
-      this.error(strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [indexURL, req.status], 2));
-    deferred.resolve();
-  };
-  req.onerror = () => {
-    this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
-    deferred.resolve();
-  };
+    let req = new XMLHttpRequest();
+    req.overrideMimeType("text/plain");
+    try {
+      req.open("HEAD", indexURL, true);
+      req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
+    } catch (e) {
+      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
+      return resolve();
+    }
+    req.onload = () => {
+      if (req.status >= 400)
+        this.error(strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [indexURL, req.status], 2));
+      resolve();
+    };
+    req.onerror = () => {
+      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
+      resolve();
+    };
 
-  try {
-    req.send(null);
-  } catch (e) {
-    this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
-    deferred.resolve();
-  }
-
-  return deferred.promise;
+    try {
+      req.send(null);
+    } catch (e) {
+      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
+      resolve();
+    }
+  });
 };
 
 AppValidator.prototype.validateType = function (manifest) {
   let appType = manifest.type || "web";
   if (["web", "privileged", "certified"].indexOf(appType) === -1) {
     this.error(strings.formatStringFromName("validator.invalidAppType", [appType], 1));
   } else if (this.type == "hosted" &&
              ["certified", "privileged"].indexOf(appType) !== -1) {
@@ -274,17 +264,17 @@ AppValidator.prototype.validate = functi
   this.warnings = [];
   return this._getManifest().
     then((manifest) => {
       if (manifest) {
         this.manifest = manifest;
 
         // Skip validations for add-ons
         if (manifest.role === "addon" || manifest.manifest_version) {
-          return promise.resolve();
+          return Promise.resolve();
         }
 
         this.validateManifest(manifest);
         this.validateType(manifest);
         return this.validateLaunchPath(manifest);
       }
     });
 };
--- a/devtools/client/webide/modules/build.js
+++ b/devtools/client/webide/modules/build.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/. */
 
 const {Cu, Cc, Ci} = require("chrome");
 
-const promise = require("promise");
 const { Task } = require("devtools/shared/task");
 const { 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);
@@ -144,41 +143,40 @@ const ProjectBuilding = exports.ProjectB
       args.unshift("/C");
     } else {
       args.unshift("-c");
     }
 
     // Subprocess changes CWD, we have to save and restore it.
     let originalCwd = yield OS.File.getCurrentDirectory();
     try {
-      let defer = promise.defer();
-      Subprocess.call({
-        command: shell,
-        arguments: args,
-        environment: env,
-        workdir: cwd,
+      yield new Promise((resolve, reject) => {
+        Subprocess.call({
+          command: shell,
+          arguments: args,
+          environment: env,
+          workdir: cwd,
 
-        stdout: data =>
-          logger(data),
-        stderr: data =>
-          logger(data),
+          stdout: data =>
+            logger(data),
+          stderr: data =>
+            logger(data),
 
-        done: result => {
-          logger("Terminated with error code: " + result.exitCode);
-          if (result.exitCode == 0) {
-            defer.resolve();
-          } else {
-            defer.reject("pre-package command failed with error code " + result.exitCode);
+          done: result => {
+            logger("Terminated with error code: " + result.exitCode);
+            if (result.exitCode == 0) {
+              resolve();
+            } else {
+              reject("pre-package command failed with error code " + result.exitCode);
+            }
           }
-        }
-      });
-      defer.promise.then(() => {
+        });
+      }).then(() => {
         OS.File.setCurrentDirectory(originalCwd);
       });
-      yield defer.promise;
     } catch (e) {
       throw new Error("Unable to run pre-package command '" + command + "' " +
                       args.join(" ") + ":\n" + (e.message || e));
     }
   }),
 
   getPackageDir: Task.async(function* (project) {
     let manifest = yield ProjectBuilding.fetchPackageManifest(project);
--- a/devtools/client/webide/modules/project-list.js
+++ b/devtools/client/webide/modules/project-list.js
@@ -2,17 +2,16 @@
 * 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 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} = 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;
@@ -195,17 +194,17 @@ ProjectList.prototype = {
           app: tab,
           icon: tab.favicon || AppManager.DEFAULT_PROJECT_ICON,
           location: tab.url,
           name: tab.name
         };
       }, true);
     }
 
-    return promise.resolve();
+    return Promise.resolve();
   },
 
   updateApps: function () {
     let doc = this._doc;
     let runtimeappsHeaderNode = doc.querySelector("#panel-header-runtimeapps");
     let sortedApps = [];
     for (let [manifestURL, app] of AppManager.apps) {
       sortedApps.push(app);
@@ -258,17 +257,17 @@ ProjectList.prototype = {
           type: "runtimeApp",
           app: app.manifest,
           icon: app.iconURL || AppManager.DEFAULT_PROJECT_ICON,
           name: app.manifest.name
         };
       }, true);
     }
 
-    return promise.resolve();
+    return Promise.resolve();
   },
 
   updateCommands: function () {
     let doc = this._doc;
     let newAppCmd;
     let packagedAppCmd;
     let hostedAppCmd;
 
@@ -294,79 +293,77 @@ ProjectList.prototype = {
 
   /**
    * Trigger an update of the project and remote runtime list.
    * @param options object (optional)
    *        An |options| object containing a type of |apps| or |tabs| will limit
    *        what is updated to only those sections.
    */
   update: function (options) {
-    let deferred = promise.defer();
-
     if (options && options.type === "apps") {
       return this.updateApps();
     } else if (options && options.type === "tabs") {
       return this.updateTabs();
     }
 
-    let doc = this._doc;
-    let projectsNode = doc.querySelector("#project-panel-projects");
+    return new Promise((resolve, reject) => {
+      let doc = this._doc;
+      let projectsNode = doc.querySelector("#project-panel-projects");
 
-    while (projectsNode.hasChildNodes()) {
-      projectsNode.firstChild.remove();
-    }
+      while (projectsNode.hasChildNodes()) {
+        projectsNode.firstChild.remove();
+      }
 
-    AppProjects.load().then(() => {
-      let projects = AppProjects.projects;
-      for (let i = 0; i < projects.length; i++) {
-        let project = projects[i];
-        let panelItemNode = doc.createElement(this._panelNodeEl);
-        panelItemNode.className = "panel-item";
-        projectsNode.appendChild(panelItemNode);
-        if (!project.validationStatus) {
-          // The result of the validation process (storing names, icons, …) is not stored in
-          // the IndexedDB database when App Manager v1 is used.
-          // We need to run the validation again and update the name and icon of the app.
-          AppManager.validateAndUpdateProject(project).then(() => {
+      AppProjects.load().then(() => {
+        let projects = AppProjects.projects;
+        for (let i = 0; i < projects.length; i++) {
+          let project = projects[i];
+          let panelItemNode = doc.createElement(this._panelNodeEl);
+          panelItemNode.className = "panel-item";
+          projectsNode.appendChild(panelItemNode);
+          if (!project.validationStatus) {
+            // The result of the validation process (storing names, icons, …) is not stored in
+            // the IndexedDB database when App Manager v1 is used.
+            // We need to run the validation again and update the name and icon of the app.
+            AppManager.validateAndUpdateProject(project).then(() => {
+              this._renderProjectItem({
+                panel: panelItemNode,
+                name: project.name,
+                icon: project.icon
+              });
+            });
+          } else {
             this._renderProjectItem({
               panel: panelItemNode,
-              name: project.name,
-              icon: project.icon
+              name: project.name || AppManager.DEFAULT_PROJECT_NAME,
+              icon: project.icon || AppManager.DEFAULT_PROJECT_ICON
             });
-          });
-        } else {
-          this._renderProjectItem({
-            panel: panelItemNode,
-            name: project.name || AppManager.DEFAULT_PROJECT_NAME,
-            icon: project.icon || AppManager.DEFAULT_PROJECT_ICON
-          });
+          }
+          panelItemNode.addEventListener("click", () => {
+            AppManager.selectedProject = project;
+          }, true);
         }
-        panelItemNode.addEventListener("click", () => {
-          AppManager.selectedProject = project;
-        }, true);
-      }
+
+        resolve();
+      }, reject);
 
-      deferred.resolve();
-    }, deferred.reject);
+      // List remote apps and the main process, if they exist
+      this.updateApps();
 
-    // List remote apps and the main process, if they exist
-    this.updateApps();
-
-    // Build the tab list right now, so it's fast...
-    this.updateTabs();
+      // Build the tab list right now, so it's fast...
+      this.updateTabs();
 
-    // But re-list them and rebuild, in case any tabs navigated since the last
-    // time they were listed.
-    if (AppManager.connected) {
-      AppManager.listTabs().then(() => {
-        this.updateTabs();
-      }).catch(console.error);
-    }
-
-    return deferred.promise;
+      // But re-list them and rebuild, in case any tabs navigated since the last
+      // time they were listed.
+      if (AppManager.connected) {
+        AppManager.listTabs().then(() => {
+          this.updateTabs();
+        }).catch(console.error);
+      }
+    });
   },
 
   destroy: function () {
     this._doc = null;
     AppManager.off("app-manager-update", this.appManagerUpdate);
     this._UI.off("webide-update", this.onWebIDEUpdate);
     this._UI = null;
     this._parentWindow = null;
--- a/devtools/client/webide/modules/simulator-process.js
+++ b/devtools/client/webide/modules/simulator-process.js
@@ -4,17 +4,16 @@
  */
 
 "use strict";
 
 const { Cc, Ci, Cu } = require("chrome");
 
 const Environment = require("sdk/system/environment").env;
 const EventEmitter = require("devtools/shared/event-emitter");
-const promise = require("promise");
 const Subprocess = require("sdk/system/child_process/subprocess");
 const Services = require("Services");
 
 loader.lazyGetter(this, "OS", () => {
   const Runtime = require("sdk/system/runtime");
   switch (Runtime.OS) {
     case "Darwin":
       return "mac64";
@@ -99,31 +98,31 @@ SimulatorProcess.prototype = {
         this.process = null;
         this.emit("exit", result.exitCode);
       }
     });
   },
 
   // Request a B2G instance kill.
   kill() {
-    let deferred = promise.defer();
-    if (this.process) {
-      this.once("exit", (e, exitCode) => {
-        this.shuttingDown = false;
-        deferred.resolve(exitCode);
-      });
-      if (!this.shuttingDown) {
-        this.shuttingDown = true;
-        this.emit("kill", null);
-        this.process.kill();
+    return new Promise(resolve => {
+      if (this.process) {
+        this.once("exit", (e, exitCode) => {
+          this.shuttingDown = false;
+          resolve(exitCode);
+        });
+        if (!this.shuttingDown) {
+          this.shuttingDown = true;
+          this.emit("kill", null);
+          this.process.kill();
+        }
+      } else {
+        return resolve(undefined);
       }
-      return deferred.promise;
-    } else {
-      return promise.resolve(undefined);
-    }
+    });
   },
 
   // Maybe log output messages.
   log(level, message) {
     if (!Services.prefs.getBoolPref("devtools.webide.logSimulatorOutput")) {
       return;
     }
     if (level === "stderr" || level === "error") {
--- a/devtools/client/webide/modules/simulators.js
+++ b/devtools/client/webide/modules/simulators.js
@@ -7,17 +7,16 @@
 const { AddonManager } = require("resource://gre/modules/AddonManager.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");
 
 const SimulatorRegExp = new RegExp(Services.prefs.getCharPref("devtools.webide.simulatorAddonRegExp"));
 const LocaleCompare = (a, b) => {
   return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
 };
 
 var Simulators = {
@@ -41,28 +40,29 @@ var Simulators = {
       let value = yield asyncStorage.getItem("simulators");
       if (Array.isArray(value)) {
         value.forEach(options => {
           let simulator = new Simulator(options);
           Simulators.add(simulator, true);
 
           // If the simulator had a reference to an addon, fix it.
           if (options.addonID) {
-            let deferred = promise.defer();
-            AddonManager.getAddonByID(options.addonID, addon => {
-              simulator.addon = addon;
-              delete simulator.options.addonID;
-              deferred.resolve();
+            let deferred = new Promise(resolve => {
+              AddonManager.getAddonByID(options.addonID, addon => {
+                simulator.addon = addon;
+                delete simulator.options.addonID;
+                resolve();
+              });
             });
-            jobs.push(deferred.promise);
+            jobs.push(deferred);
           }
         });
       }
 
-      yield promise.all(jobs);
+      yield Promise.all(jobs);
       yield Simulators._addUnusedAddons();
       Simulators.emitUpdated();
       return Simulators._simulators;
     });
 
     return this._loadingPromise;
   },
 
@@ -74,17 +74,17 @@ var Simulators = {
   _addUnusedAddons: Task.async(function* () {
     let jobs = [];
 
     let addons = yield Simulators.findSimulatorAddons();
     addons.forEach(addon => {
       jobs.push(Simulators.addIfUnusedAddon(addon, true));
     });
 
-    yield promise.all(jobs);
+    yield Promise.all(jobs);
   }),
 
   /**
    * Save the current list of configurations.
    *
    * @return Promise.
    */
   _save: Task.async(function* () {
@@ -112,39 +112,39 @@ var Simulators = {
   }),
 
   /**
    * List all installed simulator addons.
    *
    * @return Promised addon list.
    */
   findSimulatorAddons() {
-    let deferred = promise.defer();
-    AddonManager.getAllAddons(all => {
-      let addons = [];
-      for (let addon of all) {
-        if (Simulators.isSimulatorAddon(addon)) {
-          addons.push(addon);
+    return new Promise(resolve => {
+      AddonManager.getAllAddons(all => {
+        let addons = [];
+        for (let addon of all) {
+          if (Simulators.isSimulatorAddon(addon)) {
+            addons.push(addon);
+          }
         }
-      }
-      // Sort simulator addons by name.
-      addons.sort(LocaleCompare);
-      deferred.resolve(addons);
+        // Sort simulator addons by name.
+        addons.sort(LocaleCompare);
+        resolve(addons);
+      });
     });
-    return deferred.promise;
   },
 
   /**
    * Add a new simulator for `addon` if no other simulator uses it.
    */
   addIfUnusedAddon(addon, silently = false) {
     let simulators = this._simulators;
     let matching = simulators.filter(s => s.addon && s.addon.id == addon.id);
     if (matching.length > 0) {
-      return promise.resolve();
+      return Promise.resolve();
     }
     let options = {};
     options.name = addon.name.replace(" Simulator", "");
     // Some addons specify a simulator type at the end of their version string,
     // e.g. "2_5_tv".
     let type = this.simulatorAddonVersion(addon).split("_")[2];
     if (type) {
       // "tv" is shorthand for type "television".
@@ -171,17 +171,17 @@ var Simulators = {
   add(simulator, silently = false) {
     let simulators = this._simulators;
     let uniqueName = this.uniqueName(simulator.options.name);
     simulator.options.name = uniqueName;
     simulators.push(simulator);
     if (!silently) {
       this.emitUpdated();
     }
-    return promise.resolve(simulator);
+    return Promise.resolve(simulator);
   },
 
   /**
    * Remove a simulator from the list.
    */
   remove(simulator) {
     let simulators = this._simulators;
     let remaining = simulators.filter(s => s !== simulator);
@@ -327,23 +327,23 @@ Simulator.prototype = {
       // Recent simulator addon.
       this.process = new AddonSimulatorProcess(this.addon, this.options);
     } else {
       // Old simulator addon.
       this.process = new OldAddonSimulatorProcess(this.addon, this.options);
     }
     this.process.run();
 
-    return promise.resolve(this.options.port);
+    return Promise.resolve(this.options.port);
   },
 
   kill() {
     let process = this.process;
     if (!process) {
-      return promise.resolve();
+      return Promise.resolve();
     }
     this.process = null;
     return process.kill();
   },
 
   get defaults() {
     let defaults = this._defaults;
     return defaults[this.type] || defaults[this._defaultType];
--- a/devtools/client/webide/modules/tab-store.js
+++ b/devtools/client/webide/modules/tab-store.js
@@ -2,17 +2,16 @@
  * 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 { 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 } = require("devtools/shared/task");
 
 const _knownTabStores = new WeakMap();
 
 var TabStore;
 
 module.exports = TabStore = function (connection) {
   // If we already know about this connection,
@@ -90,35 +89,36 @@ TabStore.prototype = {
     }
     this._selectedTab.url = url;
     this._selectedTab.title = title;
     this.emit("navigate");
   },
 
   listTabs: function () {
     if (!this._connection || !this._connection.client) {
-      return promise.reject(new Error("Can't listTabs, not connected."));
+      return Promise.reject(new Error("Can't listTabs, not connected."));
     }
-    let deferred = promise.defer();
-    this._connection.client.listTabs(response => {
-      if (response.error) {
-        this._connection.disconnect();
-        deferred.reject(response.error);
-        return;
-      }
-      let tabsChanged = JSON.stringify(this.tabs) !== JSON.stringify(response.tabs);
-      this.response = response;
-      this.tabs = response.tabs;
-      this._checkSelectedTab();
-      if (tabsChanged) {
-        this.emit("tab-list");
-      }
-      deferred.resolve(response);
+
+    return new Promise((resolve, reject) => {
+      this._connection.client.listTabs(response => {
+        if (response.error) {
+          this._connection.disconnect();
+          reject(response.error);
+          return;
+        }
+        let tabsChanged = JSON.stringify(this.tabs) !== JSON.stringify(response.tabs);
+        this.response = response;
+        this.tabs = response.tabs;
+        this._checkSelectedTab();
+        if (tabsChanged) {
+          this.emit("tab-list");
+        }
+        resolve(response);
+      });
     });
-    return deferred.promise;
   },
 
   // TODO: Tab "selection" should really take place by creating a TabProject
   // which is the selected project.  This should be done as part of the
   // project-agnostic work.
   _selectedTab: null,
   _selectedTabTargetPromise: null,
   get selectedTab() {
--- a/devtools/client/webide/test/browser_tabs.js
+++ b/devtools/client/webide/test/browser_tabs.js
@@ -59,22 +59,22 @@ function test() {
     yield win.Cmds.disconnectRuntime();
     yield closeWebIDE(win);
 
     DebuggerServer.destroy();
   }).then(finish, handleError);
 }
 
 function connectToLocal(win, docRuntime) {
-  let deferred = promise.defer();
-  win.AppManager.connection.once(
+  return new Promise(resolve => {
+    win.AppManager.connection.once(
       win.Connection.Events.CONNECTED,
-      () => deferred.resolve());
-  docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
-  return deferred.promise;
+      resolve);
+    docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
+  });
 }
 
 function selectTabProject(win, docProject) {
   return Task.spawn(function* () {
     yield waitForUpdate(win, "runtime-targets");
     let tabsNode = docProject.querySelector("#project-panel-tabs");
     let tabNode = tabsNode.querySelectorAll(".panel-item")[1];
     let project = waitForUpdate(win, "project");
--- a/devtools/client/webide/test/head.js
+++ b/devtools/client/webide/test/head.js
@@ -3,17 +3,16 @@
 
 "use strict";
 
 var {utils: Cu, classes: Cc, interfaces: Ci} = Components;
 
 const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
 const { gDevTools } = require("devtools/client/framework/devtools");
-const promise = require("promise");
 const Services = require("Services");
 const { Task } = require("devtools/shared/task");
 const { AppProjects } = require("devtools/client/webide/modules/app-projects");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { DebuggerServer } = require("devtools/server/main");
 const flags = require("devtools/shared/flags");
 flags.testing = true;
 
@@ -66,130 +65,120 @@ var openWebIDE = Task.async(function* (a
   info("WebIDE open");
 
   return win;
 });
 
 function closeWebIDE(win) {
   info("Closing WebIDE");
 
-  let deferred = promise.defer();
+  return new Promise(resolve => {
+    win.addEventListener("unload", function () {
+      info("WebIDE closed");
+      SimpleTest.executeSoon(resolve);
+    }, {once: true});
 
-  win.addEventListener("unload", function () {
-    info("WebIDE closed");
-    SimpleTest.executeSoon(() => {
-      deferred.resolve();
-    });
-  }, {once: true});
-
-  win.close();
-
-  return deferred.promise;
+    win.close();
+  });
 }
 
 function removeAllProjects() {
   return Task.spawn(function* () {
     yield AppProjects.load();
     // use a new array so we're not iterating over the same
     // underlying array that's being modified by AppProjects
     let projects = AppProjects.projects.map(p => p.location);
     for (let i = 0; i < projects.length; i++) {
       yield AppProjects.remove(projects[i]);
     }
   });
 }
 
 function nextTick() {
-  let deferred = promise.defer();
-  SimpleTest.executeSoon(() => {
-    deferred.resolve();
+  return new Promise(resolve => {
+    SimpleTest.executeSoon(resolve);
   });
-
-  return deferred.promise;
 }
 
 function waitForUpdate(win, update) {
   info("Wait: " + update);
-  let deferred = promise.defer();
-  win.AppManager.on("app-manager-update", function onUpdate(e, what) {
-    info("Got: " + what);
-    if (what !== update) {
-      return;
-    }
-    win.AppManager.off("app-manager-update", onUpdate);
-    deferred.resolve(win.UI._updatePromise);
+  return new Promise(resolve => {
+    win.AppManager.on("app-manager-update", function onUpdate(e, what) {
+      info("Got: " + what);
+      if (what !== update) {
+        return;
+      }
+      win.AppManager.off("app-manager-update", onUpdate);
+      resolve(win.UI._updatePromise);
+    });
   });
-  return deferred.promise;
 }
 
 function waitForTime(time) {
-  let deferred = promise.defer();
-  setTimeout(() => {
-    deferred.resolve();
-  }, time);
-  return deferred.promise;
+  return new Promise(resolve => {
+    setTimeout(resolve, time);
+  });
 }
 
 function documentIsLoaded(doc) {
-  let deferred = promise.defer();
-  if (doc.readyState == "complete") {
-    deferred.resolve();
-  } else {
-    doc.addEventListener("readystatechange", function onChange() {
-      if (doc.readyState == "complete") {
-        doc.removeEventListener("readystatechange", onChange);
-        deferred.resolve();
-      }
-    });
-  }
-  return deferred.promise;
+  return new Promise(resolve => {
+    if (doc.readyState == "complete") {
+      resolve();
+    } else {
+      doc.addEventListener("readystatechange", function onChange() {
+        if (doc.readyState == "complete") {
+          doc.removeEventListener("readystatechange", onChange);
+          resolve();
+        }
+      });
+    }
+  });
 }
 
 function lazyIframeIsLoaded(iframe) {
-  let deferred = promise.defer();
-  iframe.addEventListener("load", function () {
-    deferred.resolve(nextTick());
-  }, {capture: true, once: true});
-  return deferred.promise;
+  return new Promise(resolve => {
+    iframe.addEventListener("load", function () {
+      resolve(nextTick());
+    }, {capture: true, once: true});
+  });
 }
 
 function addTab(aUrl, aWindow) {
   info("Adding tab: " + aUrl);
 
-  let deferred = promise.defer();
-  let targetWindow = aWindow || window;
-  let targetBrowser = targetWindow.gBrowser;
+  return new Promise(resolve => {
+    let targetWindow = aWindow || window;
+    let targetBrowser = targetWindow.gBrowser;
 
-  targetWindow.focus();
-  let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
-  let linkedBrowser = tab.linkedBrowser;
+    targetWindow.focus();
+    let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
+    let linkedBrowser = tab.linkedBrowser;
 
-  BrowserTestUtils.browserLoaded(linkedBrowser).then(function () {
-    info("Tab added and finished loading: " + aUrl);
-    deferred.resolve(tab);
+    BrowserTestUtils.browserLoaded(linkedBrowser).then(function () {
+      info("Tab added and finished loading: " + aUrl);
+      resolve(tab);
+    });
   });
-
-  return deferred.promise;
 }
 
 function removeTab(aTab, aWindow) {
   info("Removing tab.");
 
-  let deferred = promise.defer();
-  let targetWindow = aWindow || window;
-  let targetBrowser = targetWindow.gBrowser;
-  let tabContainer = targetBrowser.tabContainer;
+  return new Promise(resolve => {
+    let targetWindow = aWindow || window;
+    let targetBrowser = targetWindow.gBrowser;
+    let tabContainer = targetBrowser.tabContainer;
 
-  tabContainer.addEventListener("TabClose", function (aEvent) {
-    info("Tab removed and finished closing.");
-    deferred.resolve();
-  }, {once: true});
+    tabContainer.addEventListener("TabClose", function (aEvent) {
+      info("Tab removed and finished closing.");
+      resolve();
+    }, {once: true});
 
-  targetBrowser.removeTab(aTab);
-  return deferred.promise;
+    targetBrowser.removeTab(aTab);
+  });
 }
 
 function getRuntimeDocument(win) {
   return win.document.querySelector("#runtime-listing-panel-details").contentDocument;
 }
 
 function getProjectDocument(win) {
   return win.document.querySelector("#project-listing-panel-details").contentDocument;
--- a/devtools/client/webide/test/test_addons.html
+++ b/devtools/client/webide/test/test_addons.html
@@ -17,92 +17,93 @@
     <script type="application/javascript">
       window.onload = function() {
         SimpleTest.waitForExplicitFinish();
 
         const {GetAvailableAddons} = require("devtools/client/webide/modules/addons");
         const {Devices} = Cu.import("resource://devtools/shared/apps/Devices.jsm");
         const {Simulators} = require("devtools/client/webide/modules/simulators");
 
-        let adbAddonsInstalled = promise.defer();
-        Devices.on("addon-status-updated", function onUpdate1() {
-          Devices.off("addon-status-updated", onUpdate1);
-          adbAddonsInstalled.resolve();
-        });
+        let adbAddonsInstalled;
 
         function getVersion(name) {
           return name.match(/(\d+\.\d+)/)[0];
         }
 
         function onSimulatorInstalled(name) {
-          let deferred = promise.defer();
-          Simulators.on("updated", function onUpdate() {
-            Simulators.findSimulatorAddons().then(addons => {
-              for (let addon of addons) {
-                if (name == addon.name.replace(" Simulator", "")) {
-                  Simulators.off("updated", onUpdate);
-                  nextTick().then(deferred.resolve);
-                  return;
+          return new Promise(resolve => {
+            Simulators.on("updated", function onUpdate() {
+              Simulators.findSimulatorAddons().then(addons => {
+                for (let addon of addons) {
+                  if (name == addon.name.replace(" Simulator", "")) {
+                    Simulators.off("updated", onUpdate);
+                    nextTick().then(resolve);
+                    return;
+                  }
                 }
-              }
+              });
             });
           });
-          return deferred.promise;
         }
 
         function installSimulatorFromUI(doc, name) {
           let li = doc.querySelector('[addon="simulator-' + getVersion(name) + '"]');
           li.querySelector(".install-button").click();
           return onSimulatorInstalled(name);
         }
 
         function uninstallSimulatorFromUI(doc, name) {
-          let deferred = promise.defer();
-          Simulators.on("updated", function onUpdate() {
-            nextTick().then(() => {
-              let li = doc.querySelector('[status="uninstalled"][addon="simulator-' + getVersion(name) + '"]');
-              if (li) {
-                Simulators.off("updated", onUpdate);
-                deferred.resolve();
-              } else {
-                deferred.reject("Can't find item");
-              }
+          return new Promise((resolve, reject) => {
+            Simulators.on("updated", function onUpdate() {
+              nextTick().then(() => {
+                let li = doc.querySelector('[status="uninstalled"][addon="simulator-' + getVersion(name) + '"]');
+                if (li) {
+                  Simulators.off("updated", onUpdate);
+                  resolve();
+                } else {
+                  reject("Can't find item");
+                }
+              });
             });
+            let li = doc.querySelector('[status="installed"][addon="simulator-' + getVersion(name) + '"]');
+            li.querySelector(".uninstall-button").click();
           });
-          let li = doc.querySelector('[status="installed"][addon="simulator-' + getVersion(name) + '"]');
-          li.querySelector(".uninstall-button").click();
-          return deferred.promise;
         }
 
         function uninstallADBFromUI(doc) {
-          let deferred = promise.defer();
-          Devices.on("addon-status-updated", function onUpdate() {
-            nextTick().then(() => {
-              let li = doc.querySelector('[status="uninstalled"][addon="adb"]');
-              if (li) {
-                Devices.off("addon-status-updated", onUpdate);
-                deferred.resolve();
-              } else {
-                deferred.reject("Can't find item");
-              }
-            })
+          return new Promise((resolve, reject) => {
+            Devices.on("addon-status-updated", function onUpdate() {
+              nextTick().then(() => {
+                let li = doc.querySelector('[status="uninstalled"][addon="adb"]');
+                if (li) {
+                  Devices.off("addon-status-updated", onUpdate);
+                  resolve();
+                } else {
+                  reject("Can't find item");
+                }
+              })
+            });
+            let li = doc.querySelector('[status="installed"][addon="adb"]');
+            li.querySelector(".uninstall-button").click();
           });
-          let li = doc.querySelector('[status="installed"][addon="adb"]');
-          li.querySelector(".uninstall-button").click();
-          return deferred.promise;
         }
 
         Task.spawn(function*() {
 
           ok(!Devices.helperAddonInstalled, "Helper not installed");
 
           let win = yield openWebIDE(true);
           let docRuntime = getRuntimeDocument(win);
 
-          yield adbAddonsInstalled.promise;
+          adbAddonsInstalled = new Promise(resolve => {
+            Devices.on("addon-status-updated", function onUpdate1() {
+              Devices.off("addon-status-updated", onUpdate1);
+              resolve();
+            });
+          });
 
           ok(Devices.helperAddonInstalled, "Helper has been auto-installed");
 
           yield nextTick();
 
           let addons = yield GetAvailableAddons();
 
           is(addons.simulators.length, 3, "3 simulator addons to install");
--- a/devtools/client/webide/test/test_autoconnect_runtime.html
+++ b/devtools/client/webide/test/test_autoconnect_runtime.html
@@ -28,17 +28,17 @@
           let docRuntime = getRuntimeDocument(win);
 
           let fakeRuntime = {
             type: "USB",
             connect: function(connection) {
               is(connection, win.AppManager.connection, "connection is valid");
               connection.host = null; // force connectPipe
               connection.connect();
-              return promise.resolve();
+              return Promise.resolve();
             },
 
             get id() {
               return "fakeRuntime";
             },
 
             get name() {
               return "fakeRuntime";
--- a/devtools/client/webide/test/test_basic.html
+++ b/devtools/client/webide/test/test_basic.html
@@ -30,22 +30,23 @@
             let appmgr = win.AppManager;
             ok(appmgr.connection, "App Manager connection ready");
             ok(appmgr.runtimeList, "Runtime list ready");
 
             // test error reporting
             let nbox = win.document.querySelector("#notificationbox");
             let notification =  nbox.getNotificationWithValue("webide:errornotification");
             ok(!notification, "No notification yet");
-            let deferred = promise.defer();
-            nextTick().then(() => {
-              deferred.reject("BOOM!");
+            let deferred = new Promise((resolve, reject) => {
+              nextTick().then(() => {
+                reject("BOOM!");
+              });
             });
             try {
-              yield win.UI.busyUntil(deferred.promise, "xx");
+              yield win.UI.busyUntil(deferred, "xx");
             } catch(e) {/* This *will* fail */}
             notification =  nbox.getNotificationWithValue("webide:errornotification");
             ok(notification, "Error has been reported");
 
             yield closeWebIDE(win);
 
             SimpleTest.finish();
         });
--- a/devtools/client/webide/test/test_fullscreenToolbox.html
+++ b/devtools/client/webide/test/test_fullscreenToolbox.html
@@ -11,34 +11,34 @@
     <script type="application/javascript" src="head.js"></script>
     <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   </head>
 
   <body>
 
     <script type="application/javascript">
       function connectToLocal(win, docRuntime) {
-        let deferred = promise.defer();
-        win.AppManager.connection.once(
-            win.Connection.Events.CONNECTED,
-            () => deferred.resolve());
-        docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
-        return deferred.promise;
+        return new Promise(resolve => {
+          win.AppManager.connection.once(
+              win.Connection.Events.CONNECTED,
+              resolve);
+          docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
+        });
       }
 
       window.onload = function() {
         SimpleTest.waitForExplicitFinish();
 
         Task.spawn(function* () {
           let win = yield openWebIDE();
           let docProject = getProjectDocument(win);
           let docRuntime = getRuntimeDocument(win);
           win.AppManager.update("runtime-list");
 
-          yield connectToLocal(win, docRuntime);
+          connectToLocal(win, docRuntime);
 
           // Select main process
           yield waitForUpdate(win, "runtime-targets");
           SimpleTest.executeSoon(() => {
             docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
           });
 
           yield waitForUpdate(win, "project");
--- a/devtools/client/webide/test/test_runtime.html
+++ b/devtools/client/webide/test/test_runtime.html
@@ -57,39 +57,37 @@
           yield onValidated;
           yield onDetails;
 
           win.AppManager.runtimeList.usb.push({
             connect: function(connection) {
               is(connection, win.AppManager.connection, "connection is valid");
               connection.host = null; // force connectPipe
               connection.connect();
-              return promise.resolve();
+              return Promise.resolve();
             },
 
             get name() {
               return "fakeRuntime";
             }
           });
 
           win.AppManager.runtimeList.usb.push({
             connect: function(connection) {
-              let deferred = promise.defer();
-              return deferred.promise;
+              return new Promise(() => {});
             },
 
             get name() {
               return "infiniteRuntime";
             }
           });
 
           win.AppManager.runtimeList.usb.push({
             connect: function(connection) {
-              let deferred = promise.defer();
-              return deferred.promise;
+              return new Promise(() => {});
             },
 
             prolongedConnection: true,
 
             get name() {
               return "prolongedRuntime";
             }
           });
@@ -159,45 +157,44 @@
           // Toolbox opens automatically for main process / runtime apps
           ok(win.UI.toolboxPromise, "Toolbox promise exists");
           yield win.UI.toolboxPromise;
 
           yield win.Cmds.disconnectRuntime();
 
           Services.prefs.setIntPref("devtools.webide.busyTimeout", 100);
 
-          // Wait for error message since connection never completes
-          let errorDeferred = promise.defer();
-          win.UI.reportError = errorName => {
-            if (errorName === "error_operationTimeout") {
-              errorDeferred.resolve();
-            }
-          };
-
           // Click the infinite runtime
           items[1].click();
           ok(win.document.querySelector("window").className, "busy", "UI is busy");
-          yield errorDeferred.promise;
 
-          // Check for unexpected error message since this is prolonged
-          let noErrorDeferred = promise.defer();
-          win.UI.reportError = errorName => {
-            if (errorName === "error_operationTimeout") {
-              noErrorDeferred.reject();
-            }
-          };
+          // Wait for error message since connection never completes
+          let errorDeferred = new Promise(resolve => {
+            win.UI.reportError = errorName => {
+              if (errorName === "error_operationTimeout") {
+                resolve();
+              }
+            };
+          });
 
           // Click the prolonged runtime
           items[2].click();
           ok(win.document.querySelector("window").className, "busy", "UI is busy");
 
-          setTimeout(() => {
-            noErrorDeferred.resolve();
-          }, 1000);
+          // Check for unexpected error message since this is prolonged
+          let noErrorDeferred = new Promise((resolve, reject) => {
+            win.UI.reportError = errorName => {
+              if (errorName === "error_operationTimeout") {
+                reject();
+              }
+            };
 
-          yield noErrorDeferred.promise;
+            setTimeout(() => {
+              resolve();
+            }, 1000);
+          });
 
           SimpleTest.finish();
         });
       }
     </script>
   </body>
 </html>
--- a/devtools/client/webide/test/test_simulators.html
+++ b/devtools/client/webide/test/test_simulators.html
@@ -24,75 +24,76 @@
         const { getDevices } = require("devtools/client/shared/devices");
         const { Simulator, Simulators } = require("devtools/client/webide/modules/simulators");
         const { AddonSimulatorProcess,
                 OldAddonSimulatorProcess,
                 CustomSimulatorProcess } = require("devtools/client/webide/modules/simulator-process");
 
         function addonStatus(addon, status) {
           if (addon.status == status) {
-            return promise.resolve();
+            return Promise.resolve();
           }
-          let deferred = promise.defer();
-          addon.on("update", function onUpdate() {
-            if (addon.status == status) {
-              addon.off("update", onUpdate);
-              nextTick().then(() => deferred.resolve());
-            }
+          return new Promise(resolve => {
+            addon.on("update", function onUpdate() {
+              if (addon.status == status) {
+                addon.off("update", onUpdate);
+                nextTick().then(() => resolve());
+              }
+            });
           });
-          return deferred.promise;
         }
 
         function waitForUpdate(length) {
           info(`Wait for update with length ${length}`);
-          let deferred = promise.defer();
-          let handler = (_, data) => {
-            if (data.length != length) {
-              return;
-            }
-            info(`Got update with length ${length}`);
-            Simulators.off("updated", handler);
-            deferred.resolve();
-          };
-          Simulators.on("updated", handler);
-          return deferred.promise;
+          return new Promise(resolve => {
+            let handler = (_, data) => {
+              if (data.length != length) {
+                return;
+              }
+              info(`Got update with length ${length}`);
+              Simulators.off("updated", handler);
+              resolve();
+            };
+            Simulators.on("updated", handler);
+          });
         }
 
         Task.spawn(function* () {
           let win = yield openWebIDE(false);
 
           yield Simulators._load();
 
           let docRuntime = getRuntimeDocument(win);
           let find = win.document.querySelector.bind(docRuntime);
           let findAll = win.document.querySelectorAll.bind(docRuntime);
 
           let simulatorList = find("#runtime-panel-simulator");
           let simulatorPanel = win.document.querySelector("#deck-panel-simulator");
 
           // Hack SimulatorProcesses to spy on simulation parameters.
 
-          let runPromise;
-          function fakeRun() {
-            runPromise.resolve({
+          let resolver;
+	  function fakeRun() {
+            resolver({
               path: this.b2gBinary.path,
               args: this.args
             });
             // Don't actually try to connect to the fake simulator.
             throw new Error("Aborting on purpose before connection.");
           }
 
           AddonSimulatorProcess.prototype.run = fakeRun;
           OldAddonSimulatorProcess.prototype.run = fakeRun;
           CustomSimulatorProcess.prototype.run = fakeRun;
 
           function runSimulator(i) {
-            runPromise = promise.defer();
-            findAll(".runtime-panel-item-simulator")[i].click();
-            return runPromise.promise;
+            return new Promise(resolve => {
+              resolver = resolve;
+              findAll(".runtime-panel-item-simulator")[i].click();
+            });
           }
 
           // Install fake "Firefox OS 1.0" simulator addon.
 
           let addons = yield GetAvailableAddons();
 
           let sim10 = addons.simulators.filter(a => a.version == "1.0")[0];
 
--- a/devtools/client/webide/test/test_toolbox.html
+++ b/devtools/client/webide/test/test_toolbox.html
@@ -37,20 +37,21 @@
           }
 
           win = yield openWebIDE();
           let docRuntime = getRuntimeDocument(win);
           let docProject = getProjectDocument(win);
 
           win.AppManager.update("runtime-list");
 
-          let deferred = promise.defer();
-          win.AppManager.connection.once(
-              win.Connection.Events.CONNECTED,
-              () => deferred.resolve());
+          let deferred = new Promise(resolve => {
+             win.AppManager.connection.once(
+                 win.Connection.Events.CONNECTED,
+                 resolve);
+          });
 
           docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
 
           ok(win.document.querySelector("window").className, "busy", "UI is busy");
           yield win.UI._busyPromise;
 
           is(Object.keys(DebuggerServer._connections).length, 1, "Connected");