Bug 1003109 - Replace TaskUtils.spawn with Task.spawn. r=Yoric
☠☠ backed out by 7bb33e71b2a0 ☠ ☠
authorBirunthan Mohanathas <birunthan@mohanathas.com>
Tue, 29 Apr 2014 05:31:00 -0400
changeset 181225 77abda00ae6e698c3735088eeab8618b46b277e8
parent 181224 c4cdaf3bd2d431e475659bfd4490e518a9501aff
child 181226 7de28e99eb681332a6388f96911a925544854423
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersYoric
bugs1003109
milestone32.0a1
Bug 1003109 - Replace TaskUtils.spawn with Task.spawn. r=Yoric
toolkit/components/search/nsSearchService.js
toolkit/components/thumbnails/PageThumbs.jsm
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -293,81 +293,16 @@ function FAIL(message, resultCode) {
 function limitURILength(str, len) {
   len = len || 140;
   if (str.length > len)
     return str.slice(0, len) + "...";
   return str;
 }
 
 /**
- * Utilities for dealing with promises and Task.jsm
- */
-const TaskUtils = {
-  /**
-   * Add logging to a promise.
-   *
-   * @param {Promise} promise
-   * @return {Promise} A promise behaving as |promise|, but with additional
-   * logging in case of uncaught error.
-   */
-  captureErrors: function captureErrors(promise) {
-    return promise.then(
-      null,
-      function onError(reason) {
-        LOG("Uncaught asynchronous error: " + reason + " at\n" + reason.stack);
-        throw reason;
-      }
-    );
-  },
-  /**
-   * Spawn a new Task from a generator.
-   *
-   * This function behaves as |Task.spawn|, with the exception that it
-   * adds logging in case of uncaught error. For more information, see
-   * the documentation of |Task.jsm|.
-   *
-   * @param {generator} gen Some generator.
-   * @return {Promise} A promise built from |gen|, with the same semantics
-   * as |Task.spawn(gen)|.
-   */
-  spawn: function spawn(gen) {
-    return this.captureErrors(Task.spawn(gen));
-  },
-  /**
-   * Execute a mozIStorage statement asynchronously, wrapping the
-   * result in a promise.
-   *
-   * @param {mozIStorageStaement} statement A statement to be executed
-   * asynchronously. The semantics are the same as these of |statement.execute|.
-   * @param {function*} onResult A callback, called for each successive result.
-   *
-   * @return {Promise} A promise, resolved successfully if |statement.execute|
-   * succeeds, rejected if it fails.
-   */
-  executeStatement: function executeStatement(statement, onResult) {
-    let deferred = Promise.defer();
-    onResult = onResult || function() {};
-    statement.executeAsync({
-      handleResult: onResult,
-      handleError: function handleError(aError) {
-        deferred.reject(aError);
-      },
-      handleCompletion: function handleCompletion(aReason) {
-        statement.finalize();
-        // Note that, in case of error, deferred.reject(aError)
-        // has already been called by this point, so the call to
-        // |deferred.resolve| is simply ignored.
-        deferred.resolve(aReason);
-      }
-    });
-    return deferred.promise;
-  }
-};
-
-/**
  * Ensures an assertion is met before continuing. Should be used to indicate
  * fatal errors.
  * @param  assertion
  *         An assertion that must be met
  * @param  message
  *         A message to display if the assertion is not met
  * @param  resultCode
  *         The NS_ERROR_* value to throw if the assertion is not met
@@ -1248,17 +1183,17 @@ Engine.prototype = {
   /**
    * Retrieves the data from the engine's file asynchronously. If the engine's
    * dataType is XML, the document element is placed in the engine's data field.
    *
    * @returns {Promise} A promise, resolved successfully if initializing from
    * data succeeds, rejected if it fails.
    */
   _asyncInitFromFile: function SRCH_ENG__asyncInitFromFile() {
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       if (!this._file || !(yield OS.File.exists(this._file.path)))
         FAIL("File must exist before calling initFromFile!", Cr.NS_ERROR_UNEXPECTED);
 
       if (this._dataType == SEARCH_DATA_XML) {
         let fileURI = NetUtil.ioService.newFileURI(this._file);
         yield this._retrieveSearchXMLData(fileURI.spec);
       } else {
         ERROR("Unsuppored engine _dataType in _initFromFile: \"" +
@@ -1297,17 +1232,17 @@ Engine.prototype = {
 
   /**
    * Retrieves the engine data from a URI asynchronously and initializes it.
    *
    * @returns {Promise} A promise, resolved successfully if retrieveing data
    * succeeds.
    */
   _asyncInitFromURI: function SRCH_ENG__asyncInitFromURI() {
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       LOG("_asyncInitFromURI: Loading engine from: \"" + this._uri.spec + "\".");
       yield this._retrieveSearchXMLData(this._uri.spec);
       // Now that the data is loaded, initialize the engine object
       this._initFromData();
     }.bind(this));
   },
 
   /**
@@ -2946,17 +2881,17 @@ SearchService.prototype = {
 
   /**
    * Asynchronous implementation of the initializer.
    *
    * @returns {Promise} A promise, resolved successfully if the initialization
    * succeeds.
    */
   _asyncInit: function SRCH_SVC__asyncInit() {
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       LOG("_asyncInit start");
       try {
         yield checkForSyncCompletion(this._asyncLoadEngines());
       } catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
         this._initRV = Cr.NS_ERROR_FAILURE;
         LOG("_asyncInit: failure loading engines: " + ex);
       }
       this._addObservers();
@@ -3143,17 +3078,17 @@ SearchService.prototype = {
 
   /**
    * Loads engines asynchronously.
    *
    * @returns {Promise} A promise, resolved successfully if loading data
    * succeeds.
    */
   _asyncLoadEngines: function SRCH_SVC__asyncLoadEngines() {
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       LOG("_asyncLoadEngines: start");
       // See if we have a cache file so we don't have to parse a bunch of XML.
       let cache = {};
       let cacheEnabled = getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true);
       if (cacheEnabled) {
         let cacheFilePath = OS.Path.join(OS.Constants.Path.profileDir, "search.json");
         cache = yield checkForSyncCompletion(this._asyncReadCacheFile(cacheFilePath));
       }
@@ -3183,17 +3118,17 @@ SearchService.prototype = {
       if (loadFromJARs) {
         Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "find-jar-engines");
         [chromeFiles, chromeURIs] =
           yield checkForSyncCompletion(this._asyncFindJAREngines());
       }
 
       let toLoad = chromeFiles.concat(loadDirs);
       function hasModifiedDir(aList) {
-        return TaskUtils.spawn(function() {
+        return Task.spawn(function*() {
           let modifiedDir = false;
 
           for (let dir of aList) {
             if (!cache.directories || !cache.directories[dir.path]) {
               modifiedDir = true;
               break;
             }
 
@@ -3270,17 +3205,17 @@ SearchService.prototype = {
    * Read from a given cache file asynchronously.
    *
    * @param aPath the file path.
    *
    * @returns {Promise} A promise, resolved successfully if retrieveing data
    * succeeds.
    */
   _asyncReadCacheFile: function SRCH_SVC__asyncReadCacheFile(aPath) {
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       let json;
       try {
         let bytes = yield OS.File.read(aPath);
         json = JSON.parse(new TextDecoder().decode(bytes));
       } catch (ex) {
         LOG("_asyncReadCacheFile: Error reading cache file: " + ex);
         json = {};
       }
@@ -3434,17 +3369,17 @@ SearchService.prototype = {
    * succeeds.
    */
   _asyncLoadEnginesFromDir: function SRCH_SVC__asyncLoadEnginesFromDir(aDir) {
     LOG("_asyncLoadEnginesFromDir: Searching in " + aDir.path + " for search engines.");
 
     // Check whether aDir is the user profile dir
     let isInProfile = aDir.equals(getDir(NS_APP_USER_SEARCH_DIR));
     let iterator = new OS.File.DirectoryIterator(aDir.path);
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       let osfiles = yield iterator.nextBatch();
       iterator.close();
 
       let engines = [];
       for (let osfile of osfiles) {
         if (osfile.isDir || osfile.isSymLink)
           continue;
 
@@ -3494,17 +3429,17 @@ SearchService.prototype = {
    * Loads engines from Chrome URLs asynchronously.
    *
    * @param aURLs a list of URLs.
    *
    * @returns {Promise} A promise, resolved successfully if loading data
    * succeeds.
    */
   _asyncLoadFromChromeURLs: function SRCH_SVC__asyncLoadFromChromeURLs(aURLs) {
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       let engines = [];
       for (let url of aURLs) {
         try {
           LOG("_asyncLoadFromChromeURLs: loading engine from chrome url: " + url);
           let engine = new Engine(NetUtil.newURI(url), SEARCH_DATA_XML, true);
           yield checkForSyncCompletion(engine._asyncInitFromURI());
           engines.push(engine);
         } catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
@@ -3578,17 +3513,17 @@ SearchService.prototype = {
 
   /**
    * Loads jar engines asynchronously.
    *
    * @returns {Promise} A promise, resolved successfully if finding jar engines
    * succeeds.
    */
   _asyncFindJAREngines: function SRCH_SVC__asyncFindJAREngines() {
-    return TaskUtils.spawn(function() {
+    return Task.spawn(function*() {
       LOG("_asyncFindJAREngines: looking for engines in JARs")
 
       let rootURIPref = "";
       try {
         rootURIPref = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + "jarURIs");
       } catch (ex) {}
 
       if (!rootURIPref) {
@@ -3783,42 +3718,42 @@ SearchService.prototype = {
 
   // nsIBrowserSearchService
   init: function SRCH_SVC_init(observer) {
     LOG("SearchService.init");
     let self = this;
     if (!this._initStarted) {
       TelemetryStopwatch.start("SEARCH_SERVICE_INIT_MS");
       this._initStarted = true;
-      TaskUtils.spawn(function task() {
+      Task.spawn(function task() {
         try {
           yield checkForSyncCompletion(engineMetadataService.init());
           // Complete initialization by calling asynchronous initializer.
           yield self._asyncInit();
           TelemetryStopwatch.finish("SEARCH_SERVICE_INIT_MS");
         } catch (ex if ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
           // No need to pursue asynchronous because synchronous fallback was
           // called and has finished.
           TelemetryStopwatch.finish("SEARCH_SERVICE_INIT_MS");
         } catch (ex) {
           self._initObservers.reject(ex);
           TelemetryStopwatch.cancel("SEARCH_SERVICE_INIT_MS");
         }
       });
     }
     if (observer) {
-      TaskUtils.captureErrors(this._initObservers.promise.then(
+      this._initObservers.promise.then(
         function onSuccess() {
           observer.onInitComplete(self._initRV);
         },
         function onError(aReason) {
           Components.utils.reportError("Internal error while initializing SearchService: " + aReason);
           observer.onInitComplete(Components.results.NS_ERROR_UNEXPECTED);
         }
-      ));
+      );
     }
   },
 
   get isInitialized() {
     return gInitialized;
   },
 
   getEngines: function SRCH_SVC_getEngines(aCount) {
@@ -4328,17 +4263,17 @@ var engineMetadataService = {
    * Asynchronous initializer
    *
    * Note: In the current implementation, initialization never fails.
    */
   init: function epsInit() {
     if (!this._initializer) {
       // Launch asynchronous initialization
       let initializer = this._initializer = Promise.defer();
-      TaskUtils.spawn((function task_init() {
+      Task.spawn((function task_init() {
         LOG("metadata init: starting");
         switch (this._initState) {
           case engineMetadataService._InitStates.NOT_STARTED:
             // 1. Load json file if it exists
             try {
               let contents = yield OS.File.read(this._jsonFile);
               if (this._initState == engineMetadataService._InitStates.FINISHED_SUCCESS) {
                 // No need to pursue asynchronous initialization,
@@ -4369,17 +4304,17 @@ var engineMetadataService = {
         function onSuccess() {
           initializer.resolve();
         },
         function onError() {
           initializer.reject();
         }
       );
     }
-    return TaskUtils.captureErrors(this._initializer.promise);
+    return this._initializer.promise;
   },
 
   /**
    * Synchronous implementation of initializer
    *
    * This initializer is able to pick wherever the async initializer
    * is waiting. The asynchronous initializer is expected to stop
    * if it detects that the synchronous initializer has completed
@@ -4527,18 +4462,17 @@ var engineMetadataService = {
         promise = promise.then(
           function onSuccess() {
             Services.obs.notifyObservers(null,
               SEARCH_SERVICE_TOPIC,
               SEARCH_SERVICE_METADATA_WRITTEN);
             LOG("metadata writeCommit: done");
           }
         );
-        // Use our error logging instead of the default one.
-        return TaskUtils.captureErrors(promise).then(null, () => {});
+        return promise;
       }
       this._lazyWriter = new DeferredTask(writeCommit, LAZY_SERIALIZE_DELAY);
     }
     LOG("metadata _commit: (re)setting timer");
     this._lazyWriter.disarm();
     this._lazyWriter.arm();
   },
   _lazyWriter: null
--- a/toolkit/components/thumbnails/PageThumbs.jsm
+++ b/toolkit/components/thumbnails/PageThumbs.jsm
@@ -68,48 +68,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
   "resource://gre/modules/Deprecated.jsm");
 
 /**
  * Utilities for dealing with promises and Task.jsm
  */
 const TaskUtils = {
   /**
-   * Add logging to a promise.
-   *
-   * @param {Promise} promise
-   * @return {Promise} A promise behaving as |promise|, but with additional
-   * logging in case of uncaught error.
-   */
-  captureErrors: function captureErrors(promise) {
-    return promise.then(
-      null,
-      function onError(reason) {
-        Cu.reportError("Uncaught asynchronous error: " + reason + " at\n"
-          + reason.stack + "\n");
-        throw reason;
-      }
-    );
-  },
-
-  /**
-   * Spawn a new Task from a generator.
-   *
-   * This function behaves as |Task.spawn|, with the exception that it
-   * adds logging in case of uncaught error. For more information, see
-   * the documentation of |Task.jsm|.
-   *
-   * @param {generator} gen Some generator.
-   * @return {Promise} A promise built from |gen|, with the same semantics
-   * as |Task.spawn(gen)|.
-   */
-  spawn: function spawn(gen) {
-    return this.captureErrors(Task.spawn(gen));
-  },
-  /**
    * Read the bytes from a blob, asynchronously.
    *
    * @return {Promise}
    * @resolve {ArrayBuffer} In case of success, the bytes contained in the blob.
    * @reject {DOMError} In case of error, the underlying DOMError.
    */
   readBlob: function readBlob(blob) {
     let deferred = Promise.defer();
@@ -293,17 +261,17 @@ this.PageThumbs = {
 
     let url = aBrowser.currentURI.spec;
     let channel = aBrowser.docShell.currentDocumentChannel;
     let originalURL = channel.originalURI.spec;
 
     // see if this was an error response.
     let wasError = this._isChannelErrorResponse(channel);
 
-    TaskUtils.spawn((function task() {
+    Task.spawn((function task() {
       let isSuccess = true;
       try {
         let blob = yield this.captureToBlob(aBrowser.contentWindow);
         let buffer = yield TaskUtils.readBlob(blob);
         yield this._store(originalURL, url, buffer, wasError);
       } catch (_) {
         isSuccess = false;
       }
@@ -348,17 +316,17 @@ this.PageThumbs = {
    * @param aOriginalURL The URL with which the capture was initiated.
    * @param aFinalURL The URL to which aOriginalURL ultimately resolved.
    * @param aData An ArrayBuffer containing the image data.
    * @param aNoOverwrite If true and files for the URLs already exist, the files
    *                     will not be overwritten.
    * @return {Promise}
    */
   _store: function PageThumbs__store(aOriginalURL, aFinalURL, aData, aNoOverwrite) {
-    return TaskUtils.spawn(function () {
+    return Task.spawn(function () {
       let telemetryStoreTime = new Date();
       yield PageThumbsStorage.writeData(aFinalURL, aData, aNoOverwrite);
       Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
         .add(new Date() - telemetryStoreTime);
 
       Services.obs.notifyObservers(null, "page-thumbnail:create", aFinalURL);
       // We've been redirected. Create a copy of the current thumbnail for
       // the redirect source. We need to do this because: