From 1a1aa33d878eadce7f39ace8b36ee58c2489a2a6 Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Wed, 6 Jan 2021 11:25:02 -0800 Subject: [PATCH 1/4] update browser history switching --- lib/web_ui/lib/src/engine/window.dart | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/web_ui/lib/src/engine/window.dart b/lib/web_ui/lib/src/engine/window.dart index 0557acd9c129d..d57095c0c4b77 100644 --- a/lib/web_ui/lib/src/engine/window.dart +++ b/lib/web_ui/lib/src/engine/window.dart @@ -51,7 +51,7 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow { } BrowserHistory? _browserHistory; - + bool _usingRouter = false; Future _useSingleEntryBrowserHistory() async { if (_browserHistory is SingleEntryBrowserHistory) { return; @@ -61,6 +61,15 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow { _browserHistory = SingleEntryBrowserHistory(urlStrategy: strategy); } + Future _useMultiEntryBrowserHistory() async { + if (_browserHistory is MultiEntriesBrowserHistory) { + return; + } + final UrlStrategy? strategy = _browserHistory?.urlStrategy; + await _browserHistory?.tearDown(); + _browserHistory = MultiEntriesBrowserHistory(urlStrategy: strategy); + } + @visibleForTesting Future debugInitializeHistory( UrlStrategy? strategy, { @@ -95,11 +104,13 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow { switch (decoded.method) { case 'routeUpdated': + assert(!_usingRouter); await _useSingleEntryBrowserHistory(); browserHistory.setRouteName(arguments['routeName']); return true; case 'routeInformationUpdated': - assert(browserHistory is MultiEntriesBrowserHistory); + await _useMultiEntryBrowserHistory(); + _usingRouter = true; browserHistory.setRouteName( arguments['location'], state: arguments['state'], From 233db8f7134bf343db7c32bbe172a618e79fa338 Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Wed, 6 Jan 2021 14:16:12 -0800 Subject: [PATCH 2/4] update --- lib/web_ui/lib/src/engine/window.dart | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/web_ui/lib/src/engine/window.dart b/lib/web_ui/lib/src/engine/window.dart index d57095c0c4b77..f989425f8274a 100644 --- a/lib/web_ui/lib/src/engine/window.dart +++ b/lib/web_ui/lib/src/engine/window.dart @@ -104,9 +104,17 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow { switch (decoded.method) { case 'routeUpdated': - assert(!_usingRouter); - await _useSingleEntryBrowserHistory(); - browserHistory.setRouteName(arguments['routeName']); + if (!_usingRouter) { + await _useSingleEntryBrowserHistory(); + browserHistory.setRouteName(arguments['routeName']); + } else { + assert( + false, + 'Receives old navigator update in a router application. ' + 'This can happen if you use non-router versions of MaterialApp/' + 'CupertinoApp/WidgetsApp together with the router versions of them.' + ); + } return true; case 'routeInformationUpdated': await _useMultiEntryBrowserHistory(); From 9fd913f5a0f96642ebb8cbd34fd0da24ad539bd6 Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Wed, 6 Jan 2021 15:31:28 -0800 Subject: [PATCH 3/4] update --- lib/web_ui/lib/src/engine/window.dart | 3 +- lib/web_ui/test/window_test.dart | 59 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/window.dart b/lib/web_ui/lib/src/engine/window.dart index f989425f8274a..8c7e7c53630ae 100644 --- a/lib/web_ui/lib/src/engine/window.dart +++ b/lib/web_ui/lib/src/engine/window.dart @@ -77,7 +77,7 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow { }) async { // Prevent any further customization of URL strategy. _isUrlStrategySet = true; - + _usingRouter = false; await _browserHistory?.tearDown(); if (useSingle) { _browserHistory = SingleEntryBrowserHistory(urlStrategy: strategy); @@ -114,6 +114,7 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow { 'This can happen if you use non-router versions of MaterialApp/' 'CupertinoApp/WidgetsApp together with the router versions of them.' ); + return false; } return true; case 'routeInformationUpdated': diff --git a/lib/web_ui/test/window_test.dart b/lib/web_ui/test/window_test.dart index 0a02485ef0b8f..19b2db7ca2263 100644 --- a/lib/web_ui/test/window_test.dart +++ b/lib/web_ui/test/window_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. // @dart = 2.6 +import 'dart:async'; import 'dart:html' as html; import 'dart:js_util' as js_util; import 'dart:typed_data'; @@ -69,6 +70,64 @@ void testMain() { expect(window.defaultRouteName, '/'); }); + test('should throw when using nav1 and nav2 together', + () async { + await window.debugInitializeHistory(TestUrlStrategy.fromEntry( + TestHistoryEntry('initial state', null, '/initial'), + ), useSingle: false); + // Receive nav1 update first. + Completer callback = Completer(); + window.sendPlatformMessage( + 'flutter/navigation', + JSONMethodCodec().encodeMethodCall(MethodCall( + 'routeUpdated', + {'routeName': '/bar'}, + )), + (_) { callback.complete(); }, + ); + await callback.future; + expect(window.browserHistory is SingleEntryBrowserHistory, true); + expect(window.browserHistory.urlStrategy.getPath(), '/bar'); + + // We can still receive nav2 update. + callback = Completer(); + window.sendPlatformMessage( + 'flutter/navigation', + JSONMethodCodec().encodeMethodCall(MethodCall( + 'routeInformationUpdated', + { + 'location': '/baz', + 'state': null, + }, + )), + (_) { callback.complete(); }, + ); + await callback.future; + expect(window.browserHistory is MultiEntriesBrowserHistory, true); + expect(window.browserHistory.urlStrategy.getPath(), '/baz'); + + // Throws assertion error if it receives nav1 update after nav2 update. + AssertionError caughtAssertion; + await window.handleNavigationMessage( + JSONMethodCodec().encodeMethodCall(MethodCall( + 'routeUpdated', + {'routeName': '/foo'}, + )) + ).catchError((Object e) { + caughtAssertion = e as AssertionError; + }); + + expect( + caughtAssertion.message, + 'Receives old navigator update in a router application. This can ' + 'happen if you use non-router versions of ' + 'MaterialApp/CupertinoApp/WidgetsApp together with the router versions of them.' + ); + // The history does not change. + expect(window.browserHistory is MultiEntriesBrowserHistory, true); + expect(window.browserHistory.urlStrategy.getPath(), '/baz'); + }); + test('can disable location strategy', () async { // Disable URL strategy. expect(() => jsSetUrlStrategy(null), returnsNormally); From 4dc5d63a435a565f0e6e4b79cd28a1886a65bd97 Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Wed, 6 Jan 2021 16:17:29 -0800 Subject: [PATCH 4/4] whitespace --- lib/web_ui/test/window_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web_ui/test/window_test.dart b/lib/web_ui/test/window_test.dart index 19b2db7ca2263..676bc1a315023 100644 --- a/lib/web_ui/test/window_test.dart +++ b/lib/web_ui/test/window_test.dart @@ -116,7 +116,7 @@ void testMain() { ).catchError((Object e) { caughtAssertion = e as AssertionError; }); - + expect( caughtAssertion.message, 'Receives old navigator update in a router application. This can '