Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[web] Fix window.defaultRouteName #17580

Merged
merged 2 commits into from
Apr 8, 2020
Merged
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
26 changes: 2 additions & 24 deletions lib/web_ui/lib/src/engine/browser_location.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,6 @@ part of engine;

// Some parts of this file were inspired/copied from the AngularDart router.

/// Ensures that `str` is prefixed with `leading`.
///
/// If `str` is already prefixed, it'll be returned unchanged. If it's not,
/// this function will prefix it.
///
/// The `applyWhenEmpty` flag controls whether this function should prefix `str`
/// or not when it's an empty string.
///
/// ```dart
/// ensureLeading('/path', '/'); // "/path"
/// ensureLeading('path', '/'); // "/path"
/// ensureLeading('', '/'); // "/"
/// ensureLeading('', '/', applyWhenEmpty: false); // ""
/// ```
String ensureLeading(String str, String leading, {bool applyWhenEmpty = true}) {
if (str.isEmpty && !applyWhenEmpty) {
return str;
}
return str.startsWith(leading) ? str : '$leading$str';
}

/// [LocationStrategy] is responsible for representing and reading route state
/// from the browser's URL.
///
Expand Down Expand Up @@ -93,12 +72,11 @@ class HashLocationStrategy extends LocationStrategy {
// the hash value is always prefixed with a `#`
// and if it is empty then it will stay empty
String path = _platformLocation.hash ?? '';
assert(path.isEmpty || path.startsWith('#'));
// Dart will complain if a call to substring is
// executed with a position value that exceeds the
// length of string.
path = path.isEmpty ? path : path.substring(1);
// The path, by convention, should always contain a leading '/'.
return ensureLeading(path, '/');
return path.isEmpty ? path : path.substring(1);
}

@override
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/test_embedding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class TestLocationStrategy extends LocationStrategy {
history = <TestHistoryEntry>[initialEntry];

@override
String get path => ensureLeading(currentEntry.url, '/');
String get path => currentEntry.url;

int _currentEntryIndex;
int get currentEntryIndex => _currentEntryIndex;
Expand Down
4 changes: 4 additions & 0 deletions lib/web_ui/lib/src/engine/window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,10 @@ class EngineWindow extends ui.Window {
_replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
break;
}
// As soon as Flutter starts taking control of the app navigation, we
// should reset [_defaultRouteName] to "/" so it doesn't have any
// further effect after this point.
_defaultRouteName = '/';
return;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/test/engine/history_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// found in the LICENSE file.

// @dart = 2.6
@TestOn('vm && linux')
@TestOn('!safari')
// TODO(nurhan): https://github.com/flutter/flutter/issues/51169

import 'dart:async';
Expand Down
26 changes: 26 additions & 0 deletions lib/web_ui/test/window_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
// found in the LICENSE file.

// @dart = 2.6
import 'dart:typed_data';

import 'package:test/test.dart';
import 'package:ui/src/engine.dart';

const MethodCodec codec = JSONMethodCodec();

void emptyCallback(ByteData date) {}

TestLocationStrategy _strategy;
TestLocationStrategy get strategy => _strategy;
set strategy(TestLocationStrategy newStrategy) {
Expand All @@ -17,7 +23,27 @@ void main() {
strategy = TestLocationStrategy.fromEntry(TestHistoryEntry('initial state', null, '/initial'));
expect(window.defaultRouteName, '/initial');

// Changing the URL in the address bar later shouldn't affect [window.defaultRouteName].
strategy.replaceState(null, null, '/newpath');
expect(window.defaultRouteName, '/initial');
});

test('window.defaultRouteName should reset after navigation platform message', () {
strategy = TestLocationStrategy.fromEntry(TestHistoryEntry('initial state', null, '/initial'));
// Reading it multiple times should return the same value.
expect(window.defaultRouteName, '/initial');
expect(window.defaultRouteName, '/initial');

window.sendPlatformMessage(
'flutter/navigation',
JSONMethodCodec().encodeMethodCall(MethodCall(
'routePushed',
<String, dynamic>{'previousRouteName': '/foo', 'routeName': '/bar'},
)),
emptyCallback,
);
// After a navigation platform message, [window.defaultRouteName] should
// reset to "/".
expect(window.defaultRouteName, '/');
});
}