-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[go_router]: fix leaking GoRouter.replace and GoRouter.pushReplacement completer, preserve it #6451
[go_router]: fix leaking GoRouter.replace and GoRouter.pushReplacement completer, preserve it #6451
Conversation
…t completer, preserve it (#141251) When route from the stack is replaced, its completer is lost, and causes futures in routes chain to never finish.
@hangyujin @johnpryan Could you please take a look? Added reviewer is not longer active. |
await tester.pumpAndSettle(); | ||
|
||
expect(goRouter.routerDelegate.currentConfiguration.matches.length, 2); | ||
expect(await sourceFeature, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not look right. the once page-1
is replaced, its future should never be completed. The pop
result on line 373 is only meant for page-2
. It should not be used to complete page-1
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not look right. the once
page-1
is replaced, its future should never be completed. Thepop
result on line 373 is only meant forpage-2
. It should not be used to completepage-1
.
On the other hand, is it good approach to throw any Future into the void (in any case, not only in this particular case)?
This implies that users of go router must carefully design their flow, because feature never ends. And it differs from how the navigator works itself - it completes the future on replacement, which is actually pretty logically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, is it good approach to throw any Future into the void (in any case, not only in this particular case)?
No, but sometimes it is unavoidable.
it differs from how the navigator works itself - it completes the future on replacement
Ah you are right, I missed that the navigator completes the previous route for pushReplacement, although the way it completes previous route is different from this pr. We can add a result parameter to pushReplacement to complete previous route. The current implementation uses the same result for both routes seem wrong to me.
The NavigatorState.replace however removes the route without completing it. I think we should keep it that way in go_router
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current behavior is working as intended. If a page is removed, its future should never complete
imagine this
this is intended? |
assuming we add a result to pushReplacement void onPress() async {
var result = await context.push("/login");
var data = await result;
}
void handleLogin() async {
var completer = Completer()
var someData = await context.pushReplacement("/setup_profile", result: completer.future);
completer.complete(someData);
} |
If you add more replace routes down the road, you will need to chain such completers down the flow, otherwise original future from What if we will reflect navigator behaviour including keeping the futures chain on multiple push replacements? If so, I would remove storing the futures for replace method, but keep it as I did in the PR for |
The current implementation may be slightly confused as calling one pop will resolve multiple future with the same result. In your use case, that may be ok. Others may want to have a way to complete these future with different values. These API suppose to mirror Navigator's. |
if we can't pass result value to original 'push' operation, at least, let original 'await push' get a whatever result value or exception. |
I will try to update the PR with the changes @chunhtai suggested - replacing the route will complete the future instead throwing it into the void. Hopefully this week. |
Hi @pawlowskim I am going to close this pr, feel free to reopen if you have time to work on it. |
When route from the stack is replaced, its completer is lost, and causes futures in routes chain to never finish. This change stores completers from the routes that are replaced and calls their complete method when route that replaces them is popped.
It fixes: flutter/flutter#141251
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).