Unverified Commit 2f04ba91 authored by chunhtai's avatar chunhtai Committed by GitHub

Fixes the navigator pages update crashes when there is still route wa… (#55998)

parent c2b7342c
...@@ -2367,6 +2367,66 @@ void main() { ...@@ -2367,6 +2367,66 @@ void main() {
expect(find.text('forth'), findsOneWidget); expect(find.text('forth'), findsOneWidget);
}); });
testWidgets('can repush a page that was previously popped before it has finished popping', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
List<Page<dynamic>> myPages = <TestPage>[
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
const TestPage(key: ValueKey<String>('2'), name: 'second'),
];
bool onPopPage(Route<dynamic> route, dynamic result) {
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
return route.didPop(result);
}
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
// Pops the second page route.
myPages = <TestPage>[
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
];
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
// Re-push the second page again before it finishes popping.
myPages = <TestPage>[
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
const TestPage(key: ValueKey<String>('2'), name: 'second'),
];
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
// It should not crash the app.
expect(tester.takeException(), isNull);
await tester.pumpAndSettle();
expect(find.text('second'), findsOneWidget);
});
testWidgets('can update pages before a route has finished popping', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
List<Page<dynamic>> myPages = <TestPage>[
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
const TestPage(key: ValueKey<String>('2'), name: 'second'),
];
bool onPopPage(Route<dynamic> route, dynamic result) {
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
return route.didPop(result);
}
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
// Pops the second page route.
myPages = <TestPage>[
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
];
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
// Updates the pages again before second page finishes popping.
myPages = <TestPage>[
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
];
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
// It should not crash the app.
expect(tester.takeException(), isNull);
await tester.pumpAndSettle();
expect(find.text('initial'), findsOneWidget);
});
}); });
} }
...@@ -2415,23 +2475,24 @@ class AlwaysRemoveTransitionDelegate extends TransitionDelegate<void> { ...@@ -2415,23 +2475,24 @@ class AlwaysRemoveTransitionDelegate extends TransitionDelegate<void> {
return; return;
final RouteTransitionRecord exitingPageRoute = locationToExitingPageRoute[location]; final RouteTransitionRecord exitingPageRoute = locationToExitingPageRoute[location];
if (exitingPageRoute.isWaitingForExitingDecision) {
final bool hasPagelessRoute = pageRouteToPagelessRoutes.containsKey(exitingPageRoute); final bool hasPagelessRoute = pageRouteToPagelessRoutes.containsKey(exitingPageRoute);
exitingPageRoute.markForRemove(); exitingPageRoute.markForRemove();
results.add(exitingPageRoute);
if (hasPagelessRoute) { if (hasPagelessRoute) {
final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute]; final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) { for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
pagelessRoute.markForRemove(); pagelessRoute.markForRemove();
} }
} }
}
results.add(exitingPageRoute);
handleExitingRoute(exitingPageRoute); handleExitingRoute(exitingPageRoute);
} }
handleExitingRoute(null); handleExitingRoute(null);
for (final RouteTransitionRecord pageRoute in newPageRouteHistory) { for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
if (pageRoute.isEntering) { if (pageRoute.isWaitingForEnteringDecision) {
pageRoute.markForAdd(); pageRoute.markForAdd();
} }
results.add(pageRoute); results.add(pageRoute);
......
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