Commit 97c1f0b7 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Route.didMount should throw a useful error message (#4665)

The error code path wasn't actually getting the point where it would throw the
useful error message. Also, fix error recovery when runApp fails.

Fixes #4655
parent c823acc3
...@@ -349,14 +349,30 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje ...@@ -349,14 +349,30 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje
void mount(Element parent, dynamic newSlot) { void mount(Element parent, dynamic newSlot) {
assert(parent == null); assert(parent == null);
super.mount(parent, newSlot); super.mount(parent, newSlot);
_child = updateChild(_child, widget.child, _rootChildSlot); _rebuild();
} }
@override @override
void update(RenderObjectToWidgetAdapter<T> newWidget) { void update(RenderObjectToWidgetAdapter<T> newWidget) {
super.update(newWidget); super.update(newWidget);
assert(widget == newWidget); assert(widget == newWidget);
_child = updateChild(_child, widget.child, _rootChildSlot); _rebuild();
}
void _rebuild() {
try {
_child = updateChild(_child, widget.child, _rootChildSlot);
assert(_child != null);
} catch (exception, stack) {
FlutterError.reportError(new FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'widgets library',
context: 'attaching to the render tree'
));
Widget error = new ErrorWidget(exception);
_child = updateChild(null, error, _rootChildSlot);
}
} }
@override @override
......
...@@ -525,14 +525,17 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -525,14 +525,17 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
@override @override
void didPush() { void didPush() {
if (!settings.isInitialRoute) { if (!settings.isInitialRoute) {
BuildContext overlayContext = navigator.overlay.context; BuildContext overlayContext = navigator.overlay?.context;
if (overlayContext == null) { assert(() {
throw new FlutterError( if (overlayContext == null) {
'Unable to find the BuildContext for the Navigator\'s overlay.\n' throw new FlutterError(
'Did you remember to pass the settings object to the route\'s ' 'Unable to find the BuildContext for the Navigator\'s overlay.\n'
'constructor in your onGenerateRoute callback?' 'Did you remember to pass the settings object to the route\'s '
); 'constructor in your onGenerateRoute callback?'
} );
}
return true;
});
Focus.moveScopeTo(focusKey, context: overlayContext); Focus.moveScopeTo(focusKey, context: overlayContext);
} }
super.didPush(); super.didPush();
......
...@@ -112,4 +112,16 @@ void main() { ...@@ -112,4 +112,16 @@ void main() {
expect(exception, new isInstanceOf<FlutterError>()); expect(exception, new isInstanceOf<FlutterError>());
expect('$exception', startsWith('openTransaction called with a context')); expect('$exception', startsWith('openTransaction called with a context'));
}); });
testWidgets('Missing settings in onGenerateRoute throws exception', (WidgetTester tester) async {
await tester.pumpWidget(new Navigator(
onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute<Null>(
builder: (BuildContext context) => new Container()
);
}
));
Object exception = tester.takeException();
expect(exception is FlutterError, isTrue);
});
} }
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