Commit 7cf362fc authored by Nate Bosch's avatar Nate Bosch Committed by Jonah Williams

Handle onError callback with optional argument (#43436)

Check for a binary callback first since a function with an optional
second argument will match both typedefs.

Remove documentation around a synchronous error following some other
error or value - a synchronous error can never follow a value or an
asynchronous error. If there is a synchronous error it will _always_ be
the first thing to happen.

Add a test for a unary error handler and an error handler with an
optional stack trace argument.
parent 0dc5ea4a
...@@ -26,8 +26,7 @@ import 'dart:async'; ...@@ -26,8 +26,7 @@ import 'dart:async';
/// completed with its result when passed the error object and stack trace. /// completed with its result when passed the error object and stack trace.
/// ///
/// After the returned [Future] is completed, whether it be with a value or an /// After the returned [Future] is completed, whether it be with a value or an
/// error, all further errors resulting from the execution of [fn] both /// error, all further errors resulting from the execution of [fn] are ignored.
/// synchronous and asynchronous are ignored.
/// ///
/// Rationale: /// Rationale:
/// ///
...@@ -100,10 +99,10 @@ Future<T> asyncGuard<T>( ...@@ -100,10 +99,10 @@ Future<T> asyncGuard<T>(
completer.completeError(e, s); completer.completeError(e, s);
return; return;
} }
if (onError is _UnaryOnError) { if (onError is _BinaryOnError) {
completer.complete(onError(e));
} else if (onError is _BinaryOnError) {
completer.complete(onError(e, s)); completer.complete(onError(e, s));
} else if (onError is _UnaryOnError) {
completer.complete(onError(e));
} }
} }
......
...@@ -181,7 +181,7 @@ void main() { ...@@ -181,7 +181,7 @@ void main() {
expect(caughtByCatchError, true); expect(caughtByCatchError, true);
}); });
test('asyncError is propagated correctly with onError callback', () async { test('asyncError is propagated with binary onError', () async {
bool caughtByZone = false; bool caughtByZone = false;
bool caughtByHandler = false; bool caughtByHandler = false;
bool caughtByOnError = false; bool caughtByOnError = false;
...@@ -218,4 +218,83 @@ void main() { ...@@ -218,4 +218,83 @@ void main() {
expect(caughtByHandler, false); expect(caughtByHandler, false);
expect(caughtByOnError, true); expect(caughtByOnError, true);
}); });
test('asyncError is propagated with unary onError', () async {
bool caughtByZone = false;
bool caughtByHandler = false;
bool caughtByOnError = false;
final Completer<void> completer = Completer<void>();
await FakeAsync().run((FakeAsync time) {
unawaited(runZoned(() async {
final Future<void> f = asyncGuard<void>(
() => delayedThrow(time),
onError: (Object e) {
caughtByOnError = true;
},
);
try {
await f;
} catch (e) {
caughtByHandler = true;
}
if (!completer.isCompleted) {
completer.complete(null);
}
}, onError: (Object e, StackTrace s) {
caughtByZone = true;
if (!completer.isCompleted) {
completer.complete(null);
}
}));
time.elapse(const Duration(seconds: 1));
time.flushMicrotasks();
return completer.future;
});
expect(caughtByZone, false);
expect(caughtByHandler, false);
expect(caughtByOnError, true);
});
test('asyncError is propagated with optional stack trace', () async {
bool caughtByZone = false;
bool caughtByHandler = false;
bool caughtByOnError = false;
bool nonNullStackTrace = false;
final Completer<void> completer = Completer<void>();
await FakeAsync().run((FakeAsync time) {
unawaited(runZoned(() async {
final Future<void> f = asyncGuard<void>(
() => delayedThrow(time),
onError: (Object e, [StackTrace s]) {
caughtByOnError = true;
nonNullStackTrace = s != null;
},
);
try {
await f;
} catch (e) {
caughtByHandler = true;
}
if (!completer.isCompleted) {
completer.complete(null);
}
}, onError: (Object e, StackTrace s) {
caughtByZone = true;
if (!completer.isCompleted) {
completer.complete(null);
}
}));
time.elapse(const Duration(seconds: 1));
time.flushMicrotasks();
return completer.future;
});
expect(caughtByZone, false);
expect(caughtByHandler, false);
expect(caughtByOnError, true);
expect(nonNullStackTrace, true);
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment