Backed out changeset 3bfcf691690a (bug 966182) for adding a hazard.
authorWes Kocher <wkocher@mozilla.com>
Wed, 05 Mar 2014 20:31:38 -0800
changeset 189363 19fe1e621c5ca48d360eb05cb984668f5f81fb41
parent 189362 8adacb553312a43d7e9cda515f595ba86ca6e348
child 189364 b8551123b3dae18333535e76e279555c5383cdf6
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs966182
milestone30.0a1
backs out3bfcf691690ac260038d58f079ace08973f58605
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 3bfcf691690a (bug 966182) for adding a hazard.
toolkit/modules/Promise.jsm
toolkit/modules/Task.jsm
toolkit/modules/tests/xpcshell/test_Promise.js
toolkit/modules/tests/xpcshell/test_task.js
--- a/toolkit/modules/Promise.jsm
+++ b/toolkit/modules/Promise.jsm
@@ -437,24 +437,16 @@ Promise.defer = function ()
  *        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.
  */
 Promise.resolve = function (aValue)
 {
-  if (aValue && typeof(aValue) == "function" && aValue.isAsyncFunction) {
-    throw new TypeError(
-      "Cannot resolve a promise with an async function. " +
-      "You should either invoke the async function first " +
-      "or use 'Task.spawn' instead of 'Task.async' to start " +
-      "the Task and return its promise.");
-  }
-
   return new Promise((aResolve) => aResolve(aValue));
 };
 
 /**
  * Creates a new promise rejected with the specified reason.
  *
  * @param aReason
  *        The rejection reason for the returned promise.  Although the reason
--- a/toolkit/modules/Task.jsm
+++ b/toolkit/modules/Task.jsm
@@ -131,113 +131,48 @@ this.Task = {
    *          returned promise.
    *        - If you specify anything else, you get a promise that is already
    *          resolved with the specified value.
    *
    * @return A promise object where you can register completion callbacks to be
    *         called when the task terminates.
    */
   spawn: function Task_spawn(aTask) {
-    return createAsyncFunction(aTask).call(undefined);
-  },
-
-  /**
-   * Create and return an 'async function' that starts a new task.
-   *
-   * This is similar to 'spawn' except that it doesn't immediately start
-   * the task, it binds the task to the async function's 'this' object and
-   * arguments, and it requires the task to be a function.
-   *
-   * It simplifies the common pattern of implementing a method via a task,
-   * like this simple object with a 'greet' method that has a 'name' parameter
-   * and spawns a task to send a greeting and return its reply:
-   *
-   * let greeter = {
-   *   message: "Hello, NAME!",
-   *   greet: function(name) {
-   *     return Task.spawn((function* () {
-   *       return yield sendGreeting(this.message.replace(/NAME/, name));
-   *     }).bind(this);
-   *   })
-   * };
-   *
-   * With Task.async, the method can be declared succinctly:
-   *
-   * let greeter = {
-   *   message: "Hello, NAME!",
-   *   greet: Task.async(function* (name) {
-   *     return yield sendGreeting(this.message.replace(/NAME/, name));
-   *   })
-   * };
-   *
-   * While maintaining identical semantics:
-   *
-   * greeter.greet("Mitchell").then((reply) => { ... }); // behaves the same
-   *
-   * @param aTask
-   *        The task function to start.
-   *
-   * @return A function that starts the task function and returns its promise.
-   */
-  async: function Task_async(aTask) {
-    if (typeof(aTask) != "function") {
-      throw new TypeError("aTask argument must be a function");
+    if (aTask && typeof(aTask) == "function") {
+      try {
+        // Let's call into the function ourselves.
+        aTask = aTask();
+      } catch (ex if ex instanceof Task.Result) {
+        return Promise.resolve(ex.value);
+      } catch (ex) {
+        return Promise.reject(ex);
+      }
     }
 
-    return createAsyncFunction(aTask);
+    if (isGenerator(aTask)) {
+      // This is an iterator resulting from calling a generator function.
+      return new TaskImpl(aTask).deferred.promise;
+    }
+
+    // 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
    * function (non-star generator), allows the associated task to be resolved
    * with a specific value.
    *
    * Example: throw new Task.Result("Value");
    */
   Result: function Task_Result(aValue) {
     this.value = aValue;
   }
 };
 
-function createAsyncFunction(aTask) {
-  let asyncFunction = function () {
-    let result = aTask;
-    if (aTask && typeof(aTask) == "function") {
-      if (aTask.isAsyncFunction) {
-        throw new TypeError(
-          "Cannot use an async function in place of a promise. " +
-          "You should either invoke the async function first " +
-          "or use 'Task.spawn' instead of 'Task.async' to start " +
-          "the Task and return its promise.");
-      }
-
-      try {
-        // Let's call into the function ourselves.
-        result = aTask.apply(this, arguments);
-      } catch (ex if ex instanceof Task.Result) {
-        return Promise.resolve(ex.value);
-      } catch (ex) {
-        return Promise.reject(ex);
-      }
-    }
-
-    if (isGenerator(result)) {
-      // This is an iterator resulting from calling a generator function.
-      return new TaskImpl(result).deferred.promise;
-    }
-
-    // Just propagate the given value to the caller as a resolved promise.
-    return Promise.resolve(result);
-  };
-
-  asyncFunction.isAsyncFunction = true;
-
-  return asyncFunction;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 //// TaskImpl
 
 /**
  * Executes the specified iterator as a task, and gives access to the promise
  * that is fulfilled when the task terminates.
  */
 function TaskImpl(iterator) {
--- a/toolkit/modules/tests/xpcshell/test_Promise.js
+++ b/toolkit/modules/tests/xpcshell/test_Promise.js
@@ -1,15 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 Components.utils.import("resource://gre/modules/Promise.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/Task.jsm");
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Test runner
 
 let run_promise_tests = function run_promise_tests(tests, cb) {
   let loop = function loop(index) {
     if (index >= tests.length) {
       if (cb) {
@@ -523,24 +522,16 @@ tests.push(
     let promise = Promise.resolve(RESULT).then(
       function onResolve(result) {
         do_check_eq(result, RESULT, "Promise.resolve propagated the correct result");
       }
     );
     return promise;
   }));
 
-// Test that Promise.resolve throws when its argument is an async function.
-tests.push(
-  make_promise_test(function test_promise_resolve_throws_with_async_function(test) {
-    Assert.throws(() => Promise.resolve(Task.async(function* () {})),
-                  /Cannot resolve a promise with an async function/);
-    return Promise.resolve();
-  }));
-
 // Test that the code after "then" is always executed before the callbacks
 tests.push(
   make_promise_test(function then_returns_before_callbacks(test) {
     let promise = Promise.resolve();
 
     let thenExecuted = false;
 
     promise = promise.then(
--- a/toolkit/modules/tests/xpcshell/test_task.js
+++ b/toolkit/modules/tests/xpcshell/test_task.js
@@ -113,46 +113,16 @@ add_test(function test_spawn_function()
   }).then(function (result) {
     do_check_eq("This is not a generator.", result);
     run_next_test();
   }, function (ex) {
     do_throw("Unexpected error: " + ex);
   });
 });
 
-add_test(function test_spawn_function_this()
-{
-  Task.spawn(function () {
-    return this;
-  }).then(function (result) {
-    // Since the task function wasn't defined in strict mode, its "this" object
-    // should be the same as the "this" object in this function, i.e. the global
-    // object.
-    do_check_eq(result, this);
-    run_next_test();
-  }, function (ex) {
-    do_throw("Unexpected error: " + ex);
-  });
-});
-
-add_test(function test_spawn_function_this_strict()
-{
-  "use strict";
-  Task.spawn(function () {
-    return this;
-  }).then(function (result) {
-    // Since the task function was defined in strict mode, its "this" object
-    // should be undefined.
-    do_check_eq(typeof(result), "undefined");
-    run_next_test();
-  }, function (ex) {
-    do_throw("Unexpected error: " + ex);
-  });
-});
-
 add_test(function test_spawn_function_returning_promise()
 {
   Task.spawn(function () {
     return promiseResolvedLater("Resolution value.");
   }).then(function (result) {
     do_check_eq("Resolution value.", result);
     run_next_test();
   }, function (ex) {
@@ -267,121 +237,8 @@ add_test(function test_mixed_legacy_and_
     })();
   }).then(function (result) {
     do_check_eq(5, result);
     run_next_test();
   }, function (ex) {
     do_throw("Unexpected error: " + ex);
   });
 });
-
-add_test(function test_async_function_from_generator()
-{
-  Task.spawn(function* () {
-    let object = {
-      asyncFunction: Task.async(function* (param) {
-        do_check_eq(this, object);
-        return param;
-      })
-    };
-
-    // Ensure the async function returns a promise that resolves as expected.
-    do_check_eq((yield object.asyncFunction(1)), 1);
-
-    // Ensure a second call to the async function also returns such a promise.
-    do_check_eq((yield object.asyncFunction(3)), 3);
-  }).then(function () {
-    run_next_test();
-  }, function (ex) {
-    do_throw("Unexpected error: " + ex);
-  });
-});
-
-add_test(function test_async_function_from_function()
-{
-  Task.spawn(function* () {
-    return Task.spawn(function* () {
-      let object = {
-        asyncFunction: Task.async(function (param) {
-          do_check_eq(this, object);
-          return param;
-        })
-      };
-
-      // Ensure the async function returns a promise that resolves as expected.
-      do_check_eq((yield object.asyncFunction(5)), 5);
-
-      // Ensure a second call to the async function also returns such a promise.
-      do_check_eq((yield object.asyncFunction(7)), 7);
-    });
-  }).then(function () {
-    run_next_test();
-  }, function (ex) {
-    do_throw("Unexpected error: " + ex);
-  });
-});
-
-add_test(function test_async_function_that_throws_rejects_promise()
-{
-  Task.spawn(function* () {
-    let object = {
-      asyncFunction: Task.async(function* () {
-        throw "Rejected!";
-      })
-    };
-
-    yield object.asyncFunction();
-  }).then(function () {
-    do_throw("unexpected success calling async function that throws error");
-  }, function (ex) {
-    do_check_eq(ex, "Rejected!");
-    run_next_test();
-  });
-});
-
-add_test(function test_async_return_function()
-{
-  Task.spawn(function* () {
-    // Ensure an async function that returns a function resolves to the function
-    // itself instead of calling the function and resolving to its return value.
-    return Task.spawn(function* () {
-      let returnValue = function () {
-        return "These aren't the droids you're looking for.";
-      };
-
-      let asyncFunction = Task.async(function () {
-        return returnValue;
-      });
-
-      do_check_eq((yield asyncFunction()), returnValue);
-    });
-  }).then(function () {
-    run_next_test();
-  }, function (ex) {
-    do_throw("Unexpected error: " + ex);
-  });
-});
-
-add_test(function test_async_throw_argument_not_function()
-{
-  Task.spawn(function* () {
-    // Ensure Task.async throws if its aTask argument is not a function.
-    Assert.throws(() => Task.async("not a function"),
-                  /aTask argument must be a function/);
-  }).then(function () {
-    run_next_test();
-  }, function (ex) {
-    do_throw("Unexpected error: " + ex);
-  });
-});
-
-add_test(function test_async_throw_on_function_in_place_of_promise()
-{
-  Task.spawn(function* () {
-    // Ensure Task.spawn throws if passed an async function.
-    Assert.throws(() => Task.spawn(Task.async(function* () {})),
-                  /Cannot use an async function in place of a promise/);
-  }).then(function () {
-    run_next_test();
-  }, function (ex) {
-    do_throw("Unexpected error: " + ex);
-  });
-});