DELETE: 1 patches - 939636-toolkit
authorNikhil Marathe <nsm.nikhil@gmail.com>
Wed, 23 Jul 2014 17:33:41 -0700
changeset 1115 1fe757dfd53e1355931e584bd047388fd8e4a9d2
parent 1114 82d7962b2e2891dac83099c833b67b46878fb460
child 1116 af55728bd88e3fafcda4aea08268fa5a25294656
push id32
push usernsm.nikhil@gmail.com
push dateThu, 24 Jul 2014 00:32:46 +0000
bugs939636
DELETE: 1 patches - 939636-toolkit DELETE: 939636-toolkit qparent: 666e5e6b3abf qtip: 666e5e6b3abf top: (none)
939636-toolkit
series
deleted file mode 100644
--- a/939636-toolkit
+++ /dev/null
@@ -1,2654 +0,0 @@
-# HG changeset patch
-# Parent 548aa4c2fb84c3ab22a0722e2742c7d06357e3a0
-# User Nikhil Marathe <nsm.nikhil@gmail.com>
-Bug 939636 - DOM Promise changes in toolkit/ r=?
-
-diff --git a/toolkit/components/osfile/modules/_PromiseWorker.jsm b/toolkit/components/osfile/modules/_PromiseWorker.jsm
---- a/toolkit/components/osfile/modules/_PromiseWorker.jsm
-+++ b/toolkit/components/osfile/modules/_PromiseWorker.jsm
-@@ -2,21 +2,20 @@
-  * Thin wrapper around a ChromeWorker that wraps postMessage/onmessage/onerror
-  * as promises.
-  *
-  * Not for public use yet.
-  */
- 
- "use strict";
- 
-+Components.utils.importGlobalProperties(["Promise"]);
-+
- this.EXPORTED_SYMBOLS = ["PromiseWorker"];
- 
--// The library of promises.
--Components.utils.import("resource://gre/modules/Promise.jsm", this);
--
- /**
-  * 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.
-  */
- let Queue = function Queue() {
-   this._array = [];
-@@ -49,25 +48,25 @@ function PromiseWorker(url, log) {
-   }
-   if (typeof log !== "function") {
-     throw new TypeError("log is expected to be a function");
-   }
-   this._log = log;
-   this._url = url;
- 
-   /**
--   * The queue of deferred, waiting for the completion of their
-+   * The queue of promise resolvers, waiting for the completion of their
-    * respective job by the worker.
-    *
-    * Each item in the list may contain an additional field |closure|,
-    * used to store strong references to value that must not be
-    * garbage-collected before the reply has been received (e.g.
-    * arrays).
-    *
--   * @type {Queue<{deferred:deferred, closure:*=}>}
-+   * @type {Queue<{resolve:Function, reject:Function, closure:*=}>}
-    */
-   this._queue = new Queue();
- 
-   /**
-    * The number of the current message.
-    *
-    * Used for debugging purposes.
-    */
-@@ -95,18 +94,18 @@ PromiseWorker.prototype = {
-      * serializing errors, which transmits these errors through
-      * |worker.onerror|.
-      *
-      * @param {Error} error Some JS error.
-      */
-     worker.onerror = function onerror(error) {
-       self._log("Received uncaught error from worker", error.message, error.filename, error.lineno);
-       error.preventDefault();
--      let {deferred} = self._queue.pop();
--      deferred.reject(error);
-+      let handler = self._queue.pop();
-+      handler.reject(error);
-     };
- 
-     /**
-      * Receive messages from the worker, propagate them to the listeners.
-      *
-      * Messages must have one of the following shapes:
-      * - {ok: some_value} in case of success
-      * - {fail: some_error} in case of error, where
-@@ -118,56 +117,58 @@ PromiseWorker.prototype = {
-      * Messages may also optionally contain a field |durationMs|, holding
-      * the duration of the function call in milliseconds.
-      *
-      * @param {*} msg The message received from the worker.
-      */
-     worker.onmessage = function onmessage(msg) {
-       self._log("Received message from worker", msg.data);
-       let handler = self._queue.pop();
--      let deferred = handler.deferred;
-+      let resolve = handler.resolve;
-+      let reject = handler.reject;
-       let data = msg.data;
-       if (data.id != handler.id) {
-         throw new Error("Internal error: expecting msg " + handler.id + ", " +
-                         " got " + data.id + ": " + JSON.stringify(msg.data));
-       }
-       if ("ok" in data) {
-         // Pass the data to the listeners.
--        deferred.resolve(data);
-+        resolve(data);
-       } else if ("StopIteration" in data) {
-         // We have received a StopIteration error
--        deferred.reject(StopIteration);
-+        reject(StopIteration);
-       } if ("fail" in data) {
-         // We have received an error that was serialized by the
-         // worker.
--        deferred.reject(new PromiseWorker.WorkerError(data.fail));
-+        reject(new PromiseWorker.WorkerError(data.fail));
-       }
-     };
-     return worker;
-   },
- 
-   /**
-    * Post a message to a worker.
-    *
-    * @param {string} fun The name of the function to call.
-    * @param {Array} array The contents of the message.
-    * @param {*=} closure An object holding references that should not be
-    * garbage-collected before the message treatment is complete.
-    *
-    * @return {promise}
-    */
-   post: function post(fun, array, closure) {
--    let deferred = Promise.defer();
-     let id = ++this._id;
-     let message = {fun: fun, args: array, id: id};
-     this._log("Posting message", message);
--    this._queue.push({deferred:deferred, closure: closure, id: id});
-+    let p = new Promise(function(resolve, reject) {
-+      this._queue.push({resolve: resolve, reject: reject, closure: closure, id: id});
-+    }.bind(this));
-     this._worker.postMessage(message);
-     this._log("Message posted");
--    return deferred.promise;
-+    return p;
-   }
- };
- 
- /**
-  * An error that has been serialized by the worker.
-  *
-  * @constructor
-  */
-diff --git a/toolkit/components/osfile/modules/osfile_async_front.jsm b/toolkit/components/osfile/modules/osfile_async_front.jsm
---- a/toolkit/components/osfile/modules/osfile_async_front.jsm
-+++ b/toolkit/components/osfile/modules/osfile_async_front.jsm
-@@ -23,16 +23,17 @@ this.EXPORTED_SYMBOLS = ["OS"];
- 
- const Cu = Components.utils;
- const Ci = Components.interfaces;
- 
- let SharedAll = {};
- Cu.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm", SharedAll);
- Cu.import("resource://gre/modules/Deprecated.jsm", this);
- Cu.import("resource://gre/modules/Timer.jsm", this);
-+Cu.importGlobalProperties(["Promise"]);
- 
- // Boilerplate, to simplify the transition to require()
- let LOG = SharedAll.LOG.bind(SharedAll, "Controller");
- let isTypedArray = SharedAll.isTypedArray;
- 
- // The constructor for file errors.
- let SysAll = {};
- if (SharedAll.Constants.Win) {
-@@ -43,19 +44,16 @@ if (SharedAll.Constants.Win) {
-   throw new Error("I am neither under Windows nor under a Posix system");
- }
- let OSError = SysAll.Error;
- let Type = SysAll.Type;
- 
- let Path = {};
- Cu.import("resource://gre/modules/osfile/ospath.jsm", Path);
- 
--// The library of promises.
--Cu.import("resource://gre/modules/Promise.jsm", this);
--
- // The implementation of communications
- Cu.import("resource://gre/modules/osfile/_PromiseWorker.jsm", this);
- 
- Cu.import("resource://gre/modules/Services.jsm", this);
- 
- Cu.import("resource://gre/modules/AsyncShutdown.jsm", this);
- 
- // If profileDir is not available, osfile.jsm has been imported before the
-diff --git a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
---- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
-+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
-@@ -1,20 +1,20 @@
- "use strict";
- 
- Components.utils.import("resource://gre/modules/osfile.jsm");
--Components.utils.import("resource://gre/modules/Promise.jsm");
- Components.utils.import("resource://gre/modules/Task.jsm");
- Components.utils.import("resource://gre/modules/AsyncShutdown.jsm");
- 
- // The following are used to compare against a well-tested reference
- // implementation of file I/O.
- Components.utils.import("resource://gre/modules/NetUtil.jsm");
- Components.utils.import("resource://gre/modules/FileUtils.jsm");
- Components.utils.import("resource://gre/modules/Services.jsm");
-+Components.utils.importGlobalProperties(["Promise"]);
- 
- let myok = ok;
- let myis = is;
- let myinfo = info;
- let myisnot = isnot;
- 
- let isPromise = function ispromise(value) {
-   return value != null && typeof value == "object" && "then" in value;
-@@ -82,38 +82,34 @@ let maketest = function(prefix, test) {
-  * Used for comparing xpcom-based results to os.file-based results.
-  *
-  * @param {string} path The _absolute_ path to the file.
-  * @return {promise}
-  * @resolves {string} The contents of the file.
-  */
- let reference_fetch_file = function reference_fetch_file(path, test) {
-   test.info("Fetching file " + path);
--  let promise = Promise.defer();
-   let file = new FileUtils.File(path);
--  NetUtil.asyncFetch(file,
--    function(stream, status) {
--      if (!Components.isSuccessCode(status)) {
--        promise.reject(status);
--        return;
--      }
-+
-+  let promise = new Promise(function(resolve, reject) {
-+    NetUtil.asyncFetch(file, function(stream, status) {
-+        if (!Components.isSuccessCode(status)) {
-+          reject(status);
-+        }
-+        resolve(stream);
-+    });
-+  });
-+
-+  return promise.then(function(stream) {
-       let result, reject;
--      try {
--        result = NetUtil.readInputStreamToString(stream, stream.available());
--      } catch (x) {
--        reject = x;
--      }
-+      // If this call throws, the returned promise is rejected.
-+      result = NetUtil.readInputStreamToString(stream, stream.available());
-       stream.close();
--      if (reject) {
--        promise.reject(reject);
--      } else {
--        promise.resolve(result);
--      }
-+      return result;
-   });
--  return promise.promise;
- };
- 
- /**
-  * Compare asynchronously the contents two files using xpcom.
-  *
-  * Used for comparing xpcom-based results to os.file-based results.
-  *
-  * @param {string} a The _absolute_ path to the first file.
-diff --git a/toolkit/components/social/FrameWorker.jsm b/toolkit/components/social/FrameWorker.jsm
---- a/toolkit/components/social/FrameWorker.jsm
-+++ b/toolkit/components/social/FrameWorker.jsm
-@@ -14,17 +14,17 @@
- 
- "use strict";
- 
- const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
- 
- Cu.import("resource://gre/modules/Services.jsm");
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
- Cu.import("resource://gre/modules/MessagePortBase.jsm");
--Cu.import("resource://gre/modules/Promise.jsm");
-+Cu.importGlobalProperties(["Promise"]);
- 
- XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
-   "resource://gre/modules/SocialService.jsm");
- 
- const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
- const HTML_NS = "http://www.w3.org/1999/xhtml";
- 
- this.EXPORTED_SYMBOLS = ["getFrameWorkerHandle"];
-@@ -190,27 +190,33 @@ ParentPort.prototype = {
- // Make the <browser remote="true"> element that hosts the worker.
- function makeRemoteBrowser() {
-   let deferred = Promise.defer();
-   let hiddenDoc = Services.appShell.hiddenDOMWindow.document;
-   // Create a HTML iframe with a chrome URL, then this can host the browser.
-   let iframe = hiddenDoc.createElementNS(HTML_NS, "iframe");
-   iframe.setAttribute("src", "chrome://global/content/mozilla.xhtml");
-   iframe.addEventListener("load", function onLoad() {
-+  var p = new Promise(function(resolve, reject) {
-+    iframe.addEventListener("load", resolve, true);
-+  });
-+
-+  let ret = p.then(function() {
-     iframe.removeEventListener("load", onLoad, true);
-     let browser = iframe.contentDocument.createElementNS(XUL_NS, "browser");
-     browser.setAttribute("type", "content");
-     browser.setAttribute("disableglobalhistory", "true");
-     browser.setAttribute("remote", "true");
- 
-     iframe.contentDocument.documentElement.appendChild(browser);
--    deferred.resolve(browser);
--  }, true);
-+    return browser;
-+  });
-+
-   hiddenDoc.documentElement.appendChild(iframe);
--  return deferred.promise;
-+  return ret;
- }
- 
- function notifyWorkerError(origin) {
-   // Try to retrieve the worker's associated provider, if it has one, to set its
-   // error state.
-   SocialService.getProvider(origin, function (provider) {
-     if (provider)
-       provider.errorState = "frameworker-error";
-diff --git a/toolkit/components/url-classifier/tests/unit/test_digest256.js b/toolkit/components/url-classifier/tests/unit/test_digest256.js
---- a/toolkit/components/url-classifier/tests/unit/test_digest256.js
-+++ b/toolkit/components/url-classifier/tests/unit/test_digest256.js
-@@ -1,14 +1,13 @@
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
- 
- XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                   "resource://gre/modules/NetUtil.jsm");
--XPCOMUtils.defineLazyModuleGetter(this, "Promise",
--                                  "resource://gre/modules/Promise.jsm");
-+Components.utils.importGlobalProperties(["Promise"]);
- // Global test server for serving safebrowsing updates.
- let gHttpServ = null;
- // Global nsIUrlClassifierDBService
- let gDbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
-   .getService(Ci.nsIUrlClassifierDBService);
- // Security manager for creating nsIPrincipals from URIs
- let gSecMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
-   .getService(Ci.nsIScriptSecurityManager);
-@@ -24,41 +23,41 @@ function readFileToString(aFilename) {
-   stream.init(f, -1, 0, 0);
-   let buf = NetUtil.readInputStreamToString(stream, stream.available());
-   return buf;
- }
- 
- // Registers a table for which to serve update chunks. Returns a promise that
- // resolves when that chunk has been downloaded.
- function registerTableUpdate(aTable, aFilename) {
--  let deferred = Promise.defer();
-   // If we haven't been given an update for this table yet, add it to the map
-   if (!(aTable in gTables)) {
-     gTables[aTable] = [];
-   }
- 
-   // The number of chunks associated with this table.
-   let numChunks = gTables[aTable].length + 1;
-   let redirectPath = "/" + aTable + "-" + numChunks;
-   let redirectUrl = "localhost:4444" + redirectPath;
- 
-   // Store redirect url for that table so we can return it later when we
-   // process an update request.
-   gTables[aTable].push(redirectUrl);
- 
--  gHttpServ.registerPathHandler(redirectPath, function(request, response) {
--    do_print("Mock safebrowsing server handling request for " + redirectPath);
--    let contents = readFileToString(aFilename);
--    response.setHeader("Content-Type",
--                       "application/vnd.google.safebrowsing-update", false);
--    response.setStatusLine(request.httpVersion, 200, "OK");
--    response.bodyOutputStream.write(contents, contents.length);
--    deferred.resolve(contents);
-+  return new Promise(function(resolve) {
-+    gHttpServ.registerPathHandler(redirectPath, function(request, response) {
-+      do_print("Mock safebrowsing server handling request for " + redirectPath);
-+      let contents = readFileToString(aFilename);
-+      response.setHeader("Content-Type",
-+                         "application/vnd.google.safebrowsing-update", false);
-+      response.setStatusLine(request.httpVersion, 200, "OK");
-+      response.bodyOutputStream.write(contents, contents.length);
-+      resolve(contents);
-+    });
-   });
--  return deferred.promise;
- }
- 
- // Construct a response with redirect urls.
- function processUpdateRequest() {
-   let response = "n:1000\n";
-   for (let table in gTables) {
-     response += "i:" + table + "\n";
-     for (let i = 0; i < gTables[table].length; ++i) {
-diff --git a/toolkit/modules/AsyncShutdown.jsm b/toolkit/modules/AsyncShutdown.jsm
---- a/toolkit/modules/AsyncShutdown.jsm
-+++ b/toolkit/modules/AsyncShutdown.jsm
-@@ -43,19 +43,18 @@
- 
- "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);
-+Cu.importGlobalProperties(["Promise"]);
- 
--XPCOMUtils.defineLazyModuleGetter(this, "Promise",
--  "resource://gre/modules/Promise.jsm");
- XPCOMUtils.defineLazyServiceGetter(this, "gDebug",
-   "@mozilla.org/xpcom/debug;1", "nsIDebug");
- Object.defineProperty(this, "gCrashReporter", {
-   get: function() {
-     delete this.gCrashReporter;
-     try {
-       let reporter = Cc["@mozilla.org/xre/app-info;1"].
-             getService(Ci.nsICrashReporter);
-@@ -116,27 +115,28 @@ function err(msg, error = null) {
-  * 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();
--  timer.initWithCallback(function() {
--    if (beats <= 0) {
--      deferred.resolve();
--    }
--    --beats;
--  }, DELAY_BEAT, Ci.nsITimer.TYPE_REPEATING_PRECISE_CAN_SKIP);
-+  var p = new Promise(function(resolve, reject) {
-+    timer.initWithCallback(function() {
-+      if (beats <= 0) {
-+        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.
--  deferred.promise.then(() => timer.cancel(), () => timer.cancel());
--  return deferred;
-+  p.then(() => timer.cancel(), () => timer.cancel());
-+  return p;
- }
- 
- this.EXPORTED_SYMBOLS = ["AsyncShutdown"];
- 
- /**
-  * {string} topic -> phase
-  */
- let gPhases = new Map();
-@@ -353,17 +353,17 @@ Spinner.prototype = {
- 
-     // If after DELAY_CRASH_MS (approximately one minute, adjusted to take
-     // into account sleep and otherwise busy computer) we have not finished
-     // this shutdown phase, we assume that the shutdown is somehow frozen,
-     // presumably deadlocked. At this stage, the only thing we can do to
-     // avoid leaving the user's computer in an unstable (and battery-sucking)
-     // situation is report the issue and crash.
-     let timeToCrash = looseTimer(DELAY_CRASH_MS);
--    timeToCrash.promise.then(
-+    timeToCrash.then(
-       function onTimeout() {
-         // Report the problem as best as we can, then crash.
-         let frozen = [];
-         for (let {name, isFrozen} of allMonitors) {
-           if (isFrozen) {
-             frozen.push(name);
-           }
-         }
-diff --git a/toolkit/modules/Promise.jsm b/toolkit/modules/Promise.jsm
---- a/toolkit/modules/Promise.jsm
-+++ b/toolkit/modules/Promise.jsm
-@@ -1,805 +1,35 @@
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
- /* This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- "use strict";
- 
-+Components.utils.importGlobalProperties(["Promise"]);
-+
- this.EXPORTED_SYMBOLS = [
-   "Promise"
- ];
- 
--/**
-- * This module implements the "promise" construct, according to the
-- * "Promises/A+" proposal as known in April 2013, documented here:
-- *
-- * <http://promises-aplus.github.com/promises-spec/>
-- *
-- * A promise is an object representing a value that may not be available yet.
-- * Internally, a promise can be in one of three states:
-- *
-- * - Pending, when the final value is not available yet.  This is the only state
-- *   that may transition to one of the other two states.
-- *
-- * - Resolved, when and if the final value becomes available.  A resolution
-- *   value becomes permanently associated with the promise.  This may be any
-- *   value, including "undefined".
-- *
-- * - Rejected, if an error prevented the final value from being determined.  A
-- *   rejection reason becomes permanently associated with the promise.  This may
-- *   be any value, including "undefined", though it is generally an Error
-- *   object, like in exception handling.
-- *
-- * A reference to an existing promise may be received by different means, for
-- * example as the return value of a call into an asynchronous API.  In this
-- * case, the state of the promise can be observed but not directly controlled.
-- *
-- * To observe the state of a promise, its "then" method must be used.  This
-- * method registers callback functions that are called as soon as the promise is
-- * either resolved or rejected.  The method returns a new promise, that in turn
-- * is resolved or rejected depending on the state of the original promise and on
-- * the behavior of the callbacks.  For example, unhandled exceptions in the
-- * callbacks cause the new promise to be rejected, even if the original promise
-- * is resolved.  See the documentation of the "then" method for details.
-- *
-- * Promises may also be created using the "Promise.defer" function, the main
-- * entry point of this module.  The function, along with the new promise,
-- * returns separate methods to change its state to be resolved or rejected.
-- * See the documentation of the "Deferred" prototype for details.
-- *
-- * -----------------------------------------------------------------------------
-- *
-- * Cu.import("resource://gre/modules/Promise.jsm");
-- *
-- * // This function creates and returns a new promise.
-- * function promiseValueAfterTimeout(aValue, aTimeout)
-- * {
-- *   let deferred = Promise.defer();
-- *
-- *   try {
-- *     // An asynchronous operation will trigger the resolution of the promise.
-- *     // In this example, we don't have a callback that triggers a rejection.
-- *     do_timeout(aTimeout, function () {
-- *       deferred.resolve(aValue);
-- *     });
-- *   } catch (ex) {
-- *     // Generally, functions returning promises propagate exceptions through
-- *     // the returned promise, though they may also choose to fail early.
-- *     deferred.reject(ex);
-- *   }
-- *
-- *   // We don't return the deferred to the caller, but only the contained
-- *   // promise, so that the caller cannot accidentally change its state.
-- *   return deferred.promise;
-- * }
-- *
-- * // This code uses the promise returned be the function above.
-- * let promise = promiseValueAfterTimeout("Value", 1000);
-- *
-- * let newPromise = promise.then(function onResolve(aValue) {
-- *   do_print("Resolved with this value: " + aValue);
-- * }, function onReject(aReason) {
-- *   do_print("Rejected with this reason: " + aReason);
-- * });
-- *
-- * // Unexpected errors should always be reported at the end of a promise chain.
-- * newPromise.then(null, Components.utils.reportError);
-- *
-- * -----------------------------------------------------------------------------
-- */
--
--////////////////////////////////////////////////////////////////////////////////
--//// Globals
--
--const Cc = Components.classes;
--const Ci = Components.interfaces;
--const Cu = Components.utils;
--const Cr = Components.results;
--
--Cu.import("resource://gre/modules/Services.jsm");
--Cu.import("resource://gre/modules/XPCOMUtils.jsm");
--
--const STATUS_PENDING = 0;
--const STATUS_RESOLVED = 1;
--const STATUS_REJECTED = 2;
--
--// These "private names" allow some properties of the Promise object to be
--// accessed only by this module, while still being visible on the object
--// manually when using a debugger.  They don't strictly guarantee that the
--// properties are inaccessible by other code, but provide enough protection to
--// avoid using them by mistake.
--const salt = Math.floor(Math.random() * 100);
--const Name = (n) => "{private:" + n + ":" + salt + "}";
--const N_STATUS = Name("status");
--const N_VALUE = Name("value");
--const N_HANDLERS = Name("handlers");
--const N_WITNESS = Name("witness");
--
--
--/////// Warn-upon-finalization mechanism
--//
--// One of the difficult problems with promises is locating uncaught
--// rejections. We adopt the following strategy: if a promise is rejected
--// at the time of its garbage-collection *and* if the promise is at the
--// end of a promise chain (i.e. |thatPromise.then| has never been
--// called), then we print a warning.
--//
--//  let deferred = Promise.defer();
--//  let p = deferred.promise.then();
--//  deferred.reject(new Error("I am un uncaught error"));
--//  deferred = null;
--//  p = null;
--//
--// In this snippet, since |deferred.promise| is not the last in the
--// chain, no error will be reported for that promise. However, since
--// |p| is the last promise in the chain, the error will be reported
--// for |p|.
--//
--// Note that this may, in some cases, cause an error to be reported more
--// than once. For instance, consider:
--//
--//   let deferred = Promise.defer();
--//   let p1 = deferred.promise.then();
--//   let p2 = deferred.promise.then();
--//   deferred.reject(new Error("I am an uncaught error"));
--//   p1 = p2 = deferred = null;
--//
--// In this snippet, the error is reported both by p1 and by p2.
--//
--
--XPCOMUtils.defineLazyServiceGetter(this, "FinalizationWitnessService",
--                                   "@mozilla.org/toolkit/finalizationwitness;1",
--                                   "nsIFinalizationWitnessService");
--
--let PendingErrors = {
--  _counter: 0,
--  _map: new Map(),
--  register: function(error) {
--    let id = "pending-error-" + (this._counter++);
--    //
--    // At this stage, ideally, we would like to store the error itself
--    // and delay any treatment until we are certain that we will need
--    // to report that error. However, in the (unlikely but possible)
--    // case the error holds a reference to the promise itself, doing so
--    // would prevent the promise from being garbabe-collected, which
--    // would both cause a memory leak and ensure that we cannot report
--    // the uncaught error.
--    //
--    // To avoid this situation, we rather extract relevant data from
--    // the error and further normalize it to strings.
--    //
--    let value = {
--      date: new Date(),
--      message: "" + error,
--      fileName: null,
--      stack: null,
--      lineNumber: null
--    };
--    try { // Defend against non-enumerable values
--      if (error && error instanceof Ci.nsIException) {
--        // nsIException does things a little differently.
--        try {
--          // For starters |.toString()| does not only contain the message, but
--          // also the top stack frame, and we don't really want that.
--          value.message = error.message;
--        } catch (ex) {
--          // Ignore field
--        }
--        try {
--          // All lowercase filename. ;)
--          value.fileName = error.filename;
--        } catch (ex) {
--          // Ignore field
--        }
--        try {
--          value.lineNumber = error.lineNumber;
--        } catch (ex) {
--          // Ignore field
--        }
--      } else if (typeof error == "object" && error) {
--        for (let k of ["fileName", "stack", "lineNumber"]) {
--          try { // Defend against fallible getters and string conversions
--            let v = error[k];
--            value[k] = v ? ("" + v) : null;
--          } catch (ex) {
--            // Ignore field
--          }
--        }
--      }
--
--      if (!value.stack) {
--        // |error| is not an Error (or Error-alike). Try to figure out the stack.
--        let stack = null;
--        if (error && error.location &&
--            error.location instanceof Ci.nsIStackFrame) {
--          // nsIException has full stack frames in the |.location| member.
--          stack = error.location;
--        } else {
--          // Components.stack to the rescue!
--          stack  = Components.stack;
--          // Remove those top frames that refer to Promise.jsm.
--          while (stack) {
--            if (!stack.filename.endsWith("/Promise.jsm")) {
--              break;
--            }
--            stack = stack.caller;
--          }
--        }
--        if (stack) {
--          let frames = [];
--          while (stack) {
--            frames.push(stack);
--            stack = stack.caller;
--          }
--          value.stack = frames.join("\n");
--        }
--      }
--    } catch (ex) {
--      // Ignore value
--    }
--    this._map.set(id, value);
--    return id;
--  },
--  extract: function(id) {
--    let value = this._map.get(id);
--    this._map.delete(id);
--    return value;
--  },
--  unregister: function(id) {
--    this._map.delete(id);
--  }
--};
--
--// Actually print the finalization warning.
--Services.obs.addObserver(function observe(aSubject, aTopic, aValue) {
--  let error = PendingErrors.extract(aValue);
--  let {message, date, fileName, stack, lineNumber} = error;
--  let error = Cc['@mozilla.org/scripterror;1'].createInstance(Ci.nsIScriptError);
--  if (!error || !Services.console) {
--    // Too late during shutdown to use the nsIConsole
--    dump("*************************\n");
--    dump("A promise chain failed to handle a rejection\n\n");
--    dump("On: " + date + "\n");
--    dump("Full message: " + message + "\n");
--    dump("See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise\n");
--    dump("Full stack: " + (stack||"not available") + "\n");
--    dump("*************************\n");
--    return;
--  }
--  if (stack) {
--    message += "\nFull Stack: " + stack;
--  }
--  error.init(
--             /*message*/"A promise chain failed to handle a rejection.\n\n" +
--             "Date: " + date + "\nFull Message: " + message,
--             /*sourceName*/ fileName,
--             /*sourceLine*/ lineNumber?("" + lineNumber):0,
--             /*lineNumber*/ lineNumber || 0,
--             /*columnNumber*/ 0,
--             /*flags*/ Ci.nsIScriptError.errorFlag,
--             /*category*/ "chrome javascript");
--  Services.console.logMessage(error);
--}, "promise-finalization-witness", false);
--
--///////// Additional warnings for developers
--//
--// The following error types are considered programmer errors, which should be
--// reported (possibly redundantly) so as to let programmers fix their code.
--const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"];
--
--////////////////////////////////////////////////////////////////////////////////
--//// Promise
--
--/**
-- * This object provides the public module functions.
-- */
--this.Promise = Object.freeze({
--  /**
--   * Creates a new pending promise and provides methods to resolve or reject it.
--   *
--   * @return A new object, containing the new promise in the "promise" property,
--   *         and the methods to change its state in the "resolve" and "reject"
--   *         properties.  See the Deferred documentation for details.
--   */
--  defer: function ()
--  {
--    return new Deferred();
--  },
--
--  /**
--   * Creates a new promise resolved with the specified value, or propagates the
--   * state of an existing promise.
--   *
--   * @param aValue
--   *        If this value is not a promise, including "undefined", it becomes
--   *        the resolution value of the returned promise.  If this value is a
--   *        promise, then the returned promise will eventually assume the same
--   *        state as the provided promise.
--   *
--   * @return A promise that can be pending, resolved, or rejected.
--   */
--  resolve: function (aValue)
--  {
--    let promise = new PromiseImpl();
--    PromiseWalker.completePromise(promise, STATUS_RESOLVED, aValue);
--    return promise;
--  },
--
--  /**
--   * Creates a new promise rejected with the specified reason.
--   *
--   * @param aReason
--   *        The rejection reason for the returned promise.  Although the reason
--   *        can be "undefined", it is generally an Error object, like in
--   *        exception handling.
--   *
--   * @return A rejected promise.
--   *
--   * @note The aReason argument should not be a promise.  Using a rejected
--   *       promise for the value of aReason would make the rejection reason
--   *       equal to the rejected promise itself, and not its rejection reason.
--   */
--  reject: function (aReason)
--  {
--    let promise = new PromiseImpl();
--    PromiseWalker.completePromise(promise, STATUS_REJECTED, aReason);
--    return promise;
--  },
--
--  /**
--   * Returns a promise that is resolved or rejected when all values are
--   * resolved or any is rejected.
--   *
--   * @param aValues
--   *        Array of promises that may be pending, resolved, or rejected. When
--   *        all are resolved or any is rejected, the returned promise will be
--   *        resolved or rejected as well.
--   *
--   * @return A new promise that is fulfilled when all values are resolved or
--   *         that is rejected when any of the values are rejected. Its
--   *         resolution value will be an array of all resolved values in the
--   *         given order, or undefined if aValues is an empty array. The reject
--   *         reason will be forwarded from the first promise in the list of
--   *         given promises to be rejected.
--   */
--  all: function (aValues)
--  {
--    if (!Array.isArray(aValues)) {
--      throw new Error("Promise.all() expects an array of promises or values.");
--    }
--
--    if (!aValues.length) {
--      return Promise.resolve([]);
--    }
--
--    let countdown = aValues.length;
--    let deferred = Promise.defer();
--    let resolutionValues = new Array(countdown);
--
--    function checkForCompletion(aValue, aIndex) {
--      resolutionValues[aIndex] = aValue;
--
--      if (--countdown === 0) {
--        deferred.resolve(resolutionValues);
--      }
--    }
--
--    for (let i = 0; i < aValues.length; i++) {
--      let index = i;
--      let value = aValues[i];
--      let resolve = val => checkForCompletion(val, index);
--
--      if (value && typeof(value.then) == "function") {
--        value.then(resolve, deferred.reject);
--      } else {
--        // Given value is not a promise, forward it as a resolution value.
--        resolve(value);
--      }
--    }
--
--    return deferred.promise;
--  },
--});
--
--////////////////////////////////////////////////////////////////////////////////
--//// PromiseWalker
--
--/**
-- * This singleton object invokes the handlers registered on resolved and
-- * rejected promises, ensuring that processing is not recursive and is done in
-- * the same order as registration occurred on each promise.
-- *
-- * There is no guarantee on the order of execution of handlers registered on
-- * different promises.
-- */
--this.PromiseWalker = {
--  /**
--   * Singleton array of all the unprocessed handlers currently registered on
--   * resolved or rejected promises.  Handlers are removed from the array as soon
--   * as they are processed.
--   */
--  handlers: [],
--
--  /**
--   * Called when a promise needs to change state to be resolved or rejected.
--   *
--   * @param aPromise
--   *        Promise that needs to change state.  If this is already resolved or
--   *        rejected, this method has no effect.
--   * @param aStatus
--   *        New desired status, either STATUS_RESOLVED or STATUS_REJECTED.
--   * @param aValue
--   *        Associated resolution value or rejection reason.
--   */
--  completePromise: function (aPromise, aStatus, aValue)
--  {
--    // Do nothing if the promise is already resolved or rejected.
--    if (aPromise[N_STATUS] != STATUS_PENDING) {
--      return;
--    }
--
--    // Resolving with another promise will cause this promise to eventually
--    // assume the state of the provided promise.
--    if (aStatus == STATUS_RESOLVED && aValue &&
--        typeof(aValue.then) == "function") {
--      aValue.then(this.completePromise.bind(this, aPromise, STATUS_RESOLVED),
--                  this.completePromise.bind(this, aPromise, STATUS_REJECTED));
--      return;
--    }
--
--    // Change the promise status and schedule our handlers for processing.
--    aPromise[N_STATUS] = aStatus;
--    aPromise[N_VALUE] = aValue;
--    if (aPromise[N_HANDLERS].length > 0) {
--      this.schedulePromise(aPromise);
--    } else if (aStatus == STATUS_REJECTED) {
--      // This is a rejection and the promise is the last in the chain.
--      // For the time being we therefore have an uncaught error.
--      let id = PendingErrors.register(aValue);
--      let witness =
--          FinalizationWitnessService.make("promise-finalization-witness", id);
--      aPromise[N_WITNESS] = [id, witness];
--    }
--  },
--
--  /**
--   * Sets up the PromiseWalker loop to start on the next tick of the event loop
--   */
--  scheduleWalkerLoop: function()
--  {
--    this.walkerLoopScheduled = true;
--    Services.tm.currentThread.dispatch(this.walkerLoop,
--                                       Ci.nsIThread.DISPATCH_NORMAL);
--  },
--
--  /**
--   * Schedules the resolution or rejection handlers registered on the provided
--   * promise for processing.
--   *
--   * @param aPromise
--   *        Resolved or rejected promise whose handlers should be processed.  It
--   *        is expected that this promise has at least one handler to process.
--   */
--  schedulePromise: function (aPromise)
--  {
--    // Migrate the handlers from the provided promise to the global list.
--    for (let handler of aPromise[N_HANDLERS]) {
--      this.handlers.push(handler);
--    }
--    aPromise[N_HANDLERS].length = 0;
--
--    // Schedule the walker loop on the next tick of the event loop.
--    if (!this.walkerLoopScheduled) {
--      this.scheduleWalkerLoop();
--    }
--  },
--
--  /**
--   * Indicates whether the walker loop is currently scheduled for execution on
--   * the next tick of the event loop.
--   */
--  walkerLoopScheduled: false,
--
--  /**
--   * Processes all the known handlers during this tick of the event loop.  This
--   * eager processing is done to avoid unnecessarily exiting and re-entering the
--   * JavaScript context for each handler on a resolved or rejected promise.
--   *
--   * This function is called with "this" bound to the PromiseWalker object.
--   */
--  walkerLoop: function ()
--  {
--    // If there is more than one handler waiting, reschedule the walker loop
--    // immediately.  Otherwise, use walkerLoopScheduled to tell schedulePromise()
--    // to reschedule the loop if it adds more handlers to the queue.  This makes
--    // this walker resilient to the case where one handler does not return, but
--    // starts a nested event loop.  In that case, the newly scheduled walker will
--    // take over.  In the common case, the newly scheduled walker will be invoked
--    // after this one has returned, with no actual handler to process.  This
--    // small overhead is required to make nested event loops work correctly, but
--    // occurs at most once per resolution chain, thus having only a minor
--    // impact on overall performance.
--    if (this.handlers.length > 1) {
--      this.scheduleWalkerLoop();
--    } else {
--      this.walkerLoopScheduled = false;
--    }
--
--    // Process all the known handlers eagerly.
--    while (this.handlers.length > 0) {
--      this.handlers.shift().process();
--    }
--  },
--};
--
--// Bind the function to the singleton once.
--PromiseWalker.walkerLoop = PromiseWalker.walkerLoop.bind(PromiseWalker);
-+Promise.defer = function() {
-+  return new Deferred();
-+}
-+this.Promise = Promise;
- 
- ////////////////////////////////////////////////////////////////////////////////
- //// Deferred
- 
- /**
-  * Returned by "Promise.defer" to provide a new promise along with methods to
-  * change its state.
-  */
- function Deferred()
- {
--  this.promise = new PromiseImpl();
--  this.resolve = this.resolve.bind(this);
--  this.reject = this.reject.bind(this);
-+  this.promise = new Promise(function(resolve, reject) {
-+    this.resolve = resolve;
-+    this.reject = reject;
-+  }.bind(this));
- 
-   Object.freeze(this);
- }
--
--Deferred.prototype = {
--  /**
--   * A newly created promise, initially in the pending state.
--   */
--  promise: null,
--
--  /**
--   * Resolves the associated promise with the specified value, or propagates the
--   * state of an existing promise.  If the associated promise has already been
--   * resolved or rejected, this method does nothing.
--   *
--   * This function is bound to its associated promise when "Promise.defer" is
--   * called, and can be called with any value of "this".
--   *
--   * @param aValue
--   *        If this value is not a promise, including "undefined", it becomes
--   *        the resolution value of the associated promise.  If this value is a
--   *        promise, then the associated promise will eventually assume the same
--   *        state as the provided promise.
--   *
--   * @note Calling this method with a pending promise as the aValue argument,
--   *       and then calling it again with another value before the promise is
--   *       resolved or rejected, has unspecified behavior and should be avoided.
--   */
--  resolve: function (aValue) {
--    PromiseWalker.completePromise(this.promise, STATUS_RESOLVED, aValue);
--  },
--
--  /**
--   * Rejects the associated promise with the specified reason.  If the promise
--   * has already been resolved or rejected, this method does nothing.
--   *
--   * This function is bound to its associated promise when "Promise.defer" is
--   * called, and can be called with any value of "this".
--   *
--   * @param aReason
--   *        The rejection reason for the associated promise.  Although the
--   *        reason can be "undefined", it is generally an Error object, like in
--   *        exception handling.
--   *
--   * @note The aReason argument should not generally be a promise.  In fact,
--   *       using a rejected promise for the value of aReason would make the
--   *       rejection reason equal to the rejected promise itself, not to the
--   *       rejection reason of the rejected promise.
--   */
--  reject: function (aReason) {
--    PromiseWalker.completePromise(this.promise, STATUS_REJECTED, aReason);
--  },
--};
--
--////////////////////////////////////////////////////////////////////////////////
--//// PromiseImpl
--
--/**
-- * The promise object implementation.  This includes the public "then" method,
-- * as well as private state properties.
-- */
--function PromiseImpl()
--{
--  /*
--   * Internal status of the promise.  This can be equal to STATUS_PENDING,
--   * STATUS_RESOLVED, or STATUS_REJECTED.
--   */
--  Object.defineProperty(this, N_STATUS, { value: STATUS_PENDING,
--                                          writable: true });
--
--  /*
--   * When the N_STATUS property is STATUS_RESOLVED, this contains the final
--   * resolution value, that cannot be a promise, because resolving with a
--   * promise will cause its state to be eventually propagated instead.  When the
--   * N_STATUS property is STATUS_REJECTED, this contains the final rejection
--   * reason, that could be a promise, even if this is uncommon.
--   */
--  Object.defineProperty(this, N_VALUE, { writable: true });
--
--  /*
--   * Array of Handler objects registered by the "then" method, and not processed
--   * yet.  Handlers are removed when the promise is resolved or rejected.
--   */
--  Object.defineProperty(this, N_HANDLERS, { value: [] });
--
--  /**
--   * When the N_STATUS property is STATUS_REJECTED and until there is
--   * a rejection callback, this contains an array
--   * - {string} id An id for use with |PendingErrors|;
--   * - {FinalizationWitness} witness A witness broadcasting |id| on
--   *   notification "promise-finalization-witness".
--   */
--  Object.defineProperty(this, N_WITNESS, { writable: true });
--
--  Object.seal(this);
--}
--
--PromiseImpl.prototype = {
--  /**
--   * Calls one of the provided functions as soon as this promise is either
--   * resolved or rejected.  A new promise is returned, whose state evolves
--   * depending on this promise and the provided callback functions.
--   *
--   * The appropriate callback is always invoked after this method returns, even
--   * if this promise is already resolved or rejected.  You can also call the
--   * "then" method multiple times on the same promise, and the callbacks will be
--   * invoked in the same order as they were registered.
--   *
--   * @param aOnResolve
--   *        If the promise is resolved, this function is invoked with the
--   *        resolution value of the promise as its only argument, and the
--   *        outcome of the function determines the state of the new promise
--   *        returned by the "then" method.  In case this parameter is not a
--   *        function (usually "null"), the new promise returned by the "then"
--   *        method is resolved with the same value as the original promise.
--   *
--   * @param aOnReject
--   *        If the promise is rejected, this function is invoked with the
--   *        rejection reason of the promise as its only argument, and the
--   *        outcome of the function determines the state of the new promise
--   *        returned by the "then" method.  In case this parameter is not a
--   *        function (usually left "undefined"), the new promise returned by the
--   *        "then" method is rejected with the same reason as the original
--   *        promise.
--   *
--   * @return A new promise that is initially pending, then assumes a state that
--   *         depends on the outcome of the invoked callback function:
--   *          - If the callback returns a value that is not a promise, including
--   *            "undefined", the new promise is resolved with this resolution
--   *            value, even if the original promise was rejected.
--   *          - If the callback throws an exception, the new promise is rejected
--   *            with the exception as the rejection reason, even if the original
--   *            promise was resolved.
--   *          - If the callback returns a promise, the new promise will
--   *            eventually assume the same state as the returned promise.
--   *
--   * @note If the aOnResolve callback throws an exception, the aOnReject
--   *       callback is not invoked.  You can register a rejection callback on
--   *       the returned promise instead, to process any exception occurred in
--   *       either of the callbacks registered on this promise.
--   */
--  then: function (aOnResolve, aOnReject)
--  {
--    let handler = new Handler(this, aOnResolve, aOnReject);
--    this[N_HANDLERS].push(handler);
--
--    // Ensure the handler is scheduled for processing if this promise is already
--    // resolved or rejected.
--    if (this[N_STATUS] != STATUS_PENDING) {
--
--      // This promise is not the last in the chain anymore. Remove any watchdog.
--      if (this[N_WITNESS] != null) {
--        let [id, witness] = this[N_WITNESS];
--        this[N_WITNESS] = null;
--        witness.forget();
--        PendingErrors.unregister(id);
--      }
--
--      PromiseWalker.schedulePromise(this);
--    }
--
--    return handler.nextPromise;
--  },
--};
--
--////////////////////////////////////////////////////////////////////////////////
--//// Handler
--
--/**
-- * Handler registered on a promise by the "then" function.
-- */
--function Handler(aThisPromise, aOnResolve, aOnReject)
--{
--  this.thisPromise = aThisPromise;
--  this.onResolve = aOnResolve;
--  this.onReject = aOnReject;
--  this.nextPromise = new PromiseImpl();
--}
--
--Handler.prototype = {
--  /**
--   * Promise on which the "then" method was called.
--   */
--  thisPromise: null,
--
--  /**
--   * Unmodified resolution handler provided to the "then" method.
--   */
--  onResolve: null,
--
--  /**
--   * Unmodified rejection handler provided to the "then" method.
--   */
--  onReject: null,
--
--  /**
--   * New promise that will be returned by the "then" method.
--   */
--  nextPromise: null,
--
--  /**
--   * Called after thisPromise is resolved or rejected, invokes the appropriate
--   * callback and propagates the result to nextPromise.
--   */
--  process: function()
--  {
--    // The state of this promise is propagated unless a handler is defined.
--    let nextStatus = this.thisPromise[N_STATUS];
--    let nextValue = this.thisPromise[N_VALUE];
--
--    try {
--      // If a handler is defined for either resolution or rejection, invoke it
--      // to determine the state of the next promise, that will be resolved with
--      // the returned value, that can also be another promise.
--      if (nextStatus == STATUS_RESOLVED) {
--        if (typeof(this.onResolve) == "function") {
--          nextValue = this.onResolve(nextValue);
--        }
--      } else if (typeof(this.onReject) == "function") {
--        nextValue = this.onReject(nextValue);
--        nextStatus = STATUS_RESOLVED;
--      }
--    } catch (ex) {
--
--      // An exception has occurred in the handler.
--
--      if (ex && typeof ex == "object" && "name" in ex &&
--          ERRORS_TO_REPORT.indexOf(ex.name) != -1) {
--
--        // We suspect that the exception is a programmer error, so we now
--        // display it using dump().  Note that we do not use Cu.reportError as
--        // we assume that this is a programming error, so we do not want end
--        // users to see it. Also, if the programmer handles errors correctly,
--        // they will either treat the error or log them somewhere.
--
--        dump("*************************\n");
--        dump("A coding exception was thrown in a Promise " +
--             ((nextStatus == STATUS_RESOLVED) ? "resolution":"rejection") +
--             " callback.\n\n");
--        dump("Full message: " + ex + "\n");
--        dump("See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise\n");
--        dump("Full stack: " + (("stack" in ex)?ex.stack:"not available") + "\n");
--        dump("*************************\n");
--
--      }
--
--      // Additionally, reject the next promise.
--      nextStatus = STATUS_REJECTED;
--      nextValue = ex;
--    }
--
--    // Propagate the newly determined state to the next promise.
--    PromiseWalker.completePromise(this.nextPromise, nextStatus, nextValue);
--  },
--};
-diff --git a/toolkit/modules/Sqlite.jsm b/toolkit/modules/Sqlite.jsm
---- a/toolkit/modules/Sqlite.jsm
-+++ b/toolkit/modules/Sqlite.jsm
-@@ -5,21 +5,21 @@
- "use strict";
- 
- this.EXPORTED_SYMBOLS = [
-   "Sqlite",
- ];
- 
- const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
- 
--Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
- Cu.import("resource://gre/modules/osfile.jsm");
- Cu.import("resource://gre/modules/Services.jsm");
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
- Cu.import("resource://gre/modules/Log.jsm");
-+Cu.importGlobalProperties(["Promise"]);
- 
- XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
-                                   "resource://gre/modules/AsyncShutdown.jsm");
- XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
-                                   "resource://services-common/utils.js");
- XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
-                                   "resource://gre/modules/FileUtils.jsm");
- XPCOMUtils.defineLazyModuleGetter(this, "Task",
-@@ -94,39 +94,44 @@ function openConnection(options) {
- 
-   let basename = OS.Path.basename(path);
-   let number = connectionCounters.get(basename) || 0;
-   connectionCounters.set(basename, number + 1);
- 
-   let identifier = basename + "#" + number;
- 
-   log.info("Opening database: " + path + " (" + identifier + ")");
--  let deferred = Promise.defer();
-   let options = null;
-   if (!sharedMemoryCache) {
-     options = Cc["@mozilla.org/hash-property-bag;1"].
-       createInstance(Ci.nsIWritablePropertyBag);
-     options.setProperty("shared", false);
-   }
--  Services.storage.openAsyncDatabase(file, options, function(status, connection) {
--    if (!connection) {
--      log.warn("Could not open connection: " + status);
--      deferred.reject(new Error("Could not open connection: " + status));
--    }
--    log.warn("Connection opened");
--    try {
--      deferred.resolve(
--        new OpenedConnection(connection.QueryInterface(Ci.mozIStorageAsyncConnection), basename, number,
--        openedOptions));
--    } catch (ex) {
--      log.warn("Could not open database: " + CommonUtils.exceptionStr(ex));
--      deferred.reject(ex);
--    }
-+
-+  let promise = new Promise(function(resolve, reject) {
-+    Services.storage.openAsyncDatabase(file, options, function(status, connection) {
-+      if (!connection) {
-+        log.warn("Could not open connection: " + status);
-+        reject(new Error("Could not open connection: " + status));
-+      }
-+      log.warn("Connection opened");
-+      resolve(connection);
-+    });
-   });
--  return deferred.promise;
-+
-+  let ret = promise.then(function(connection) {
-+    return new OpenedConnection(connection.QueryInterface(Ci.mozIStorageAsyncConnection),
-+                                basename, number,
-+                                openedOptions);
-+  }).catch(function(ex) {
-+    log.warn("Could not open database: " + CommonUtils.exceptionStr(ex));
-+    throw ex; // rethrow so caller can observe exception.
-+  });
-+
-+  return ret;
- }
- 
- 
- /**
-  * Handle on an opened SQLite database.
-  *
-  * This is essentially a glorified wrapper around mozIStorageConnection.
-  * However, it offers some compelling advantages.
-@@ -208,17 +213,18 @@ function OpenedConnection(connection, ba
- 
-   // A map from statement index to mozIStoragePendingStatement, to allow for
-   // canceling prior to finalizing the mozIStorageStatements.
-   this._pendingStatements = new Map();
- 
-   // Increments for each executed statement for the life of the connection.
-   this._statementCounter = 0;
- 
--  this._inProgressTransaction = null;
-+  this._rejectTransaction = null;
-+  this._inProgressTransaction = false;
- 
-   this._idleShrinkMS = options.shrinkMemoryOnConnectionIdleMS;
-   if (this._idleShrinkMS) {
-     this._idleShrinkTimer = Cc["@mozilla.org/timer;1"]
-                               .createInstance(Ci.nsITimer);
-     // We wait for the first statement execute to start the timer because
-     // shrinking now would not do anything.
-   }
-@@ -278,47 +284,43 @@ OpenedConnection.prototype = Object.free
-    */
-   close: function () {
-     if (!this._connection) {
-       return Promise.resolve();
-     }
- 
-     this._log.debug("Request to close connection.");
-     this._clearIdleShrinkTimer();
--    let deferred = Promise.defer();
- 
--    AsyncShutdown.profileBeforeChange.addBlocker(
--      "Sqlite.jsm: " + this._connectionIdentifier,
--      deferred.promise
--    );
-+    let blockerPromise;
- 
-     // We need to take extra care with transactions during shutdown.
-     //
-     // If we don't have a transaction in progress, we can proceed with shutdown
-     // immediately.
--    if (!this._inProgressTransaction) {
--      this._finalize(deferred);
--      return deferred.promise;
-+    if (this._inProgressTransaction) {
-+      this._log.warn("Transaction in progress at time of close. Rolling back.");
-+      blockerPromise = this.execute("ROLLBACK TRANSACTION").
-+                         then(this._finalize, this._finalize);
-+      this._rejectTransaction(new Error("Connection being closed."));
-+      this._rejectTransaction = null;
-+      this._inProgressTransaction = false;
-+    } else {
-+      blockerPromise = this._finalize();
-     }
- 
--    // Else if we do have a transaction in progress, we forcefully roll it
--    // back. This is an async task, so we wait on it to finish before
--    // performing finalization.
--    this._log.warn("Transaction in progress at time of close. Rolling back.");
-+    AsyncShutdown.profileBeforeChange.addBlocker(
-+      "Sqlite.jsm: " + this._connectionIdentifier,
-+      blockerPromise
-+    );
- 
--    let onRollback = this._finalize.bind(this, deferred);
--
--    this.execute("ROLLBACK TRANSACTION").then(onRollback, onRollback);
--    this._inProgressTransaction.reject(new Error("Connection being closed."));
--    this._inProgressTransaction = null;
--
--    return deferred.promise;
-+    return blockerPromise;
-   },
- 
--  _finalize: function (deferred) {
-+  _finalize: function () {
-     this._log.debug("Finalizing connection.");
-     // Cancel any pending statements.
-     for (let [k, statement] of this._pendingStatements) {
-       statement.cancel();
-     }
-     this._pendingStatements.clear();
- 
-     // We no longer need to track these.
-@@ -335,22 +337,24 @@ OpenedConnection.prototype = Object.free
-     }
-     this._cachedStatements.clear();
- 
-     // This guards against operations performed between the call to this
-     // function and asyncClose() finishing. See also bug 726990.
-     this._open = false;
- 
-     this._log.debug("Calling asyncClose().");
--    this._connection.asyncClose({
--      complete: function () {
--        this._log.info("Closed");
--        this._connection = null;
--        deferred.resolve();
--      }.bind(this),
-+    return new Promise((resolve) => {
-+      this._connection.asyncClose({
-+        complete: function () {
-+          this._log.info("Closed");
-+          this._connection = null;
-+          resolve();
-+        }.bind(this),
-+      });
-     });
-   },
- 
-   /**
-    * Execute a SQL statement and cache the underlying statement object.
-    *
-    * This function executes a SQL statement and also caches the underlying
-    * derived statement object so subsequent executions are faster and use
-@@ -417,35 +421,29 @@ OpenedConnection.prototype = Object.free
-     let statement = this._cachedStatements.get(sql);
-     if (!statement) {
-       statement = this._connection.createAsyncStatement(sql);
-       this._cachedStatements.set(sql, statement);
-     }
- 
-     this._clearIdleShrinkTimer();
- 
--    let deferred = Promise.defer();
--
--    try {
-+    let startTimerPromise =
-       this._executeStatement(sql, statement, params, onRow).then(
-         function onResult(result) {
-           this._startIdleShrinkTimer();
--          deferred.resolve(result);
-+          return result;
-         }.bind(this),
-         function onError(error) {
-           this._startIdleShrinkTimer();
--          deferred.reject(error);
-+          throw error;
-         }.bind(this)
-       );
--    } catch (ex) {
--      this._startIdleShrinkTimer();
--      throw ex;
--    }
- 
--    return deferred.promise;
-+    return startTimerPromise;
-   },
- 
-   /**
-    * Execute a one-shot SQL statement.
-    *
-    * If you find yourself feeding the same SQL string in this function, you
-    * should *not* use this function and instead use `executeCached`.
-    *
-@@ -455,60 +453,50 @@ OpenedConnection.prototype = Object.free
-    *        (string) SQL to execute.
-    * @param params optional
-    *        (Array or Object) Parameters to bind to the statement.
-    * @param onRow optional
-    *        (function) Callback to receive result of a single row.
-    */
-   execute: function (sql, params=null, onRow=null) {
-     if (typeof(sql) != "string") {
--      throw new Error("Must define SQL to execute as a string: " + sql);
-+      Promise.reject(new Error("Must define SQL to execute as a string: " + sql));
-     }
- 
-     this._ensureOpen();
- 
-     let statement = this._connection.createAsyncStatement(sql);
-     let index = this._anonymousCounter++;
- 
-     this._anonymousStatements.set(index, statement);
-     this._clearIdleShrinkTimer();
- 
-     let onFinished = function () {
-       this._anonymousStatements.delete(index);
-       statement.finalize();
-       this._startIdleShrinkTimer();
-     }.bind(this);
- 
--    let deferred = Promise.defer();
--
--    try {
--      this._executeStatement(sql, statement, params, onRow).then(
-+    return this._executeStatement(sql, statement, params, onRow).then(
-         function onResult(rows) {
-           onFinished();
--          deferred.resolve(rows);
-+          return rows;
-         }.bind(this),
--
-         function onError(error) {
-           onFinished();
--          deferred.reject(error);
-+          throw error;
-         }.bind(this)
-       );
--    } catch (ex) {
--      onFinished();
--      throw ex;
--    }
--
--    return deferred.promise;
-   },
- 
-   /**
-    * Whether a transaction is currently in progress.
-    */
-   get transactionInProgress() {
--    return this._open && !!this._inProgressTransaction;
-+    return this._open && this._inProgressTransaction;
-   },
- 
-   /**
-    * Perform a transaction.
-    *
-    * A transaction is specified by a user-supplied function that is a
-    * generator function which can be used by Task.jsm's Task.spawn(). The
-    * function receives this connection instance as its argument.
-@@ -525,31 +513,34 @@ OpenedConnection.prototype = Object.free
-    * the transaction is rolled back, the promise is rejected.
-    *
-    * @param func
-    *        (function) What to perform as part of the transaction.
-    * @param type optional
-    *        One of the TRANSACTION_* constants attached to this type.
-    */
-   executeTransaction: function (func, type=this.TRANSACTION_DEFERRED) {
-+    //FIXME(nsm): Introduces breaking change in Sqlite.jsm APIs due to some
-+    //errors being thrown async.
-     if (this.TRANSACTION_TYPES.indexOf(type) == -1) {
--      throw new Error("Unknown transaction type: " + type);
-+      return Promise.reject(new Error("Unknown transaction type: " + type));
-     }
- 
-     this._ensureOpen();
- 
-     if (this._inProgressTransaction) {
--      throw new Error("A transaction is already active. Only one transaction " +
--                      "can be active at a time.");
-+      return Promise.reject(
-+        new Error("A transaction is already active. Only one transaction " +
-+                  "can be active at a time."));
-     }
- 
-     this._log.debug("Beginning transaction");
--    let deferred = Promise.defer();
--    this._inProgressTransaction = deferred;
--    Task.spawn(function doTransaction() {
-+    this._inProgressTransaction = true;
-+
-+    let transactionTask = Task.spawn(function doTransaction() {
-       // It's tempting to not yield here and rely on the implicit serial
-       // execution of issued statements. However, the yield serves an important
-       // purpose: catching errors in statement execution.
-       yield this.execute("BEGIN " + type + " TRANSACTION");
- 
-       let result;
-       try {
-         result = yield Task.spawn(func(this));
-@@ -579,37 +570,51 @@ OpenedConnection.prototype = Object.free
- 
-       // See comment above about connection being closed during transaction.
-       if (!this._inProgressTransaction) {
-         this._log.warn("Connection was closed while performing transaction. " +
-                        "Unable to commit.");
-         throw new Error("Connection closed before transaction committed.");
-       }
- 
--      try {
--        yield this.execute("COMMIT TRANSACTION");
--      } catch (ex) {
-+      yield this.execute("COMMIT TRANSACTION").catch(function(ex) {
-         this._log.warn("Error committing transaction: " +
-                        CommonUtils.exceptionStr(ex));
-         throw ex;
--      }
-+      });
- 
-       throw new Task.Result(result);
--    }.bind(this)).then(
--      function onSuccess(result) {
--        this._inProgressTransaction = null;
--        deferred.resolve(result);
--      }.bind(this),
--      function onError(error) {
--        this._inProgressTransaction = null;
--        deferred.reject(error);
--      }.bind(this)
--    );
-+    }.bind(this));
-+    
-+    // The returned Promise captures the result of the transaction. It is
-+    // resolved/rejected by transactionTask. But we'd also like to be able to
-+    // reject the Promise if close() is called, to signal that the transaction
-+    // was aborted.
-+    let self = this;
-+    return new Promise(function(resolve, reject) {
-+      // Although this assignment is separate from the _inProgressTransaction
-+      // assignment above, it is executed in the same pass of the event loop,
-+      // which means a close() cannot interrupt it, so we don't need to worry
-+      // about _inProgressTransaction being true but _rejectTransaction being
-+      // null in close().
-+      self._rejectTransaction = reject;
- 
--    return deferred.promise;
-+      transactionTask.then(
-+        function onSuccess(result) {
-+          self._rejectTransaction = null;
-+          self._inProgressTransaction = false;
-+          resolve(result);
-+        },
-+        function onError(error) {
-+          self._rejectTransaction = null;
-+          self._inProgressTransaction = false;
-+          reject(error);
-+        }
-+      );
-+    });
-   },
- 
-   /**
-    * Whether a table exists in the database (both persistent and temporary tables).
-    *
-    * @param name
-    *        (string) Name of the table.
-    *
-@@ -722,28 +727,27 @@ OpenedConnection.prototype = Object.free
-     }
- 
-     throw new Error("Invalid type for bound parameters. Expected Array or " +
-                     "object. Got: " + params);
-   },
- 
-   _executeStatement: function (sql, statement, params, onRow) {
-     if (statement.state != statement.MOZ_STORAGE_STATEMENT_READY) {
--      throw new Error("Statement is not ready for execution.");
-+      return Promise.reject(new Error("Statement is not ready for execution."));
-     }
- 
-     if (onRow && typeof(onRow) != "function") {
--      throw new Error("onRow must be a function. Got: " + onRow);
-+      return Promise.reject(new Error("onRow must be a function. Got: " + onRow));
-     }
- 
-     this._bindParameters(statement, params);
- 
-     let index = this._statementCounter++;
- 
--    let deferred = Promise.defer();
-     let userCancelled = false;
-     let errors = [];
-     let rows = [];
- 
-     // Don't incur overhead for serializing params unless the messages go
-     // somewhere.
-     if (this._log.level <= Log.Level.Trace) {
-       let msg = "Stmt #" + index + " " + sql;
-@@ -752,84 +756,86 @@ OpenedConnection.prototype = Object.free
-         msg += " - " + JSON.stringify(params);
-       }
-       this._log.trace(msg);
-     } else {
-       this._log.debug("Stmt #" + index + " starting");
-     }
- 
-     let self = this;
--    let pending = statement.executeAsync({
--      handleResult: function (resultSet) {
--        // .cancel() may not be immediate and handleResult() could be called
--        // after a .cancel().
--        for (let row = resultSet.getNextRow(); row && !userCancelled; row = resultSet.getNextRow()) {
--          if (!onRow) {
--            rows.push(row);
--            continue;
--          }
--
--          try {
--            onRow(row);
--          } catch (e if e instanceof StopIteration) {
--            userCancelled = true;
--            pending.cancel();
--            break;
--          } catch (ex) {
--            self._log.warn("Exception when calling onRow callback: " +
--                           CommonUtils.exceptionStr(ex));
--          }
--        }
--      },
--
--      handleError: function (error) {
--        self._log.info("Error when executing SQL (" + error.result + "): " +
--                       error.message);
--        errors.push(error);
--      },
--
--      handleCompletion: function (reason) {
--        self._log.debug("Stmt #" + index + " finished.");
--        self._pendingStatements.delete(index);
--
--        switch (reason) {
--          case Ci.mozIStorageStatementCallback.REASON_FINISHED:
--            // If there is an onRow handler, we always resolve to null.
--            let result = onRow ? null : rows;
--            deferred.resolve(result);
--            break;
--
--          case Ci.mozIStorageStatementCallback.REASON_CANCELLED:
--            // It is not an error if the user explicitly requested cancel via
--            // the onRow handler.
--            if (userCancelled) {
--              let result = onRow ? null : rows;
--              deferred.resolve(result);
--            } else {
--              deferred.reject(new Error("Statement was cancelled."));
-+    // FIXME(nsm): Fix this god-awful indentation!
-+    let promise = new Promise((resolve, reject) => {
-+      let pending = statement.executeAsync({
-+        handleResult: function (resultSet) {
-+          // .cancel() may not be immediate and handleResult() could be called
-+          // after a .cancel().
-+          for (let row = resultSet.getNextRow(); row && !userCancelled; row = resultSet.getNextRow()) {
-+            if (!onRow) {
-+              rows.push(row);
-+              continue;
-             }
- 
--            break;
-+            try {
-+              onRow(row);
-+            } catch (e if e instanceof StopIteration) {
-+              userCancelled = true;
-+              pending.cancel();
-+              break;
-+            } catch (ex) {
-+              self._log.warn("Exception when calling onRow callback: " +
-+                             CommonUtils.exceptionStr(ex));
-+            }
-+          }
-+        },
- 
--          case Ci.mozIStorageStatementCallback.REASON_ERROR:
--            let error = new Error("Error(s) encountered during statement execution.");
--            error.errors = errors;
--            deferred.reject(error);
--            break;
-+        handleError: function (error) {
-+          self._log.info("Error when executing SQL (" + error.result + "): " +
-+                         error.message);
-+          errors.push(error);
-+        },
- 
--          default:
--            deferred.reject(new Error("Unknown completion reason code: " +
--                                      reason));
--            break;
--        }
--      },
-+        handleCompletion: function (reason) {
-+          self._log.debug("Stmt #" + index + " finished.");
-+          self._pendingStatements.delete(index);
-+
-+          switch (reason) {
-+            case Ci.mozIStorageStatementCallback.REASON_FINISHED:
-+              // If there is an onRow handler, we always resolve to null.
-+              let result = onRow ? null : rows;
-+              resolve(result);
-+              break;
-+
-+            case Ci.mozIStorageStatementCallback.REASON_CANCELLED:
-+              // It is not an error if the user explicitly requested cancel via
-+              // the onRow handler.
-+              if (userCancelled) {
-+                let result = onRow ? null : rows;
-+                resolve(result);
-+              } else {
-+                reject(new Error("Statement was cancelled."));
-+              }
-+
-+              break;
-+
-+            case Ci.mozIStorageStatementCallback.REASON_ERROR:
-+              let error = new Error("Error(s) encountered during statement execution.");
-+              error.errors = errors;
-+              reject(error);
-+              break;
-+
-+            default:
-+              reject(new Error("Unknown completion reason code: " + reason));
-+              break;
-+          }
-+        },
-+      });
-+      this._pendingStatements.set(index, pending);
-     });
- 
--    this._pendingStatements.set(index, pending);
--    return deferred.promise;
-+    return promise;
-   },
- 
-   _ensureOpen: function () {
-     if (!this._open) {
-       throw new Error("Connection is not open.");
-     }
-   },
- 
-diff --git a/toolkit/modules/Task.jsm b/toolkit/modules/Task.jsm
---- a/toolkit/modules/Task.jsm
-+++ b/toolkit/modules/Task.jsm
-@@ -86,17 +86,17 @@ this.EXPORTED_SYMBOLS = [
- ////////////////////////////////////////////////////////////////////////////////
- //// Globals
- 
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Cu = Components.utils;
- const Cr = Components.results;
- 
--Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
-+Cu.importGlobalProperties(["Promise"]);
- 
- // The following error types are considered programmer errors, which should be
- // reported (possibly redundantly) so as to let programmers fix their code.
- const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"];
- 
- /**
-  * Detect whether a value is a generator.
-  *
-@@ -144,17 +144,18 @@ this.Task = {
-         return Promise.resolve(ex.value);
-       } catch (ex) {
-         return Promise.reject(ex);
-       }
-     }
- 
-     if (isGenerator(aTask)) {
-       // This is an iterator resulting from calling a generator function.
--      return new TaskImpl(aTask).deferred.promise;
-+      let taskImpl = new TaskImpl(aTask);
-+      return taskImpl.run();
-     }
- 
-     // Just propagate the given value to the caller as a resolved promise.
-     return Promise.resolve(aTask);
-   },
- 
-   /**
-    * Constructs a special exception that, when thrown inside a legacy generator
-@@ -171,83 +172,79 @@ this.Task = {
- ////////////////////////////////////////////////////////////////////////////////
- //// TaskImpl
- 
- /**
-  * Executes the specified iterator as a task, and gives access to the promise
-  * that is fulfilled when the task terminates.
-  */
- function TaskImpl(iterator) {
--  this.deferred = Promise.defer();
-   this._iterator = iterator;
-   this._isStarGenerator = !("send" in iterator);
--  this._run(true);
- }
- 
- TaskImpl.prototype = {
-   /**
--   * Includes the promise object where task completion callbacks are registered,
--   * and methods to resolve or reject the promise at task completion.
--   */
--  deferred: null,
--
--  /**
-    * The iterator returned by the generator function associated with this task.
-    */
-   _iterator: null,
- 
-   /**
-    * Whether this Task is using a star generator.
-    */
-   _isStarGenerator: false,
- 
-+  run: function TaskImpl_run() {
-+    return this._run(true);
-+  },
-+
-   /**
-    * Main execution routine, that calls into the generator function.
-    *
-    * @param aSendResolved
-    *        If true, indicates that we should continue into the generator
-    *        function regularly (if we were waiting on a promise, it was
--   *        resolved). If true, indicates that we should cause an exception to
-+   *        resolved). If false, indicates that we should cause an exception to
-    *        be thrown into the generator function (if we were waiting on a
-    *        promise, it was rejected).
-    * @param aSendValue
-    *        Resolution result or rejection exception, if any.
-    */
--  _run: function TaskImpl_run(aSendResolved, aSendValue) {
-+  _run: function TaskImpl_run_private(aSendResolved, aSendValue) {
-     if (this._isStarGenerator) {
-       try {
-         let result = aSendResolved ? this._iterator.next(aSendValue)
-                                    : this._iterator.throw(aSendValue);
- 
-         if (result.done) {
-           // The generator function returned.
--          this.deferred.resolve(result.value);
-+          return Promise.resolve(result.value);
-         } else {
-           // The generator function yielded.
--          this._handleResultValue(result.value);
-+          return this._handleResultValue(result.value);
-         }
-       } catch (ex) {
-         // The generator function failed with an uncaught exception.
--        this._handleException(ex);
-+        return this._handleException(ex);
-       }
-     } else {
-       try {
-         let yielded = aSendResolved ? this._iterator.send(aSendValue)
-                                     : this._iterator.throw(aSendValue);
--        this._handleResultValue(yielded);
-+        return this._handleResultValue(yielded);
-       } catch (ex if ex instanceof Task.Result) {
-         // The generator function threw the special exception that allows it to
-         // return a specific value on resolution.
--        this.deferred.resolve(ex.value);
-+        return Promise.resolve(ex.value);
-       } catch (ex if ex instanceof StopIteration) {
-         // The generator function terminated with no specific result.
--        this.deferred.resolve();
-+        return Promise.resolve();
-       } catch (ex) {
-         // The generator function failed with an uncaught exception.
--        this._handleException(ex);
-+        return this._handleException(ex);
-       }
-     }
-   },
- 
-   /**
-    * Handle a value yielded by a generator.
-    *
-    * @param aValue
-@@ -260,22 +257,22 @@ TaskImpl.prototype = {
-     if (isGenerator(aValue)) {
-       aValue = Task.spawn(aValue);
-     }
- 
-     if (aValue && typeof(aValue.then) == "function") {
-       // We have a promise object now. When fulfilled, call again into this
-       // function to continue the task, with either a resolution or rejection
-       // condition.
--      aValue.then(this._run.bind(this, true),
--                  this._run.bind(this, false));
-+      return aValue.then(this._run.bind(this, true),
-+                         this._run.bind(this, false));
-     } else {
-       // If our task yielded a value that is not a promise, just continue and
-       // pass it directly as the result of the yield statement.
--      this._run(true, aValue);
-+      return this._run(true, aValue);
-     }
-   },
- 
-   /**
-    * Handle an uncaught exception thrown from a generator.
-    *
-    * @param aException
-    *        The uncaught exception to handle.
-@@ -293,11 +290,11 @@ TaskImpl.prototype = {
-       let stack = ("stack" in aException) ? aException.stack : "not available";
-       dump("*************************\n");
-       dump("A coding exception was thrown and uncaught in a Task.\n\n");
-       dump("Full message: " + aException + "\n");
-       dump("Full stack: " + stack + "\n");
-       dump("*************************\n");
-     }
- 
--    this.deferred.reject(aException);
-+    return Promise.reject(aException);
-   }
- };
-diff --git a/toolkit/modules/tests/xpcshell/test_AsyncShutdown.js b/toolkit/modules/tests/xpcshell/test_AsyncShutdown.js
---- a/toolkit/modules/tests/xpcshell/test_AsyncShutdown.js
-+++ b/toolkit/modules/tests/xpcshell/test_AsyncShutdown.js
-@@ -1,12 +1,11 @@
- let Cu = Components.utils;
- 
- Cu.import("resource://gre/modules/Services.jsm");
--Cu.import("resource://gre/modules/Promise.jsm");
- Cu.import("resource://gre/modules/AsyncShutdown.jsm");
- 
- Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true);
- 
- /**
-  * An asynchronous task that takes several ticks to complete.
-  *
-  * @param {*=} resolution The value with which the resulting promise will be
-@@ -18,23 +17,23 @@ Services.prefs.setBoolPref("toolkit.asyn
-  *
-  * @return {promise} A promise fulfilled once the task is complete
-  */
- function longRunningAsyncTask(resolution = undefined, outResult = {}) {
-   outResult.isFinished = false;
-   if (!("countFinished" in outResult)) {
-     outResult.countFinished = 0;
-   }
--  let deferred = Promise.defer();
--  do_timeout(100, function() {
--    ++outResult.countFinished;
--    outResult.isFinished = true;
--    deferred.resolve(resolution);
-+  return new Promise(function(resolve) {
-+    do_timeout(100, function() {
-+      ++outResult.countFinished;
-+      outResult.isFinished = true;
-+      resolve(resolution);
-+    });
-   });
--  return deferred.promise;
- }
- 
- /**
-  * Generate a unique notification topic.
-  */
- function getUniqueTopic() {
-   const PREFIX = "testing-phases-";
-   return PREFIX + ++getUniqueTopic.counter;
-diff --git a/toolkit/modules/tests/xpcshell/test_sqlite.js b/toolkit/modules/tests/xpcshell/test_sqlite.js
---- a/toolkit/modules/tests/xpcshell/test_sqlite.js
-+++ b/toolkit/modules/tests/xpcshell/test_sqlite.js
-@@ -2,40 +2,39 @@
-  * http://creativecommons.org/publicdomain/zero/1.0/ */
- 
- "use strict";
- 
- const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
- 
- do_get_profile();
- 
--Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
- Cu.import("resource://gre/modules/osfile.jsm");
- Cu.import("resource://gre/modules/FileUtils.jsm");
- Cu.import("resource://gre/modules/Services.jsm");
- Cu.import("resource://gre/modules/Sqlite.jsm");
- Cu.import("resource://gre/modules/Task.jsm");
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
- 
- // To spin the event loop in test.
- Cu.import("resource://services-common/async.js");
- 
-+Cu.importGlobalProperties(["Promise"]);
-+
- function sleep(ms) {
--  let deferred = Promise.defer();
--
-   let timer = Cc["@mozilla.org/timer;1"]
-                 .createInstance(Ci.nsITimer);
- 
--  timer.initWithCallback({
--    notify: function () {
--      deferred.resolve();
--    },
--  }, ms, timer.TYPE_ONE_SHOT);
--
--  return deferred.promise;
-+  return new Promise(function(resolve) {
-+    timer.initWithCallback({
-+      notify: function () {
-+        resolve();
-+      },
-+    }, ms, timer.TYPE_ONE_SHOT);
-+  });
- }
- 
- function getConnection(dbName, extraOptions={}) {
-   let path = dbName + ".sqlite";
-   let options = {path: path};
-   for (let [k, v] in Iterator(extraOptions)) {
-     options[k] = v;
-   }
-@@ -247,26 +246,22 @@ add_task(function test_close_cached() {
-   yield c.executeCached("SELECT * FROM files");
- 
-   yield c.close();
- });
- 
- add_task(function test_execute_invalid_statement() {
-   let c = yield getDummyDatabase("invalid_statement");
- 
--  let deferred = Promise.defer();
--
-   do_check_eq(c._anonymousStatements.size, 0);
- 
--  c.execute("SELECT invalid FROM unknown").then(do_throw, function onError(error) {
--    deferred.resolve();
-+  yield c.execute("SELECT invalid FROM unknown").then(do_throw, function onError(error) {
-+    return Promise.resolve();
-   });
- 
--  yield deferred.promise;
--
-   // Ensure we don't leak the statement instance.
-   do_check_eq(c._anonymousStatements.size, 0);
- 
-   yield c.close();
- });
- 
- add_task(function test_on_row_exception_ignored() {
-   let c = yield getDummyDatabase("on_row_exception_ignored");
-@@ -311,24 +306,22 @@ add_task(function test_on_row_stop_itera
- 
-   yield c.close();
- });
- 
- add_task(function test_invalid_transaction_type() {
-   let c = yield getDummyDatabase("invalid_transaction_type");
- 
-   let errored = false;
--  try {
--    c.executeTransaction(function () {}, "foobar");
--  } catch (ex) {
-+  yield c.executeTransaction(function () {}, "foobar").catch((ex) => {
-     errored = true;
-     do_check_true(ex.message.startsWith("Unknown transaction type"));
--  } finally {
-+  }).then(() => {
-     do_check_true(errored);
--  }
-+  });
- 
-   yield c.close();
- });
- 
- add_task(function test_execute_transaction_success() {
-   let c = yield getDummyDatabase("execute_transaction_success");
- 
-   do_check_false(c.transactionInProgress);
-@@ -346,31 +339,27 @@ add_task(function test_execute_transacti
-   do_check_eq(rows.length, 1);
- 
-   yield c.close();
- });
- 
- add_task(function test_execute_transaction_rollback() {
-   let c = yield getDummyDatabase("execute_transaction_rollback");
- 
--  let deferred = Promise.defer();
--
--  c.executeTransaction(function transaction(conn) {
-+  yield c.executeTransaction(function transaction(conn) {
-     yield conn.execute("INSERT INTO dirs (path) VALUES ('foo')");
-     print("Expecting error with next statement.");
-     yield conn.execute("INSERT INTO invalid VALUES ('foo')");
- 
-     // We should never get here.
-     do_throw();
-   }).then(do_throw, function onError(error) {
--    deferred.resolve();
-+    return Promise.resolve();
-   });
- 
--  yield deferred.promise;
--
-   let rows = yield c.execute("SELECT * FROM dirs");
-   do_check_eq(rows.length, 0);
- 
-   yield c.close();
- });
- 
- add_task(function test_close_during_transaction() {
-   let c = yield getDummyDatabase("close_during_transaction");
-@@ -777,59 +766,58 @@ add_task(function test_direct() {
-   let two = params.newBindingParams();
-   two.bindByName("name", "bar");
-   params.addParams(two);
- 
-   print("Beginning transaction.");
-   let begin = db.createAsyncStatement("BEGIN DEFERRED TRANSACTION");
-   let end = db.createAsyncStatement("COMMIT TRANSACTION");
- 
--  let deferred = Promise.defer();
--  begin.executeAsync({
--    handleCompletion: function (reason) {
--      deferred.resolve();
--    }
-+  yield new Promise(function(resolve) {
-+    begin.executeAsync({
-+      handleCompletion: function (reason) {
-+        resolve();
-+      }
-+    });
-   });
--  yield deferred.promise;
- 
-   statement.bindParameters(params);
- 
--  deferred = Promise.defer();
-   print("Executing async.");
--  statement.executeAsync({
--    handleResult: function (resultSet) {
--    },
-+  yield new Promise(function(resolve, reject) {
-+    statement.executeAsync({
-+      handleResult: function (resultSet) {
-+      },
- 
--    handleError:  function (error) {
--      print("Error when executing SQL (" + error.result + "): " +
--            error.message);
--      print("Original error: " + error.error);
--      errors.push(error);
--      deferred.reject();
--    },
-+      handleError:  function (error) {
-+        print("Error when executing SQL (" + error.result + "): " +
-+              error.message);
-+        print("Original error: " + error.error);
-+        errors.push(error);
-+        reject();
-+      },
- 
--    handleCompletion: function (reason) {
--      print("Completed.");
--      deferred.resolve();
--    }
-+      handleCompletion: function (reason) {
-+        print("Completed.");
-+        resolve();
-+      }
-+    });
-   });
- 
--  yield deferred.promise;
--
--  deferred = Promise.defer();
--  end.executeAsync({
--    handleCompletion: function (reason) {
--      deferred.resolve();
--    }
-+  yield new Promise(function(resolve) {
-+    end.executeAsync({
-+      handleCompletion: function (reason) {
-+        resolve();
-+      }
-+    });
-   });
--  yield deferred.promise;
- 
-   statement.finalize();
-   begin.finalize();
-   end.finalize();
- 
--  deferred = Promise.defer();
--  db.asyncClose(function () {
--    deferred.resolve()
-+  yield new Promise(function(resolve) {
-+    db.asyncClose(function () {
-+      resolve();
-+    });
-   });
--  yield deferred.promise;
- });
- 
-diff --git a/toolkit/modules/tests/xpcshell/test_task.js b/toolkit/modules/tests/xpcshell/test_task.js
---- a/toolkit/modules/tests/xpcshell/test_task.js
-+++ b/toolkit/modules/tests/xpcshell/test_task.js
-@@ -9,49 +9,37 @@
- /// Globals
- 
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Cu = Components.utils;
- const Cr = Components.results;
- 
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-+Cu.importGlobalProperties(["Promise"]);
- 
--XPCOMUtils.defineLazyModuleGetter(this, "Promise",
--                                  "resource://gre/modules/commonjs/sdk/core/promise.js");
- XPCOMUtils.defineLazyModuleGetter(this, "Services",
-                                   "resource://gre/modules/Services.jsm");
- XPCOMUtils.defineLazyModuleGetter(this, "Task",
-                                   "resource://gre/modules/Task.jsm");
- 
--/**
-- * Returns a promise that will be resolved with the given value, when an event
-- * posted on the event loop of the main thread is processed.
-- */
--function promiseResolvedLater(aValue) {
--  let deferred = Promise.defer();
--  Services.tm.mainThread.dispatch(function () deferred.resolve(aValue),
--                                  Ci.nsIThread.DISPATCH_NORMAL);
--  return deferred.promise;
--}
--
- ////////////////////////////////////////////////////////////////////////////////
- /// Tests
- 
- function run_test()
- {
-   run_next_test();
- }
- 
- add_test(function test_normal()
- {
-   Task.spawn(function () {
-     let result = yield Promise.resolve("Value");
-     for (let i = 0; i < 3; i++) {
--      result += yield promiseResolvedLater("!");
-+      result += yield Promise.resolve("!");
-     }
-     throw new Task.Result("Task result: " + result);
-   }).then(function (result) {
-     do_check_eq("Task result: Value!!!", result);
-     run_next_test();
-   }, function (ex) {
-     do_throw("Unexpected error: " + ex);
-   });
-@@ -179,17 +167,17 @@ add_test(function test_yielded_primitive
-   });
- });
- 
- add_test(function test_star_normal()
- {
-   Task.spawn(function* () {
-     let result = yield Promise.resolve("Value");
-     for (let i = 0; i < 3; i++) {
--      result += yield promiseResolvedLater("!");
-+      result += yield Promise.resolve("!");
-     }
-     return "Task result: " + result;
-   }).then(function (result) {
-     do_check_eq("Task result: Value!!!", result);
-     run_next_test();
-   }, function (ex) {
-     do_throw("Unexpected error: " + ex);
-   });
-diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm
---- a/toolkit/mozapps/extensions/AddonManager.jsm
-+++ b/toolkit/mozapps/extensions/AddonManager.jsm
-@@ -55,19 +55,18 @@ var PREF_EM_CHECK_COMPATIBILITY;
- 
- const TOOLKIT_ID                      = "toolkit@mozilla.org";
- 
- const VALID_TYPES_REGEXP = /^[\w\-]+$/;
- 
- Cu.import("resource://gre/modules/Services.jsm");
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
- Cu.import("resource://gre/modules/AsyncShutdown.jsm");
-+Cu.importGlobalProperties(["Promise"]);
- 
--XPCOMUtils.defineLazyModuleGetter(this, "Promise",
--                                  "resource://gre/modules/Promise.jsm");
- XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
-                                   "resource://gre/modules/AddonRepository.jsm");
- 
- XPCOMUtils.defineLazyGetter(this, "CertUtils", function certUtilsLazyGetter() {
-   let certUtils = {};
-   Components.utils.import("resource://gre/modules/CertUtils.jsm", certUtils);
-   return certUtils;
- });
-diff --git a/toolkit/mozapps/extensions/AddonRepository.jsm b/toolkit/mozapps/extensions/AddonRepository.jsm
---- a/toolkit/mozapps/extensions/AddonRepository.jsm
-+++ b/toolkit/mozapps/extensions/AddonRepository.jsm
-@@ -7,29 +7,28 @@
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Cu = Components.utils;
- const Cr = Components.results;
- 
- Components.utils.import("resource://gre/modules/Services.jsm");
- Components.utils.import("resource://gre/modules/AddonManager.jsm");
- Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-+Cu.importGlobalProperties(["Promise"]);
- 
- 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, "DeferredSave",
-                                   "resource://gre/modules/DeferredSave.jsm");
- XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository_SQLiteMigrator",
-                                   "resource://gre/modules/AddonRepository_SQLiteMigrator.jsm");
--XPCOMUtils.defineLazyModuleGetter(this, "Promise",
--                                  "resource://gre/modules/Promise.jsm");
- 
- this.EXPORTED_SYMBOLS = [ "AddonRepository" ];
- 
- const PREF_GETADDONS_CACHE_ENABLED       = "extensions.getAddons.cache.enabled";
- const PREF_GETADDONS_CACHE_TYPES         = "extensions.getAddons.cache.types";
- const PREF_GETADDONS_CACHE_ID_ENABLED    = "extensions.%ID%.getAddons.cache.enabled"
- const PREF_GETADDONS_BROWSEADDONS        = "extensions.getAddons.browseAddons";
- const PREF_GETADDONS_BYIDS               = "extensions.getAddons.get.url";
-diff --git a/toolkit/webapps/WebappsInstaller.jsm b/toolkit/webapps/WebappsInstaller.jsm
---- a/toolkit/webapps/WebappsInstaller.jsm
-+++ b/toolkit/webapps/WebappsInstaller.jsm
-@@ -11,17 +11,17 @@ const Cr = Components.results;
- 
- Cu.import("resource://gre/modules/Services.jsm");
- Cu.import("resource://gre/modules/FileUtils.jsm");
- Cu.import("resource://gre/modules/NetUtil.jsm");
- Cu.import("resource://gre/modules/osfile.jsm");
- Cu.import("resource://gre/modules/WebappOSUtils.jsm");
- Cu.import("resource://gre/modules/AppsUtils.jsm");
- Cu.import("resource://gre/modules/Task.jsm");
--Cu.import("resource://gre/modules/Promise.jsm");
-+Cu.importGlobalProperties(["Promise"]);
- 
- // 0755
- const PERMS_DIRECTORY = OS.Constants.libc.S_IRWXU |
-                         OS.Constants.libc.S_IRGRP | OS.Constants.libc.S_IXGRP |
-                         OS.Constants.libc.S_IROTH | OS.Constants.libc.S_IXOTH;
- 
- // 0644
- const PERMS_FILE = OS.Constants.libc.S_IRUSR | OS.Constants.libc.S_IWUSR |
-@@ -611,38 +611,37 @@ WinNativeApp.prototype = {
-    * Process the icon from the imageStream as retrieved from
-    * the URL by getIconForApp(). This will save the icon to the
-    * topwindow.ico file.
-    *
-    * @param aMimeType     ahe icon mimetype
-    * @param aImageStream  the stream for the image data
-    */
-   processIcon: function(aMimeType, aImageStream) {
--    let deferred = Promise.defer();
--
-     let imgTools = Cc["@mozilla.org/image/tools;1"]
-                      .createInstance(Ci.imgITools);
- 
-     let imgContainer = imgTools.decodeImage(aImageStream, aMimeType);
-     let iconStream = imgTools.encodeImage(imgContainer,
-                                           "image/vnd.microsoft.icon",
-                                           "format=bmp;bpp=32");
- 
-     let tmpIconFile = getFile(this.tmpInstallDir, this.iconPath);
- 
-     let outputStream = FileUtils.openSafeFileOutputStream(tmpIconFile);
--    NetUtil.asyncCopy(iconStream, outputStream, function(aResult) {
--      if (Components.isSuccessCode(aResult)) {
--        deferred.resolve();
--      } else {
--        deferred.reject("Failure copying icon: " + aResult);
--      }
-+    let promise = new Promise(function(resolve, reject) {
-+      NetUtil.asyncCopy(iconStream, outputStream, function(aResult) {
-+        if (Components.isSuccessCode(aResult)) {
-+          resolve();
-+        }
-+        reject("Failure copying icon: " + aResult);
-+      });
-     });
- 
--    return deferred.promise;
-+    return promise;
-   }
- }
- 
- #elifdef XP_MACOSX
- 
- const USER_LIB_DIR = OS.Constants.Path.macUserLibDir;
- const LOCAL_APP_DIR = OS.Constants.Path.macLocalApplicationsDir;
- 
-@@ -814,39 +813,40 @@ MacNativeApp.prototype = {
-    * Process the icon from the imageStream as retrieved from
-    * the URL by getIconForApp(). This will bundle the icon to the
-    * app package at Contents/Resources/appicon.icns.
-    *
-    * @param aMimeType     the icon mimetype
-    * @param aImageStream  the stream for the image data
-    */
-   processIcon: function(aMimeType, aIcon) {
--    let deferred = Promise.defer();
--
-     function conversionDone(aSubject, aTopic) {
--      if (aTopic == "process-finished") {
--        deferred.resolve();
--      } else {
--        deferred.reject("Failure converting icon.");
--      }
-     }
- 
-     let process = Cc["@mozilla.org/process/util;1"].
-                   createInstance(Ci.nsIProcess);
-     let sipsFile = getFile("/usr/bin/sips");
- 
-     process.init(sipsFile);
--    process.runAsync(["-s",
--                "format", "icns",
--                aIcon.path,
--                "--out", OS.Path.join(this.tmpInstallDir, this.iconFile),
--                "-z", "128", "128"],
--                9, conversionDone);
- 
--    return deferred.promise;
-+    let runAsync = new Promise(function(resolve) {
-+      process.runAsync(["-s",
-+                  "format", "icns",
-+                  aIcon.path,
-+                  "--out", OS.Path.join(this.tmpInstallDir, this.iconFile),
-+                  "-z", "128", "128"],
-+                  9, resolve);
-+    });
-+
-+    return runAsync.then(function(aSubject, aTopic) {
-+      if (aTopic == "process-finished") {
-+        return;
-+      }
-+      throw "Failure converting icon.";
-+    });
-   }
- 
- }
- 
- #elifdef XP_UNIX
- 
- function LinuxNativeApp(aData) {
-   NativeApp.call(this, aData);
-@@ -1048,35 +1048,36 @@ LinuxNativeApp.prototype = {
-   /**
-    * Process the icon from the imageStream as retrieved from
-    * the URL by getIconForApp().
-    *
-    * @param aMimeType     ahe icon mimetype
-    * @param aImageStream  the stream for the image data
-    */
-   processIcon: function(aMimeType, aImageStream) {
--    let deferred = Promise.defer();
--
-     let imgTools = Cc["@mozilla.org/image/tools;1"]
-                      .createInstance(Ci.imgITools);
- 
-     let imgContainer = imgTools.decodeImage(aImageStream, aMimeType);
-     let iconStream = imgTools.encodeImage(imgContainer, "image/png");
- 
-     let iconFile = getFile(this.tmpInstallDir, this.iconFile);
-     let outputStream = FileUtils.openSafeFileOutputStream(iconFile);
--    NetUtil.asyncCopy(iconStream, outputStream, function(aResult) {
--      if (Components.isSuccessCode(aResult)) {
--        deferred.resolve();
--      } else {
--        deferred.reject("Failure copying icon: " + aResult);
--      }
-+
-+    let promise = new Promise(function(resolve, reject) {
-+      NetUtil.asyncCopy(iconStream, outputStream, function(aResult) {
-+        if (Components.isSuccessCode(aResult)) {
-+          resolve();
-+        } else {
-+          reject("Failure copying icon: " + aResult);
-+        }
-+      });
-     });
- 
--    return deferred.promise;
-+    return promise;
-   }
- }
- 
- #endif
- 
- /* Helper Functions */
- 
- /**
--- a/series
+++ b/series
@@ -12,12 +12,11 @@ 903441-navigation-event
 903441-setup-request
 903441-intercepts
 903441-sw-nointercept
 foo
 898524-cache
 sw-install-tests2
 sw-more-install-tests
 943704-importscripts
-939636-toolkit
 promise-nsresult
 984048-swutil-fetcher
 984048-swm-update+