Unverified Commit 2ba0deb7 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Make runAsync() run in child zone, not root zone (#17359)

Some APIs (such as the ones in package:test) assume you're running
in a child zone of the test zone by attempting to extract information
from the zone values. When we run runAsync() in the root zone, those
zone values are lost, and such API methods don't work.

The solution is to run in a child zone, but with a specification that
says to use the Root zone for task scheduling (both timers and
microtakss).
parent cb7afc4a
......@@ -634,7 +634,21 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
);
}());
return Zone.root.run(() {
final Zone realAsyncZone = Zone.current.fork(
specification: new ZoneSpecification(
scheduleMicrotask: (Zone self, ZoneDelegate parent, Zone zone, void f()) {
Zone.root.scheduleMicrotask(f);
},
createTimer: (Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f()) {
return Zone.root.createTimer(duration, f);
},
createPeriodicTimer: (Zone self, ZoneDelegate parent, Zone zone, Duration period, void f(Timer timer)) {
return Zone.root.createPeriodicTimer(period, f);
},
),
);
return realAsyncZone.run(() {
_pendingAsyncTasks = new Completer<void>();
return callback().catchError((dynamic exception, StackTrace stack) {
FlutterError.reportError(new FlutterErrorDetails(
......
......@@ -481,6 +481,18 @@ void main() {
expect(() => tester.runAsync(() async {}), throwsA(const isInstanceOf<TestFailure>()));
completer.complete();
});
testWidgets('maintains existing zone values', (WidgetTester tester) async {
final Object key = new Object();
await runZoned(() {
expect(Zone.current[key], 'abczed');
return tester.runAsync<String>(() async {
expect(Zone.current[key], 'abczed');
});
}, zoneValues: <dynamic, dynamic>{
key: 'abczed',
});
});
});
}
......
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