async.auto Error and Exception handling

I found that dealing with errors that happen during task execution was not easy.  My initial approach was to pass the results to the final callback when an error occurred (https://github.com/caolan/async/pull/92).

But, that meant that I had to write a bunch of conditional logic in my callback to figure out which tasks completed.  Furthermore, because the callback was called immediately, some tasks may still complete after the last callback is called.

I've tried to address these issues for async.auto in this pull request by introducing a small task class that allows tasks to be composed using fluent syntax.  If an error occurs, the auto method now waits for all running tasks to complete before calling the callback (no new tasks will be started once an error occurs).

Additionally, I added an option to surround the task execution with a try/catch block, in case a synchronous error is encountered.  This provides an opportunity for error handlers to be run in the context of the operation that caused the error.

I did break one piece of backward compatibility - since more than one error may be caused by tasks that run in parallel, the first argument passed to the final callback is now an object with keys corresponding to any tasks that caused errors.

Otherwise, all existing tests pass, and new tests have been added to demonstrate the new functionality.