Bug 1034599 - Convert remaining Promise.defer() uses to PromiseUtils.defer() or new Promise(), r=mconley.
authorFlorian Quèze <florian@queze.net>
Fri, 23 Jun 2017 11:25:02 +0200
changeset 365994 ea3fb9e7622e2f890d45cc2f45cd472c6cf45935
parent 365993 4da7ff4c92bf47c1ceb8383da4cc459e84a95e08
child 365995 9c7e4d4547b752ee3bb9b603218d143ffe9f6c49
push id32090
push usercbook@mozilla.com
push dateMon, 26 Jun 2017 11:27:03 +0000
treeherdermozilla-central@af9a8cebd43f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1034599
milestone56.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 1034599 - Convert remaining Promise.defer() uses to PromiseUtils.defer() or new Promise(), r=mconley.
accessible/jsat/Gestures.jsm
browser/components/translation/BingTranslator.jsm
browser/components/translation/YandexTranslator.jsm
browser/components/uitour/UITour.jsm
browser/experiments/Experiments.jsm
browser/modules/ContentSearch.jsm
browser/modules/DirectoryLinksProvider.jsm
browser/modules/Social.jsm
toolkit/components/asyncshutdown/AsyncShutdown.jsm
toolkit/components/crashmonitor/CrashMonitor.jsm
toolkit/components/jsdownloads/src/DownloadCore.jsm
toolkit/components/jsdownloads/src/DownloadLegacy.js
toolkit/components/osfile/modules/osfile_async_front.jsm
toolkit/components/passwordmgr/LoginManagerContent.jsm
toolkit/components/promiseworker/PromiseWorker.jsm
toolkit/components/search/SearchSuggestionController.jsm
toolkit/components/search/nsSearchService.js
toolkit/components/telemetry/TelemetryController.jsm
toolkit/modules/DeferredTask.jsm
toolkit/modules/GMPInstallManager.jsm
toolkit/modules/PopupNotifications.jsm
toolkit/mozapps/extensions/DeferredSave.jsm
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -45,18 +45,18 @@ Cu.import('resource://gre/modules/XPCOMU
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils', // jshint ignore:line
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Logger', // jshint ignore:line
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout', // jshint ignore:line
   'resource://gre/modules/Timer.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'clearTimeout', // jshint ignore:line
   'resource://gre/modules/Timer.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Promise', // jshint ignore:line
-  'resource://gre/modules/Promise.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'PromiseUtils', // jshint ignore:line
+  'resource://gre/modules/PromiseUtils.jsm');
 
 // Default maximum duration of swipe
 const SWIPE_MAX_DURATION = 200;
 // Default maximum amount of time allowed for a gesture to be considered a
 // multitouch
 const MAX_MULTITOUCH = 125;
 // Default maximum consecutive pointer event timeout
 const MAX_CONSECUTIVE_GESTURE_DELAY = 200;
@@ -319,17 +319,17 @@ function compileDetail(aType, aPoints, k
  * Default is an empty object.
  * @param {?String} aLastEvent Last pointer event type.
  */
 function Gesture(aTimeStamp, aPoints = {}, aLastEvent = undefined) {
   this.startTime = Date.now();
   Logger.gesture('Creating', this.id, 'gesture.');
   this.points = aPoints;
   this.lastEvent = aLastEvent;
-  this._deferred = Promise.defer();
+  this._deferred = PromiseUtils.defer();
   // Call this._handleResolve or this._handleReject when the promise is
   // fulfilled with either resolve or reject.
   this.promise = this._deferred.promise.then(this._handleResolve.bind(this),
     this._handleReject.bind(this));
   this.startTimer(aTimeStamp);
 }
 
 Gesture.prototype = {
--- a/browser/components/translation/BingTranslator.jsm
+++ b/browser/components/translation/BingTranslator.jsm
@@ -5,17 +5,17 @@
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 this.EXPORTED_SYMBOLS = [ "BingTranslator" ];
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 Cu.import("resource://services-common/utils.js");
 Cu.import("resource://gre/modules/Http.jsm");
 
 // The maximum amount of net data allowed per request on Bing's API.
 const MAX_REQUEST_DATA = 5000; // Documentation says 10000 but anywhere
                                // close to that is refused by the service.
 
 // The maximum number of chunks allowed to be translated in a single
@@ -55,17 +55,17 @@ this.BingTranslator.prototype = {
    * respecting the data limits of the API.
    *
    * @returns {Promise}          A promise that will resolve when the translation
    *                             task is finished.
    */
   translate() {
     return (async () => {
       let currentIndex = 0;
-      this._onFinishedDeferred = Promise.defer();
+      this._onFinishedDeferred = PromiseUtils.defer();
 
       // Let's split the document into various requests to be sent to
       // Bing's Translation API.
       for (let requestCount = 0; requestCount < MAX_REQUESTS; requestCount++) {
         // Generating the text for each request can be expensive, so
         // let's take the opportunity of the chunkification process to
         // allow for the event loop to attend other pending events
         // before we continue.
@@ -384,48 +384,47 @@ var BingTokenManager = {
       ["grant_type", "client_credentials"],
       ["scope", "http://api.microsofttranslator.com"],
       ["client_id",
       getUrlParam("%BING_API_CLIENTID%", "browser.translation.bing.clientIdOverride")],
       ["client_secret",
       getUrlParam("%BING_API_KEY%", "browser.translation.bing.apiKeyOverride")]
     ];
 
-    let deferred = Promise.defer();
-    let options = {
-      onLoad(responseText, xhr) {
-        BingTokenManager._pendingRequest = null;
-        try {
-          let json = JSON.parse(responseText);
+    this._pendingRequest = new Promise((resolve, reject) => {
+      let options = {
+        onLoad(responseText, xhr) {
+          BingTokenManager._pendingRequest = null;
+          try {
+            let json = JSON.parse(responseText);
 
-          if (json.error) {
-            deferred.reject(json.error);
-            return;
-          }
+            if (json.error) {
+              reject(json.error);
+              return;
+            }
 
-          let token = json.access_token;
-          let expires_in = json.expires_in;
-          BingTokenManager._currentToken = token;
-          BingTokenManager._currentExpiryTime = new Date(Date.now() + expires_in * 1000);
-          deferred.resolve(token);
-        } catch (e) {
-          deferred.reject(e);
-        }
-      },
-      onError(e, responseText, xhr) {
-        BingTokenManager._pendingRequest = null;
-        deferred.reject(e);
-      },
-      postData: params
-    };
+            let token = json.access_token;
+            let expires_in = json.expires_in;
+            BingTokenManager._currentToken = token;
+            BingTokenManager._currentExpiryTime = new Date(Date.now() + expires_in * 1000);
+            resolve(token);
+          } catch (e) {
+            reject(e);
+          }
+        },
+        onError(e, responseText, xhr) {
+          BingTokenManager._pendingRequest = null;
+          reject(e);
+        },
+        postData: params
+      };
 
-    this._pendingRequest = deferred.promise;
-    httpRequest(url, options);
-
-    return deferred.promise;
+      httpRequest(url, options);
+    });
+    return this._pendingRequest;
   }
 };
 
 /**
  * Escape a string to be valid XML content.
  */
 function escapeXML(aStr) {
   return aStr.toString()
--- a/browser/components/translation/YandexTranslator.jsm
+++ b/browser/components/translation/YandexTranslator.jsm
@@ -5,17 +5,17 @@
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 this.EXPORTED_SYMBOLS = [ "YandexTranslator" ];
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 Cu.import("resource://services-common/utils.js");
 Cu.import("resource://gre/modules/Http.jsm");
 
 // The maximum amount of net data allowed per request on Bing's API.
 const MAX_REQUEST_DATA = 5000; // Documentation says 10000 but anywhere
                                // close to that is refused by the service.
 
 // The maximum number of chunks allowed to be translated in a single
@@ -73,17 +73,17 @@ this.YandexTranslator.prototype = {
    * respecting the data limits of the API.
    *
    * @returns {Promise}          A promise that will resolve when the translation
    *                             task is finished.
    */
   translate() {
     return (async () => {
       let currentIndex = 0;
-      this._onFinishedDeferred = Promise.defer();
+      this._onFinishedDeferred = PromiseUtils.defer();
 
       // Let's split the document into various requests to be sent to
       // Yandex's Translation API.
       for (let requestCount = 0; requestCount < MAX_REQUESTS; requestCount++) {
         // Generating the text for each request can be expensive, so
         // let's take the opportunity of the chunkification process to
         // allow for the event loop to attend other pending events
         // before we continue.
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -936,57 +936,55 @@ this.UITour = {
     let targetStyle = aElement.ownerGlobal.getComputedStyle(aElement);
     return !aElement.ownerDocument.hidden &&
              targetStyle.display != "none" &&
              targetStyle.visibility == "visible";
   },
 
   getTarget(aWindow, aTargetName, aSticky = false) {
     log.debug("getTarget:", aTargetName);
-    let deferred = Promise.defer();
     if (typeof aTargetName != "string" || !aTargetName) {
       log.warn("getTarget: Invalid target name specified");
-      deferred.reject("Invalid target name specified");
-      return deferred.promise;
+      return Promise.reject("Invalid target name specified");
     }
 
     let targetObject = this.targets.get(aTargetName);
     if (!targetObject) {
       log.warn("getTarget: The specified target name is not in the allowed set");
-      deferred.reject("The specified target name is not in the allowed set");
-      return deferred.promise;
+      return Promise.reject("The specified target name is not in the allowed set");
     }
 
-    let targetQuery = targetObject.query;
-    aWindow.PanelUI.ensureReady().then(() => {
-      let node;
-      if (typeof targetQuery == "function") {
-        try {
-          node = targetQuery(aWindow.document);
-        } catch (ex) {
-          log.warn("getTarget: Error running target query:", ex);
-          node = null;
+    return new Promise(resolve => {
+      let targetQuery = targetObject.query;
+      aWindow.PanelUI.ensureReady().then(() => {
+        let node;
+        if (typeof targetQuery == "function") {
+          try {
+            node = targetQuery(aWindow.document);
+          } catch (ex) {
+            log.warn("getTarget: Error running target query:", ex);
+            node = null;
+          }
+        } else {
+          node = aWindow.document.querySelector(targetQuery);
         }
-      } else {
-        node = aWindow.document.querySelector(targetQuery);
-      }
 
-      deferred.resolve({
-        addTargetListener: targetObject.addTargetListener,
-        infoPanelOffsetX: targetObject.infoPanelOffsetX,
-        infoPanelOffsetY: targetObject.infoPanelOffsetY,
-        infoPanelPosition: targetObject.infoPanelPosition,
-        node,
-        removeTargetListener: targetObject.removeTargetListener,
-        targetName: aTargetName,
-        widgetName: targetObject.widgetName,
-        allowAdd: targetObject.allowAdd,
-      });
-    }).catch(log.error);
-    return deferred.promise;
+        resolve({
+          addTargetListener: targetObject.addTargetListener,
+          infoPanelOffsetX: targetObject.infoPanelOffsetX,
+          infoPanelOffsetY: targetObject.infoPanelOffsetY,
+          infoPanelPosition: targetObject.infoPanelPosition,
+          node,
+          removeTargetListener: targetObject.removeTargetListener,
+          targetName: aTargetName,
+          widgetName: targetObject.widgetName,
+          allowAdd: targetObject.allowAdd,
+        });
+      }).catch(log.error);
+    });
   },
 
   targetIsInAppMenu(aTarget) {
     let placement = CustomizableUI.getPlacementOfWidget(aTarget.widgetName || aTarget.node.id);
     if (placement && placement.area == CustomizableUI.AREA_PANEL) {
       return true;
     }
 
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -1754,116 +1754,114 @@ Experiments.ExperimentEntry.prototype = 
     this._log.trace("start() for " + this.id);
 
     this._enabled = true;
     return await this.reconcileAddonState();
   },
 
   // Async install of the addon for this experiment, part of the start task above.
   async _installAddon() {
-    let deferred = Promise.defer();
-
     let hash = this._policy.ignoreHashes ? null : this._manifestData.xpiHash;
 
     let install = await addonInstallForURL(this._manifestData.xpiURL, hash);
     gActiveInstallURLs.add(install.sourceURI.spec);
 
-    let failureHandler = (failureInstall, handler) => {
-      let message = "AddonInstall " + handler + " for " + this.id + ", state=" +
-                   (failureInstall.state || "?") + ", error=" + failureInstall.error;
-      this._log.error("_installAddon() - " + message);
-      this._failedStart = true;
-      gActiveInstallURLs.delete(failureInstall.sourceURI.spec);
-
-      TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY,
-                      [TELEMETRY_LOG.ACTIVATION.INSTALL_FAILURE, this.id]);
-
-      deferred.reject(new Error(message));
-    };
-
-    let listener = {
-      _expectedID: null,
-
-      onDownloadEnded: downloadEndedInstall => {
-        this._log.trace("_installAddon() - onDownloadEnded for " + this.id);
-
-        if (downloadEndedInstall.existingAddon) {
-          this._log.warn("_installAddon() - onDownloadEnded, addon already installed");
-        }
-
-        if (downloadEndedInstall.addon.type !== "experiment") {
-          this._log.error("_installAddon() - onDownloadEnded, wrong addon type");
-          downloadEndedInstall.cancel();
-        }
-      },
-
-      onInstallStarted: installStartedInstall => {
-        this._log.trace("_installAddon() - onInstallStarted for " + this.id);
-
-        if (installStartedInstall.existingAddon) {
-          this._log.warn("_installAddon() - onInstallStarted, addon already installed");
-        }
-
-        if (installStartedInstall.addon.type !== "experiment") {
-          this._log.error("_installAddon() - onInstallStarted, wrong addon type");
-          return false;
-        }
-        return undefined;
-      },
-
-      onInstallEnded: installEndedInstall => {
-        this._log.trace("_installAddon() - install ended for " + this.id);
-        gActiveInstallURLs.delete(installEndedInstall.sourceURI.spec);
-
-        this._lastChangedDate = this._policy.now();
-        this._startDate = this._policy.now();
-        this._enabled = true;
+    return await new Promise((resolve, reject) => {
+      let failureHandler = (failureInstall, handler) => {
+        let message = "AddonInstall " + handler + " for " + this.id + ", state=" +
+                     (failureInstall.state || "?") + ", error=" + failureInstall.error;
+        this._log.error("_installAddon() - " + message);
+        this._failedStart = true;
+        gActiveInstallURLs.delete(failureInstall.sourceURI.spec);
 
         TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY,
-                       [TELEMETRY_LOG.ACTIVATION.ACTIVATED, this.id]);
+                        [TELEMETRY_LOG.ACTIVATION.INSTALL_FAILURE, this.id]);
+
+        reject(new Error(message));
+      };
 
-        let addon = installEndedInstall.addon;
-        this._name = addon.name;
-        this._addonId = addon.id;
-        this._description = addon.description || "";
-        this._homepageURL = addon.homepageURL || "";
+      let listener = {
+        _expectedID: null,
+
+        onDownloadEnded: downloadEndedInstall => {
+          this._log.trace("_installAddon() - onDownloadEnded for " + this.id);
+
+          if (downloadEndedInstall.existingAddon) {
+            this._log.warn("_installAddon() - onDownloadEnded, addon already installed");
+          }
 
-        // Experiment add-ons default to userDisabled=true. Enable if needed.
-        if (addon.userDisabled) {
-          this._log.trace("Add-on is disabled. Enabling.");
-          listener._expectedID = addon.id;
-          AddonManager.addAddonListener(listener);
-          addon.userDisabled = false;
-        } else {
-          this._log.trace("Add-on is enabled. start() completed.");
-          deferred.resolve();
-        }
-      },
+          if (downloadEndedInstall.addon.type !== "experiment") {
+            this._log.error("_installAddon() - onDownloadEnded, wrong addon type");
+            downloadEndedInstall.cancel();
+          }
+        },
+
+        onInstallStarted: installStartedInstall => {
+          this._log.trace("_installAddon() - onInstallStarted for " + this.id);
+
+          if (installStartedInstall.existingAddon) {
+            this._log.warn("_installAddon() - onInstallStarted, addon already installed");
+          }
+
+          if (installStartedInstall.addon.type !== "experiment") {
+            this._log.error("_installAddon() - onInstallStarted, wrong addon type");
+            return false;
+          }
+          return undefined;
+        },
+
+        onInstallEnded: installEndedInstall => {
+          this._log.trace("_installAddon() - install ended for " + this.id);
+          gActiveInstallURLs.delete(installEndedInstall.sourceURI.spec);
 
-      onEnabled: addon => {
-        this._log.info("onEnabled() for " + addon.id);
+          this._lastChangedDate = this._policy.now();
+          this._startDate = this._policy.now();
+          this._enabled = true;
 
-        if (addon.id != listener._expectedID) {
-          return;
-        }
+          TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY,
+                         [TELEMETRY_LOG.ACTIVATION.ACTIVATED, this.id]);
+
+          let addon = installEndedInstall.addon;
+          this._name = addon.name;
+          this._addonId = addon.id;
+          this._description = addon.description || "";
+          this._homepageURL = addon.homepageURL || "";
 
-        AddonManager.removeAddonListener(listener);
-        deferred.resolve();
-      },
-    };
+          // Experiment add-ons default to userDisabled=true. Enable if needed.
+          if (addon.userDisabled) {
+            this._log.trace("Add-on is disabled. Enabling.");
+            listener._expectedID = addon.id;
+            AddonManager.addAddonListener(listener);
+            addon.userDisabled = false;
+          } else {
+            this._log.trace("Add-on is enabled. start() completed.");
+            resolve();
+          }
+        },
+
+        onEnabled: addon => {
+          this._log.info("onEnabled() for " + addon.id);
 
-    ["onDownloadCancelled", "onDownloadFailed", "onInstallCancelled", "onInstallFailed"]
-      .forEach(what => {
-        listener[what] = eventInstall => failureHandler(eventInstall, what)
-      });
+          if (addon.id != listener._expectedID) {
+            return;
+          }
+
+          AddonManager.removeAddonListener(listener);
+          resolve();
+        },
+      };
 
-    install.addListener(listener);
-    install.install();
+      ["onDownloadCancelled", "onDownloadFailed", "onInstallCancelled", "onInstallFailed"]
+        .forEach(what => {
+          listener[what] = eventInstall => failureHandler(eventInstall, what)
+        });
 
-    return await deferred.promise;
+      install.addListener(listener);
+      install.install();
+    });
   },
 
   /**
    * Stop running the experiment if it is active.
    *
    * @param terminationKind (optional)
    *        The termination kind, e.g. ADDON_UNINSTALLED or EXPIRED.
    * @param terminationReason (optional)
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -542,15 +542,14 @@ this.ContentSearch = {
       if (!(prop in data)) {
         throw new Error("Message data missing required property: " + prop);
       }
     }
   },
 
   _initService() {
     if (!this._initServicePromise) {
-      let deferred = Promise.defer();
-      this._initServicePromise = deferred.promise;
-      Services.search.init(() => deferred.resolve());
+      this._initServicePromise =
+        new Promise(resolve => Services.search.init(resolve));
     }
     return this._initServicePromise;
   },
 };
--- a/browser/modules/DirectoryLinksProvider.jsm
+++ b/browser/modules/DirectoryLinksProvider.jsm
@@ -9,18 +9,18 @@ this.EXPORTED_SYMBOLS = ["DirectoryLinks
 const Cu = Components.utils;
 Cu.importGlobalProperties(["XMLHttpRequest"]);
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
   "resource://gre/modules/osfile.jsm")
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
-  "resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
+  "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
   "resource://gre/modules/UpdateUtils.jsm");
 XPCOMUtils.defineLazyGetter(this, "gTextDecoder", () => {
   return new TextDecoder();
 });
 
 
 // The filename where directory links are stored locally
@@ -188,17 +188,17 @@ var DirectoryLinksProvider = {
    */
   _fetchAndCacheLinksIfNecessary: function DirectoryLinksProvider_fetchAndCacheLinksIfNecessary(forceDownload = false) {
     if (this._downloadDeferred) {
       // fetching links already - just return the promise
       return this._downloadDeferred.promise;
     }
 
     if (forceDownload || this._needsDownload) {
-      this._downloadDeferred = Promise.defer();
+      this._downloadDeferred = PromiseUtils.defer();
       this._fetchAndCacheLinks(this._linksURL).then(() => {
         // the new file was successfully downloaded and cached, so update a timestamp
         this._lastDownloadMS = Date.now();
         this._downloadDeferred.resolve();
         this._downloadDeferred = null;
         this._callObservers("onManyLinksChanged")
       },
       error => {
--- a/browser/modules/Social.jsm
+++ b/browser/modules/Social.jsm
@@ -22,29 +22,29 @@ Cu.import("resource://gre/modules/XPCOMU
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
   "resource:///modules/SocialService.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata",
   "resource://gre/modules/PageMetadata.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
   "resource://gre/modules/PlacesUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
-  "resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
+  "resource://gre/modules/PromiseUtils.jsm");
 
 
 this.Social = {
   initialized: false,
   lastEventReceived: 0,
   providers: [],
   _disabledForSafeMode: false,
 
   init: function Social_init() {
     this._disabledForSafeMode = Services.appinfo.inSafeMode && this.enabled;
-    let deferred = Promise.defer();
+    let deferred = PromiseUtils.defer();
 
     if (this.initialized) {
       deferred.resolve(true);
       return deferred.promise;
     }
     this.initialized = true;
     // if SocialService.hasEnabledProviders, retreive the providers so the
     // front-end can generate UI
--- a/toolkit/components/asyncshutdown/AsyncShutdown.jsm
+++ b/toolkit/components/asyncshutdown/AsyncShutdown.jsm
@@ -39,18 +39,16 @@
 "use strict";
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
 Cu.import("resource://gre/modules/Services.jsm", this);
 
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
-  "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
   "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "gDebug",
   "@mozilla.org/xpcom/debug;1", "nsIDebug2");
 Object.defineProperty(this, "gCrashReporter", {
   get() {
@@ -270,17 +268,17 @@ function safeGetState(fetchState) {
  * up to the closest second).
  *
  * @return Deferred
  */
 function looseTimer(delay) {
   let DELAY_BEAT = 1000;
   let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   let beats = Math.ceil(delay / DELAY_BEAT);
-  let deferred = Promise.defer();
+  let deferred = PromiseUtils.defer();
   timer.initWithCallback(function() {
     if (beats <= 0) {
       deferred.resolve();
     }
     --beats;
   }, DELAY_BEAT, Ci.nsITimer.TYPE_REPEATING_PRECISE_CAN_SKIP);
   // Ensure that the timer is both canceled once we are done with it
   // and not garbage-collected until then.
--- a/toolkit/components/crashmonitor/CrashMonitor.jsm
+++ b/toolkit/components/crashmonitor/CrashMonitor.jsm
@@ -33,17 +33,17 @@
 
 this.EXPORTED_SYMBOLS = [ "CrashMonitor" ];
 
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 Cu.import("resource://gre/modules/AsyncShutdown.jsm");
 
 const NOTIFICATIONS = [
   "final-ui-startup",
   "sessionstore-windows-restored",
   "quit-application-granted",
   "quit-application",
   "profile-change-net-teardown",
@@ -72,17 +72,17 @@ var CrashMonitorInternal = {
    * to an object containing a set of properties, where a property
    * with a value of |true| means that the notification with the same
    * name as the property name was received at least once last
    * session.
    */
   previousCheckpoints: null,
 
   /* Deferred for AsyncShutdown blocker */
-  profileBeforeChangeDeferred: Promise.defer(),
+  profileBeforeChangeDeferred: PromiseUtils.defer(),
 
   /**
    * Path to checkpoint file.
    *
    * Each time a new notification is received, this file is written to
    * disc to reflect the information in |checkpoints|.
    */
   path: OS.Path.join(OS.Constants.Path.profileDir, "sessionCheckpoints.json"),
--- a/toolkit/components/jsdownloads/src/DownloadCore.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadCore.jsm
@@ -61,18 +61,18 @@ Cu.import("resource://gre/modules/Integr
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm")
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
-                                  "resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
+                                  "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gDownloadHistory",
            "@mozilla.org/browser/download-history;1",
            Ci.nsIDownloadHistory);
@@ -141,17 +141,17 @@ const kProgressUpdateIntervalMs = 400;
 // Download
 
 /**
  * Represents a single download, with associated state and actions.  This object
  * is transient, though it can be included in a DownloadList so that it can be
  * managed by the user interface and persisted across sessions.
  */
 this.Download = function() {
-  this._deferSucceeded = Promise.defer();
+  this._deferSucceeded = PromiseUtils.defer();
 }
 
 this.Download.prototype = {
   /**
    * DownloadSource object associated with this download.
    */
   source: null,
 
@@ -380,17 +380,17 @@ this.Download.prototype = {
     this.hasBlockedData = false;
     this.progress = 0;
     this.totalBytes = 0;
     this.currentBytes = 0;
     this.startTime = new Date();
 
     // Create a new deferred object and an associated promise before starting
     // the actual download.  We store it on the download as the current attempt.
-    let deferAttempt = Promise.defer();
+    let deferAttempt = PromiseUtils.defer();
     let currentAttempt = deferAttempt.promise;
     this._currentAttempt = currentAttempt;
 
     // Restart the progress and speed calculations from scratch.
     this._lastProgressTimeMs = 0;
 
     // This function propagates progress from the DownloadSaver object, unless
     // it comes in late from a download attempt that was replaced by a new one.
@@ -768,20 +768,19 @@ this.Download.prototype = {
   cancel: function D_cancel() {
     // If the download is currently stopped, we have nothing to do.
     if (this.stopped) {
       return Promise.resolve();
     }
 
     if (!this._promiseCanceled) {
       // Start a new cancellation request.
-      let deferCanceled = Promise.defer();
-      this._currentAttempt.then(() => deferCanceled.resolve(),
-                                () => deferCanceled.resolve());
-      this._promiseCanceled = deferCanceled.promise;
+      this._promiseCanceled = new Promise(resolve => {
+        this._currentAttempt.then(resolve, resolve);
+      });
 
       // The download can already be restarted.
       this._currentAttempt = null;
 
       // Notify that the cancellation request was received.
       this.canceled = true;
       this._notifyChange();
 
@@ -836,45 +835,38 @@ this.Download.prototype = {
    * @resolves When the partial data has been successfully removed.
    * @rejects JavaScript exception if the operation could not be completed.
    */
   removePartialData() {
     if (!this.canceled && !this.error) {
       return Promise.resolve();
     }
 
-    let promiseRemovePartialData = this._promiseRemovePartialData;
-
-    if (!promiseRemovePartialData) {
-      let deferRemovePartialData = Promise.defer();
-      promiseRemovePartialData = deferRemovePartialData.promise;
-      this._promiseRemovePartialData = promiseRemovePartialData;
-
-      deferRemovePartialData.resolve(
-        (async () => {
-          try {
-            // Wait upon any pending cancellation request.
-            if (this._promiseCanceled) {
-              await this._promiseCanceled;
-            }
-            // Ask the saver object to remove any partial data.
-            await this.saver.removePartialData();
-            // For completeness, clear the number of bytes transferred.
-            if (this.currentBytes != 0 || this.hasPartialData) {
-              this.currentBytes = 0;
-              this.hasPartialData = false;
-              this._notifyChange();
-            }
-          } finally {
-            this._promiseRemovePartialData = null;
+    if (!this._promiseRemovePartialData) {
+      this._promiseRemovePartialData = (async () => {
+        try {
+          // Wait upon any pending cancellation request.
+          if (this._promiseCanceled) {
+            await this._promiseCanceled;
           }
-        })());
+          // Ask the saver object to remove any partial data.
+          await this.saver.removePartialData();
+          // For completeness, clear the number of bytes transferred.
+          if (this.currentBytes != 0 || this.hasPartialData) {
+            this.currentBytes = 0;
+            this.hasPartialData = false;
+            this._notifyChange();
+          }
+        } finally {
+          this._promiseRemovePartialData = null;
+        }
+      })();
     }
 
-    return promiseRemovePartialData;
+    return this._promiseRemovePartialData;
   },
 
   /**
    * This deferred object contains a promise that is resolved as soon as this
    * download finishes successfully, and is never rejected.  This property is
    * initialized when the download is created, and never changes.
    */
   _deferSucceeded: null,
@@ -1920,17 +1912,17 @@ this.DownloadCopySaver.prototype = {
         // the target file.  We cannot translate this into a specific result
         // code, but we preserve the original message using the toString method.
         let error = new DownloadError({ message: ex.toString() });
         error.becauseTargetFailed = true;
         throw error;
       }
 
       try {
-        let deferSaveComplete = Promise.defer();
+        let deferSaveComplete = PromiseUtils.defer();
 
         if (this._canceled) {
           // Don't create the BackgroundFileSaver object if we have been
           // canceled meanwhile.
           throw new DownloadError({ message: "Saver canceled." });
         }
 
         // Create the object that will save the file in a background thread.
@@ -2307,18 +2299,18 @@ this.DownloadCopySaver.fromSerializable 
 // DownloadLegacySaver
 
 /**
  * Saver object that integrates with the legacy nsITransfer interface.
  *
  * For more background on the process, see the DownloadLegacyTransfer object.
  */
 this.DownloadLegacySaver = function() {
-  this.deferExecuted = Promise.defer();
-  this.deferCanceled = Promise.defer();
+  this.deferExecuted = PromiseUtils.defer();
+  this.deferCanceled = PromiseUtils.defer();
 }
 
 this.DownloadLegacySaver.prototype = {
   __proto__: DownloadSaver.prototype,
 
   /**
    * Save the SHA-256 hash in raw bytes of the downloaded file. This may be
    * null when nsExternalHelperAppService (and thus BackgroundFileSaver) is not
--- a/toolkit/components/jsdownloads/src/DownloadLegacy.js
+++ b/toolkit/components/jsdownloads/src/DownloadLegacy.js
@@ -22,18 +22,18 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
                                   "resource://gre/modules/Downloads.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
-                                  "resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
+                                  "resource://gre/modules/PromiseUtils.jsm");
 
 // DownloadLegacyTransfer
 
 /**
  * nsITransfer implementation that provides a bridge to a Download object.
  *
  * Legacy downloads work differently than the JavaScript implementation.  In the
  * latter, the caller only provides the properties for the Download object and
@@ -56,17 +56,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
  * cancellation requests, but after cancellation it cannot be reused again.
  *
  * Since the components that execute the download may be different and they
  * don't always give consistent results, this bridge takes care of enforcing the
  * expectations, for example by ensuring the target file exists when the
  * download is successful, even if the source has a size of zero bytes.
  */
 function DownloadLegacyTransfer() {
-  this._deferDownload = Promise.defer();
+  this._deferDownload = PromiseUtils.defer();
 }
 
 DownloadLegacyTransfer.prototype = {
   classID: Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}"),
 
   // nsISupports
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
--- a/toolkit/components/osfile/modules/osfile_async_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_async_front.jsm
@@ -45,17 +45,18 @@ if (SharedAll.Constants.Win) {
 }
 var OSError = SysAll.Error;
 var Type = SysAll.Type;
 
 var Path = {};
 Cu.import("resource://gre/modules/osfile/ospath.jsm", Path);
 
 // The library of promises.
-Cu.import("resource://gre/modules/Promise.jsm", this);
+XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
+                                  "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
 
 // The implementation of communications
 Cu.import("resource://gre/modules/PromiseWorker.jsm", this);
 Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
 Cu.import("resource://gre/modules/AsyncShutdown.jsm", this);
@@ -271,17 +272,17 @@ var Scheduler = this.Scheduler = {
     // Grab the kill queue to make sure that we
     // cannot be interrupted by another call to `kill`.
     let killQueue = this._killQueue;
 
     // Deactivate the queue, to ensure that no message is sent
     // to an obsolete worker (we reactivate it in the `finally`).
     // This needs to be done right now so that we maintain relative
     // ordering with calls to post(), etc.
-    let deferred = Promise.defer();
+    let deferred = PromiseUtils.defer();
     let savedQueue = this.queue;
     this.queue = deferred.promise;
 
     return this._killQueue = (async () => {
 
       await killQueue;
       // From this point, and until the end of the Task, we are the
       // only call to `kill`, regardless of any `yield`.
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -10,17 +10,17 @@ this.EXPORTED_SYMBOLS = [ "LoginManagerC
 
 const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
 const PASSWORD_INPUT_ADDED_COALESCING_THRESHOLD_MS = 1;
 const AUTOCOMPLETE_AFTER_RIGHT_CLICK_THRESHOLD_MS = 400;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FormLikeFactory",
                                   "resource://gre/modules/FormLikeFactory.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LoginRecipesContent",
                                   "resource://gre/modules/LoginRecipes.jsm");
@@ -241,17 +241,17 @@ var LoginManagerContent = {
       this._managers.set(messageManager, ++count);
     }
 
     let requestId = this._getRandomId();
     messageData.requestId = requestId;
 
     messageManager.sendAsyncMessage(name, messageData);
 
-    let deferred = Promise.defer();
+    let deferred = PromiseUtils.defer();
     requestData.promise = deferred;
     this._requests.set(requestId, requestData);
     return deferred.promise;
   },
 
   receiveMessage(msg, window) {
     if (msg.name == "RemoteLogins:fillForm") {
       this.fillForm({
--- a/toolkit/components/promiseworker/PromiseWorker.jsm
+++ b/toolkit/components/promiseworker/PromiseWorker.jsm
@@ -19,18 +19,18 @@
 
 this.EXPORTED_SYMBOLS = ["BasePromiseWorker"];
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
 
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
-  "resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
+  "resource://gre/modules/PromiseUtils.jsm");
 
 /**
  * An implementation of queues (FIFO).
  *
  * The current implementation uses one array, runs in O(n ^ 2), and is optimized
  * for the case in which queues are generally short.
  */
 function Queue() {
@@ -293,17 +293,17 @@ this.BasePromiseWorker.prototype = {
           // handle raw xpcom errors (see eg bug 961317)
           throw new Components.Exception("Error in postMessage", ex);
         }
 
         this.log("Could not post message", message, "due to error", ex);
         throw ex;
       }
 
-      let deferred = Promise.defer();
+      let deferred = PromiseUtils.defer();
       this._queue.push({deferred, closure, id});
       this.log("Message posted");
 
       let reply;
       try {
         this.log("Expecting reply");
         reply = await deferred.promise;
       } catch (error) {
--- a/toolkit/components/search/SearchSuggestionController.jsm
+++ b/toolkit/components/search/SearchSuggestionController.jsm
@@ -5,17 +5,17 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["SearchSuggestionController"];
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NS_ASSERT", "resource://gre/modules/debug.js");
 
 const SEARCH_RESPONSE_SUGGESTION_JSON = "application/x-suggestions+json";
 const DEFAULT_FORM_HISTORY_PARAM      = "searchbar-history";
 const HTTP_OK            = 200;
 const BROWSER_SUGGEST_PREF = "browser.search.suggest.enabled";
 const REMOTE_TIMEOUT_PREF = "browser.search.suggest.timeout";
 const REMOTE_TIMEOUT_DEFAULT = 500; // maximum time (ms) to wait before giving up on a remote suggestions
@@ -137,18 +137,17 @@ this.SearchSuggestionController.prototyp
     if (searchTerm && gRemoteSuggestionsEnabled && this.maxRemoteResults &&
         engine.supportsResponseType(SEARCH_RESPONSE_SUGGESTION_JSON)) {
       this._deferredRemoteResult = this._fetchRemote(searchTerm, engine, privateMode, userContextId);
       promises.push(this._deferredRemoteResult.promise);
     }
 
     // Local results from form history
     if (this.maxLocalResults) {
-      let deferredHistoryResult = this._fetchFormHistory(searchTerm);
-      promises.push(deferredHistoryResult.promise);
+      promises.push(this._fetchFormHistory(searchTerm));
     }
 
     function handleRejection(reason) {
       if (reason == "HTTP request aborted") {
         // Do nothing since this is normal.
         return null;
       }
       Cu.reportError("SearchSuggestionController rejection: " + reason);
@@ -172,67 +171,66 @@ this.SearchSuggestionController.prototyp
                      "requested");
     }
     this._reset();
   },
 
   // Private methods
 
   _fetchFormHistory(searchTerm) {
-    let deferredFormHistory = Promise.defer();
-
-    let acSearchObserver = {
-      // Implements nsIAutoCompleteSearch
-      onSearchResult: (search, result) => {
-        this._formHistoryResult = result;
+    return new Promise(resolve => {
+      let acSearchObserver = {
+        // Implements nsIAutoCompleteSearch
+        onSearchResult: (search, result) => {
+          this._formHistoryResult = result;
 
-        if (this._request) {
-          this._remoteResultTimer = Cc["@mozilla.org/timer;1"].
-                                    createInstance(Ci.nsITimer);
-          this._remoteResultTimer.initWithCallback(this._onRemoteTimeout.bind(this),
-                                                   this.remoteTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
-        }
+          if (this._request) {
+            this._remoteResultTimer = Cc["@mozilla.org/timer;1"].
+                                      createInstance(Ci.nsITimer);
+            this._remoteResultTimer.initWithCallback(this._onRemoteTimeout.bind(this),
+                                                     this.remoteTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
+          }
 
-        switch (result.searchResult) {
-          case Ci.nsIAutoCompleteResult.RESULT_SUCCESS:
-          case Ci.nsIAutoCompleteResult.RESULT_NOMATCH:
-            if (result.searchString !== this._searchString) {
-              deferredFormHistory.resolve("Unexpected response, this._searchString does not match form history response");
-              return;
-            }
-            let fhEntries = [];
-            for (let i = 0; i < result.matchCount; ++i) {
-              fhEntries.push(result.getValueAt(i));
-            }
-            deferredFormHistory.resolve({
-              result: fhEntries,
-              formHistoryResult: result,
-            });
-            break;
-          case Ci.nsIAutoCompleteResult.RESULT_FAILURE:
-          case Ci.nsIAutoCompleteResult.RESULT_IGNORED:
-            deferredFormHistory.resolve("Form History returned RESULT_FAILURE or RESULT_IGNORED");
-            break;
-        }
-      },
-    };
+          switch (result.searchResult) {
+            case Ci.nsIAutoCompleteResult.RESULT_SUCCESS:
+            case Ci.nsIAutoCompleteResult.RESULT_NOMATCH:
+              if (result.searchString !== this._searchString) {
+                resolve("Unexpected response, this._searchString does not match form history response");
+                return;
+              }
+              let fhEntries = [];
+              for (let i = 0; i < result.matchCount; ++i) {
+                fhEntries.push(result.getValueAt(i));
+              }
+              resolve({
+                result: fhEntries,
+                formHistoryResult: result,
+              });
+              break;
+            case Ci.nsIAutoCompleteResult.RESULT_FAILURE:
+            case Ci.nsIAutoCompleteResult.RESULT_IGNORED:
+              resolve("Form History returned RESULT_FAILURE or RESULT_IGNORED");
+              break;
+          }
+        },
+      };
 
-    let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"].
-                      createInstance(Ci.nsIAutoCompleteSearch);
-    formHistory.startSearch(searchTerm, this.formHistoryParam || DEFAULT_FORM_HISTORY_PARAM,
-                            this._formHistoryResult,
-                            acSearchObserver);
-    return deferredFormHistory;
+      let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"].
+                        createInstance(Ci.nsIAutoCompleteSearch);
+      formHistory.startSearch(searchTerm, this.formHistoryParam || DEFAULT_FORM_HISTORY_PARAM,
+                              this._formHistoryResult,
+                              acSearchObserver);
+    });
   },
 
   /**
    * Fetch suggestions from the search engine over the network.
    */
   _fetchRemote(searchTerm, engine, privateMode, userContextId) {
-    let deferredResponse = Promise.defer();
+    let deferredResponse = PromiseUtils.defer();
     this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
                     createInstance(Ci.nsIXMLHttpRequest);
     let submission = engine.getSubmission(searchTerm,
                                           SEARCH_RESPONSE_SUGGESTION_JSON);
     let method = (submission.postData ? "POST" : "GET");
     this._request.open(method, submission.uri.spec, true);
 
     this._request.setOriginAttributes({userContextId,
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -4,17 +4,17 @@
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 Cu.import("resource://gre/modules/debug.js");
 Cu.import("resource://gre/modules/AppConstants.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
   "resource://gre/modules/AsyncShutdown.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
   "resource://gre/modules/DeferredTask.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
@@ -2639,17 +2639,17 @@ function checkForSyncCompletion(aPromise
 }
 
 // nsIBrowserSearchService
 function SearchService() {
   // Replace empty LOG function with the useful one if the log pref is set.
   if (getBoolPref(BROWSER_SEARCH_PREF + "log", false))
     LOG = DO_LOG;
 
-  this._initObservers = Promise.defer();
+  this._initObservers = PromiseUtils.defer();
 }
 
 SearchService.prototype = {
   classID: Components.ID("{7319788a-fe93-4db3-9f39-818cf08f4256}"),
 
   // The current status of initialization. Note that it does not determine if
   // initialization is complete, only if an error has been encountered so far.
   _initRV: Cr.NS_OK,
@@ -3580,36 +3580,36 @@ SearchService.prototype = {
     if (!chan) {
       LOG("_asyncFindJAREngines: " + APP_SEARCH_PREFIX + " isn't registered");
       return [];
     }
 
     let uris = [];
 
     // Read list.json to find the engines we need to load.
-    let deferred = Promise.defer();
     let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
                     createInstance(Ci.nsIXMLHttpRequest);
     request.overrideMimeType("text/plain");
-    request.onload = function(aEvent) {
-      deferred.resolve(aEvent.target.responseText);
-    };
-    request.onerror = function(aEvent) {
-      LOG("_asyncFindJAREngines: failed to read " + listURL);
-      // Couldn't find list.json, try list.txt
+    let list = await new Promise(resolve => {
+      request.onload = function(aEvent) {
+        resolve(aEvent.target.responseText);
+      };
       request.onerror = function(aEvent) {
-        LOG("_asyncFindJAREngines: failed to read " + APP_SEARCH_PREFIX + "list.txt");
-        deferred.resolve("");
-      }
-      request.open("GET", Services.io.newURI(APP_SEARCH_PREFIX + "list.txt").spec, true);
+        LOG("_asyncFindJAREngines: failed to read " + listURL);
+        // Couldn't find list.json, try list.txt
+        request.onerror = function(aEvent) {
+          LOG("_asyncFindJAREngines: failed to read " + APP_SEARCH_PREFIX + "list.txt");
+          resolve("");
+        }
+        request.open("GET", Services.io.newURI(APP_SEARCH_PREFIX + "list.txt").spec, true);
+        request.send();
+      };
+      request.open("GET", Services.io.newURI(listURL).spec, true);
       request.send();
-    };
-    request.open("GET", Services.io.newURI(listURL).spec, true);
-    request.send();
-    let list = await deferred.promise;
+    });
 
     if (request.responseURL.endsWith(".txt")) {
       this._parseListTxt(list, uris);
     } else {
       this._parseListJSON(list, uris);
     }
     return uris;
   },
--- a/toolkit/components/telemetry/TelemetryController.jsm
+++ b/toolkit/components/telemetry/TelemetryController.jsm
@@ -9,17 +9,17 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 const myScope = this;
 
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
-Cu.import("resource://gre/modules/Promise.jsm", this);
+Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
 Cu.import("resource://gre/modules/DeferredTask.jsm", this);
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://gre/modules/TelemetryUtils.jsm", this);
 Cu.import("resource://gre/modules/AppConstants.jsm");
 
 const Utils = TelemetryUtils;
 
@@ -708,17 +708,17 @@ var Impl = {
     // id from disk.
     // We try to cache it in prefs to avoid this, even though this may
     // lead to some stale client ids.
     this._clientID = ClientID.getCachedClientID();
 
     // Delay full telemetry initialization to give the browser time to
     // run various late initializers. Otherwise our gathered memory
     // footprint and other numbers would be too optimistic.
-    this._delayedInitTaskDeferred = Promise.defer();
+    this._delayedInitTaskDeferred = PromiseUtils.defer();
     this._delayedInitTask = new DeferredTask(async () => {
       try {
         // TODO: This should probably happen after all the delayed init here.
         this._initialized = true;
         TelemetryEnvironment.delayedInit();
 
         // Load the ClientID.
         this._clientID = await ClientID.getClientID();
--- a/toolkit/modules/DeferredTask.jsm
+++ b/toolkit/modules/DeferredTask.jsm
@@ -83,18 +83,18 @@ this.EXPORTED_SYMBOLS = [
  */
 
 // Globals
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
-                                  "resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
+                                  "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
 
 const Timer = Components.Constructor("@mozilla.org/timer;1", "nsITimer",
                                      "initWithCallback");
 
 // DeferredTask
 
@@ -256,17 +256,17 @@ this.DeferredTask.prototype = {
     return Promise.resolve();
   },
   _finalized: false,
 
   /**
    * Timer callback used to run the delayed task.
    */
   _timerCallback() {
-    let runningDeferred = Promise.defer();
+    let runningDeferred = PromiseUtils.defer();
 
     // All these state changes must occur at the same time directly inside the
     // timer callback, to prevent race conditions and to ensure that all the
     // methods behave consistently even if called from inside the task.  This
     // means that the assignment of "this._runningPromise" must complete before
     // the task gets a chance to start.
     this._timer = null;
     this._armed = false;
--- a/toolkit/modules/GMPInstallManager.jsm
+++ b/toolkit/modules/GMPInstallManager.jsm
@@ -16,17 +16,17 @@ var GMPInstallFailureReason = {
   GMP_HIDDEN: 2,
   GMP_DISABLED: 3,
   GMP_UPDATE_DISABLED: 4,
 };
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/GMPUtils.jsm");
 Cu.import("resource://gre/modules/addons/ProductAddonChecker.jsm");
 
 this.EXPORTED_SYMBOLS = ["GMPInstallManager", "GMPExtractor", "GMPDownloader",
                          "GMPAddon"];
@@ -89,17 +89,17 @@ GMPInstallManager.prototype = {
    *           type: Sometimes specifies type of rejection
    */
   checkForAddons() {
     let log = getScopedLogger("GMPInstallManager.checkForAddons");
     if (this._deferred) {
         log.error("checkForAddons already called");
         return Promise.reject({type: "alreadycalled"});
     }
-    this._deferred = Promise.defer();
+    this._deferred = PromiseUtils.defer();
     let url = this._getURL();
 
     let allowNonBuiltIn = true;
     let certs = null;
     if (!Services.prefs.prefHasUserValue(GMPPrefs.KEY_URL_OVERRIDE)) {
       allowNonBuiltIn = !GMPPrefs.get(GMPPrefs.KEY_CERT_REQUIREBUILTIN, true);
       if (GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS, true)) {
         certs = gCertUtils.readCertPrefs(GMPPrefs.KEY_CERTS_BRANCH);
@@ -377,17 +377,17 @@ GMPExtractor.prototype = {
   /**
    * Installs the this.zipPath contents into the directory used to store GMP
    * addons for the current platform.
    *
    * @return a promise which will be resolved or rejected
    *         See GMPInstallManager.installAddon for resolve/rejected info
    */
   install() {
-    this._deferred = Promise.defer();
+    this._deferred = PromiseUtils.defer();
     let deferredPromise = this._deferred;
     let {zipPath, relativeInstallPath} = this;
     let worker =
       new ChromeWorker("resource://gre/modules/GMPExtractorWorker.js");
     worker.onmessage = function(msg) {
       let log = getScopedLogger("GMPExtractor");
       worker.terminate();
       if (msg.data.result != "success") {
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 this.EXPORTED_SYMBOLS = ["PopupNotifications"];
 
 var Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 
 const NOTIFICATION_EVENT_DISMISSED = "dismissed";
 const NOTIFICATION_EVENT_REMOVED = "removed";
 const NOTIFICATION_EVENT_SHOWING = "showing";
 const NOTIFICATION_EVENT_SHOWN = "shown";
 const NOTIFICATION_EVENT_SWAPPING = "swapping";
 
 const ICON_SELECTOR = ".notification-anchor-icon";
@@ -695,17 +695,17 @@ PopupNotifications.prototype = {
    */
   _hidePanel: function PopupNotifications_hide() {
     if (this.panel.state == "closed") {
       return Promise.resolve();
     }
     if (this._ignoreDismissal) {
       return this._ignoreDismissal.promise;
     }
-    let deferred = Promise.defer();
+    let deferred = PromiseUtils.defer();
     this._ignoreDismissal = deferred;
     this.panel.hidePopup();
     return deferred.promise;
   },
 
   /**
    * Removes all notifications from the notification popup.
    */
--- a/toolkit/mozapps/extensions/DeferredSave.jsm
+++ b/toolkit/mozapps/extensions/DeferredSave.jsm
@@ -5,17 +5,17 @@
 "use strict";
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/osfile.jsm");
 /* globals OS*/
-Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
 
 // Make it possible to mock out timers for testing
 var MakeTimer = () => Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 
 this.EXPORTED_SYMBOLS = ["DeferredSave"];
 
 // If delay parameter is not provided, default is 50 milliseconds.
 const DEFAULT_SAVE_DELAY_MS = 50;
@@ -176,17 +176,17 @@ this.DeferredSave.prototype = {
    */
   saveChanges() {
       this.logger.debug("Save changes");
     if (!this._pending) {
       if (this.writeInProgress) {
           this.logger.debug("Data changed while write in progress");
         this.overlappedSaves++;
       }
-      this._pending = Promise.defer();
+      this._pending = PromiseUtils.defer();
       // Wait until the most recent write completes or fails (if it hasn't already)
       // and then restart our timer
       this._writing.then(count => this._startTimer(), error => this._startTimer());
     }
     return this._pending.promise;
   },
 
   _deferredSave() {