Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/go_router/lib/src/match.dart
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,10 @@ abstract class RouteMatchBase with Diagnosticable {
assert(uriPathToCompare.startsWith(newMatchedLocationToCompare));
assert(remainingLocation.isNotEmpty);

final String childRestLoc = uri.path.substring(
newMatchedLocation.length + (newMatchedLocation == '/' ? 0 : 1),
);
final int offset =
newMatchedLocation.length + (newMatchedLocation == '/' ? 0 : 1);
final String childRestLoc =
offset >= uri.path.length ? '' : uri.path.substring(offset);

Map<GlobalKey<NavigatorState>?, List<RouteMatchBase>>? subRouteMatches;
for (final RouteBase subRoute in route.routes) {
Expand Down
57 changes: 57 additions & 0 deletions packages/go_router/test/match_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,63 @@ void main() {
expect(matches2.length, 1);
expect(matches1.first.pageKey, matches2.first.pageKey);
});

test('ShellRoute with empty child path does not throw RangeError', () {
// Regression test for https://github.com/flutter/flutter/issues/185948
// When state restoration produces an URI whose path does not start
// with the matched route path, the substring offset in
// _matchByNavigatorKeyForGoRoute must not exceed uri.path.length.
final route = ShellRoute(
builder: _shellBuilder,
routes: <RouteBase>[
GoRoute(
path: '/a',
builder: _builder,
routes: <RouteBase>[
GoRoute(path: 'b', builder: _builder),
],
),
],
);
final pathParameters = <String, String>{};
expect(
() => RouteMatchBase.match(
route: route,
pathParameters: pathParameters,
uri: Uri.parse('/'),
rootNavigatorKey: GlobalKey<NavigatorState>(),
),
returnsNormally,
);
});

test('nested route with path shorter than matchedLocation does not throw', () {
// Regression test for https://github.com/flutter/flutter/issues/185948
// When newMatchedLocation is longer than uri.path, the offset
// computation in _matchByNavigatorKeyForGoRoute must be clamped.
final route = ShellRoute(
builder: _shellBuilder,
routes: <RouteBase>[
GoRoute(
path: '',
builder: _builder,
routes: <RouteBase>[
GoRoute(path: '', builder: _builder),
],
),
],
);
final pathParameters = <String, String>{};
expect(
() => RouteMatchBase.match(
route: route,
pathParameters: pathParameters,
uri: Uri.parse('/'),
rootNavigatorKey: GlobalKey<NavigatorState>(),
),
returnsNormally,
);
});
});

test('complex parentNavigatorKey works', () {
Expand Down