Migrate to runZonedGuarded (#93)
The `onError` argument to `runZoned` is deprecated. Switch to the
supported `runZonedGuarded`.
Remove argument types on the function literal since thy can now be
inferred. `runZonedGuarded` has a specific function type argument,
whereas `onError` was typed as `Function` which did not allow inference
on argument types.
Refactor handling of `!when` since the new API doesn't allow a nullable
callback.
Refactor some tests to use `having` matchers which previously relied on
calling methods on `dynamic`.
diff --git a/lib/src/chain.dart b/lib/src/chain.dart
index fef2c2d..b685be9 100644
--- a/lib/src/chain.dart
+++ b/lib/src/chain.dart
@@ -66,10 +66,10 @@
/// parent Zone's `unhandledErrorHandler` will be called with the error and
/// its chain.
///
- /// If [errorZone] is `true`, the zone this creates will be an error zone,
- /// even if [onError] isn't passed. This means that any errors that would
- /// cross the zone boundary are considered unhandled. If [errorZone] is
- /// `false`, [onError] must be `null`.
+ /// The zone this creates will be an error zone if either [onError] is
+ /// not `null` and [when] is false,
+ /// or if both [when] and [errorZone] are `true`.
+ /// If [errorZone] is `false`, [onError] must be `null`.
///
/// If [callback] returns a value, it will be returned by [capture] as well.
static T capture<T>(T Function() callback,
@@ -82,20 +82,10 @@
}
if (!when) {
- void Function(Object, StackTrace)? newOnError;
- if (onError != null) {
- void wrappedOnError(Object error, StackTrace? stackTrace) {
- onError(
- error,
- stackTrace == null
- ? Chain.current()
- : Chain.forTrace(stackTrace));
- }
-
- newOnError = wrappedOnError;
- }
-
- return runZoned(callback, onError: newOnError);
+ if (onError == null) return runZoned(callback);
+ return runZonedGuarded(callback, (error, stackTrace) {
+ onError(error, Chain.forTrace(stackTrace));
+ }) as T;
}
var spec = StackZoneSpecification(onError, errorZone: errorZone);
diff --git a/test/chain/chain_test.dart b/test/chain/chain_test.dart
index 3309ae1..bb28b79 100644
--- a/test/chain/chain_test.dart
+++ b/test/chain/chain_test.dart
@@ -64,10 +64,10 @@
});
test('with no onError blocks errors', () {
- runZoned(() {
+ runZonedGuarded(() {
var future = Chain.capture(() => Future.error('oh no'), when: false);
future.then(expectAsync1((_) {}, count: 0));
- }, onError: expectAsync2((error, chain) {
+ }, expectAsync2((error, chain) {
expect(error, equals('oh no'));
expect(chain, isA<Chain>());
}));
diff --git a/test/chain/dart2js_test.dart b/test/chain/dart2js_test.dart
index c0ec913..f708637 100644
--- a/test/chain/dart2js_test.dart
+++ b/test/chain/dart2js_test.dart
@@ -140,7 +140,7 @@
test('and relays them to the parent zone', () {
var completer = Completer();
- runZoned(() {
+ runZonedGuarded(() {
Chain.capture(() {
inMicrotask(() => throw 'error');
}, onError: (error, chain) {
@@ -148,11 +148,11 @@
expect(chain.traces, hasLength(2));
throw error;
});
- }, onError: (error, chain) {
+ }, (error, chain) {
try {
expect(error, equals('error'));
- expect(chain, isA<Chain>());
- expect(chain.traces, hasLength(2));
+ expect(chain,
+ isA<Chain>().having((c) => c.traces, 'traces', hasLength(2)));
completer.complete();
} on Object catch (error, stackTrace) {
completer.completeError(error, stackTrace);
@@ -166,13 +166,13 @@
test('capture() without onError passes exceptions to parent zone', () {
var completer = Completer();
- runZoned(() {
+ runZonedGuarded(() {
Chain.capture(() => inMicrotask(() => throw 'error'));
- }, onError: (error, chain) {
+ }, (error, chain) {
try {
expect(error, equals('error'));
- expect(chain, isA<Chain>());
- expect(chain.traces, hasLength(2));
+ expect(chain,
+ isA<Chain>().having((c) => c.traces, 'traces', hasLength(2)));
completer.complete();
} on Object catch (error, stackTrace) {
completer.completeError(error, stackTrace);
diff --git a/test/chain/vm_test.dart b/test/chain/vm_test.dart
index 273276e..8a66b83 100644
--- a/test/chain/vm_test.dart
+++ b/test/chain/vm_test.dart
@@ -234,7 +234,7 @@
test('and relays them to the parent zone', () {
var completer = Completer();
- runZoned(() {
+ runZonedGuarded(() {
Chain.capture(() {
inMicrotask(() => throw 'error');
}, onError: (error, chain) {
@@ -243,12 +243,13 @@
contains(frameMember(startsWith('inMicrotask'))));
throw error;
});
- }, onError: (error, chain) {
+ }, (error, chain) {
try {
expect(error, equals('error'));
- expect(chain, isA<Chain>());
- expect(chain.traces[1].frames,
- contains(frameMember(startsWith('inMicrotask'))));
+ expect(
+ chain,
+ isA<Chain>().having((c) => c.traces[1].frames, 'traces[1].frames',
+ contains(frameMember(startsWith('inMicrotask')))));
completer.complete();
} on Object catch (error, stackTrace) {
completer.completeError(error, stackTrace);
@@ -262,14 +263,15 @@
test('capture() without onError passes exceptions to parent zone', () {
var completer = Completer();
- runZoned(() {
+ runZonedGuarded(() {
Chain.capture(() => inMicrotask(() => throw 'error'));
- }, onError: (error, chain) {
+ }, (error, chain) {
try {
expect(error, equals('error'));
- expect(chain, isA<Chain>());
- expect(chain.traces[1].frames,
- contains(frameMember(startsWith('inMicrotask'))));
+ expect(
+ chain,
+ isA<Chain>().having((c) => c.traces[1].frames, 'traces[1].frames',
+ contains(frameMember(startsWith('inMicrotask')))));
completer.complete();
} on Object catch (error, stackTrace) {
completer.completeError(error, stackTrace);