Backed out changeset 3bfcf691690a (bug 966182) for adding a hazard.

This commit is contained in:
Wes Kocher 2014-03-05 20:31:38 -08:00
parent 8e3b6aa7ec
commit 642e83c0e5
4 changed files with 16 additions and 241 deletions

View File

@ -442,14 +442,6 @@ Promise.defer = function ()
*/
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));
};

View File

@ -136,53 +136,24 @@ this.Task = {
* 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);
},
/**
@ -197,42 +168,6 @@ this.Task = {
}
};
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

View File

@ -4,7 +4,6 @@
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
@ -528,14 +527,6 @@ tests.push(
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) {

View File

@ -118,36 +118,6 @@ add_test(function test_spawn_function()
});
});
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 () {
@ -272,116 +242,3 @@ add_test(function test_mixed_legacy_and_star()
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);
});
});