mirror of
https://github.com/dart-lang/sdk
synced 2024-09-04 16:03:44 +00:00
Don't propagate synchronous Future.wait errors immediately.
Fixes #27249. R=lrn@google.com Review URL: https://codereview.chromium.org/2311923002 .
This commit is contained in:
parent
6255638cd0
commit
70c48b9a2e
|
@ -322,8 +322,13 @@ abstract class Future<T> {
|
|||
// The error must have been thrown while iterating over the futures
|
||||
// list, or while installing a callback handler on the future.
|
||||
if (remaining == 0 || eagerError) {
|
||||
// Just complete the error immediately.
|
||||
result._completeError(e, st);
|
||||
// Throw a new Future.error.
|
||||
// Don't just call `result._completeError` since that would propagate
|
||||
// the error too eagerly, not giving the callers time to install
|
||||
// error handlers.
|
||||
// Also, don't use `_asyncCompleteError` since that one doesn't give
|
||||
// zones the chance to intercept the error.
|
||||
return new Future.error(e, st);
|
||||
} else {
|
||||
// Don't allocate a list for values, thus indicating that there was an
|
||||
// error.
|
||||
|
|
|
@ -879,7 +879,6 @@ void testWaitCleanUpError() {
|
|||
void testWaitSyncError() {
|
||||
var cms = const Duration(milliseconds: 100);
|
||||
var cleanups = new List.filled(3, false);
|
||||
var uncaughts = new List.filled(3, false);
|
||||
asyncStart();
|
||||
asyncStart();
|
||||
runZoned(() {
|
||||
|
@ -896,6 +895,43 @@ void testWaitSyncError() {
|
|||
});
|
||||
}
|
||||
|
||||
void testWaitSyncError2() {
|
||||
asyncStart();
|
||||
Future.wait([null]).catchError((e, st) {
|
||||
// Makes sure that the `catchError` is invoked.
|
||||
// Regression test: an earlier version of `Future.wait` would propagate
|
||||
// the error too soon for the code to install an error handler.
|
||||
// `testWaitSyncError` didn't show this problem, because the `runZoned`
|
||||
// was already installed.
|
||||
asyncEnd();
|
||||
});
|
||||
}
|
||||
|
||||
// Future.wait transforms synchronous errors into asynchronous ones.
|
||||
// This function tests that zones can intercept them.
|
||||
void testWaitSyncError3() {
|
||||
var caughtError;
|
||||
var count = 0;
|
||||
|
||||
AsyncError errorCallback(
|
||||
Zone self, ZoneDelegate parent, Zone zone, Object error,
|
||||
StackTrace stackTrace) {
|
||||
Expect.equals(0, count);
|
||||
count++;
|
||||
caughtError = error;
|
||||
return parent.errorCallback(zone, error, stackTrace);
|
||||
}
|
||||
|
||||
asyncStart();
|
||||
runZoned(() {
|
||||
Future.wait([null]).catchError((e, st) {
|
||||
Expect.identical(e, caughtError);
|
||||
Expect.equals(1, count);
|
||||
asyncEnd();
|
||||
});
|
||||
}, zoneSpecification: new ZoneSpecification(errorCallback: errorCallback));
|
||||
}
|
||||
|
||||
void testBadFuture() {
|
||||
var bad = new BadFuture();
|
||||
// Completing with bad future (then call throws) puts error in result.
|
||||
|
@ -1096,6 +1132,8 @@ main() {
|
|||
testWaitCleanUp();
|
||||
testWaitCleanUpError();
|
||||
testWaitSyncError();
|
||||
testWaitSyncError2();
|
||||
testWaitSyncError3();
|
||||
|
||||
testBadFuture();
|
||||
|
||||
|
|
Loading…
Reference in a new issue