Skip to content

Commit 783f2f4

Browse files
authored
[web] provide serviceWorkerVersion to the getNewServiceWorker function (#131240)
Fixes flutter/flutter#130212 Fix `Unresolved variable or type 'serviceWorkerVersion'` in the `_getNewServiceWorker` function. Supersedes flutter/flutter#130206
1 parent 98bee67 commit 783f2f4

File tree

4 files changed

+182
-2
lines changed

4 files changed

+182
-2
lines changed

dev/bots/service_worker_test.dart

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ enum ServiceWorkerTestType {
3737
withFlutterJsEntrypointLoadedEvent,
3838
// Same as withFlutterJsEntrypointLoadedEvent, but with TrustedTypes enabled.
3939
withFlutterJsTrustedTypesOn,
40+
// Uses custom serviceWorkerVersion.
41+
withFlutterJsCustomServiceWorkerVersion,
4042
// Entrypoint generated by `flutter create`.
4143
generatedEntrypoint,
4244
}
@@ -58,6 +60,7 @@ Future<void> main() async {
5860
await runWebServiceWorkerTestWithCachingResources(headless: false, testType: ServiceWorkerTestType.withFlutterJsTrustedTypesOn);
5961
await runWebServiceWorkerTestWithGeneratedEntrypoint(headless: false);
6062
await runWebServiceWorkerTestWithBlockedServiceWorkers(headless: false);
63+
await runWebServiceWorkerTestWithCustomServiceWorkerVersion(headless: false);
6164

6265
if (hasError) {
6366
reportErrorsAndExit('${bold}One or more tests failed.$reset');
@@ -117,6 +120,8 @@ String _testTypeToIndexFile(ServiceWorkerTestType type) {
117120
indexFile = 'index_with_flutterjs_entrypoint_loaded.html';
118121
case ServiceWorkerTestType.withFlutterJsTrustedTypesOn:
119122
indexFile = 'index_with_flutterjs_el_tt_on.html';
123+
case ServiceWorkerTestType.withFlutterJsCustomServiceWorkerVersion:
124+
indexFile = 'index_with_flutterjs_custom_sw_version.html';
120125
case ServiceWorkerTestType.generatedEntrypoint:
121126
indexFile = 'generated_entrypoint.html';
122127
}
@@ -703,3 +708,137 @@ Future<void> runWebServiceWorkerTestWithBlockedServiceWorkers({
703708
}
704709
print('END runWebServiceWorkerTestWithBlockedServiceWorkers(headless: $headless)');
705710
}
711+
712+
/// Regression test for https://github.com/flutter/flutter/issues/130212.
713+
Future<void> runWebServiceWorkerTestWithCustomServiceWorkerVersion({
714+
required bool headless,
715+
}) async {
716+
final Map<String, int> requestedPathCounts = <String, int>{};
717+
void expectRequestCounts(Map<String, int> expectedCounts) =>
718+
_expectRequestCounts(expectedCounts, requestedPathCounts);
719+
720+
AppServer? server;
721+
Future<void> waitForAppToLoad(Map<String, int> waitForCounts) async =>
722+
_waitForAppToLoad(waitForCounts, requestedPathCounts, server);
723+
724+
Future<void> startAppServer({
725+
required String cacheControl,
726+
}) async {
727+
final int serverPort = await findAvailablePortAndPossiblyCauseFlakyTests();
728+
final int browserDebugPort = await findAvailablePortAndPossiblyCauseFlakyTests();
729+
server = await AppServer.start(
730+
headless: headless,
731+
cacheControl: cacheControl,
732+
// TODO(yjbanov): use a better port disambiguation strategy than trying
733+
// to guess what ports other tests use.
734+
appUrl: 'http://localhost:$serverPort/index.html',
735+
serverPort: serverPort,
736+
browserDebugPort: browserDebugPort,
737+
appDirectory: _appBuildDirectory,
738+
additionalRequestHandlers: <Handler>[
739+
(Request request) {
740+
final String requestedPath = request.url.path;
741+
requestedPathCounts.putIfAbsent(requestedPath, () => 0);
742+
requestedPathCounts[requestedPath] = requestedPathCounts[requestedPath]! + 1;
743+
if (requestedPath == 'CLOSE') {
744+
return Response.ok('OK');
745+
}
746+
return Response.notFound('');
747+
},
748+
],
749+
);
750+
}
751+
752+
// Preserve old index.html as index_og.html so we can restore it later for other tests
753+
await runCommand(
754+
'mv',
755+
<String>[
756+
'index.html',
757+
'index_og.html',
758+
],
759+
workingDirectory: _testAppWebDirectory,
760+
);
761+
762+
print('BEGIN runWebServiceWorkerTestWithCustomServiceWorkerVersion(headless: $headless)');
763+
try {
764+
await _rebuildApp(version: 1, testType: ServiceWorkerTestType.withFlutterJsCustomServiceWorkerVersion, target: _target);
765+
766+
print('Test page load');
767+
await startAppServer(cacheControl: 'max-age=0');
768+
await waitForAppToLoad(<String, int>{
769+
'CLOSE': 1,
770+
'flutter_service_worker.js': 1,
771+
'assets/fonts/MaterialIcons-Regular.otf': 1,
772+
});
773+
expectRequestCounts(<String, int>{
774+
'index.html': 2,
775+
'flutter.js': 1,
776+
'main.dart.js': 1,
777+
'CLOSE': 1,
778+
'flutter_service_worker.js': 1,
779+
'assets/FontManifest.json': 1,
780+
'assets/AssetManifest.json': 1,
781+
'assets/fonts/MaterialIcons-Regular.otf': 1,
782+
// In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'.
783+
if (!headless)
784+
...<String, int>{
785+
'manifest.json': 1,
786+
'favicon.ico': 1,
787+
},
788+
});
789+
790+
print('Test page reload, ensure service worker is not reloaded');
791+
await server!.chrome.reloadPage(ignoreCache: true);
792+
await waitForAppToLoad(<String, int>{
793+
'CLOSE': 1,
794+
'flutter.js': 1,
795+
});
796+
expectRequestCounts(<String, int>{
797+
'index.html': 1,
798+
'flutter.js': 1,
799+
'main.dart.js': 1,
800+
'assets/FontManifest.json': 1,
801+
'assets/fonts/MaterialIcons-Regular.otf': 1,
802+
'CLOSE': 1,
803+
// In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'.
804+
if (!headless)
805+
...<String, int>{
806+
'manifest.json': 1,
807+
'favicon.ico': 1,
808+
},
809+
});
810+
811+
print('Test page reload after rebuild, ensure service worker is not reloaded');
812+
await _rebuildApp(version: 1, testType: ServiceWorkerTestType.withFlutterJsCustomServiceWorkerVersion, target: _target);
813+
await server!.chrome.reloadPage(ignoreCache: true);
814+
await waitForAppToLoad(<String, int>{
815+
'CLOSE': 1,
816+
'flutter.js': 1,
817+
});
818+
expectRequestCounts(<String, int>{
819+
'index.html': 1,
820+
'flutter.js': 1,
821+
'main.dart.js': 1,
822+
'assets/FontManifest.json': 1,
823+
'assets/fonts/MaterialIcons-Regular.otf': 1,
824+
'CLOSE': 1,
825+
// In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'.
826+
if (!headless)
827+
...<String, int>{
828+
'manifest.json': 1,
829+
'favicon.ico': 1,
830+
},
831+
});
832+
} finally {
833+
await runCommand(
834+
'mv',
835+
<String>[
836+
'index_og.html',
837+
'index.html',
838+
],
839+
workingDirectory: _testAppWebDirectory,
840+
);
841+
await server?.stop();
842+
}
843+
print('END runWebServiceWorkerTestWithCustomServiceWorkerVersion(headless: $headless)');
844+
}

dev/bots/test.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,7 @@ Future<void> _runWebLongRunningTests() async {
12491249
() => runWebServiceWorkerTestWithCachingResources(headless: true, testType: ServiceWorkerTestType.withFlutterJsTrustedTypesOn),
12501250
() => runWebServiceWorkerTestWithGeneratedEntrypoint(headless: true),
12511251
() => runWebServiceWorkerTestWithBlockedServiceWorkers(headless: true),
1252+
() => runWebServiceWorkerTestWithCustomServiceWorkerVersion(headless: true),
12521253
() => _runWebStackTraceTest('profile', 'lib/stack_trace.dart'),
12531254
() => _runWebStackTraceTest('release', 'lib/stack_trace.dart'),
12541255
() => _runWebStackTraceTest('profile', 'lib/framework_stack_trace.dart'),
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE HTML>
2+
<!-- Copyright 2014 The Flutter Authors. All rights reserved.
3+
Use of this source code is governed by a BSD-style license that can be
4+
found in the LICENSE file. -->
5+
<html>
6+
<head>
7+
<meta charset="UTF-8">
8+
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
9+
10+
<title>Integration test. App load with flutter.js. Custom serviceWorkerVersion provided.</title>
11+
12+
<!-- iOS meta tags & icons -->
13+
<meta name="apple-mobile-web-app-capable" content="yes">
14+
<meta name="apple-mobile-web-app-status-bar-style" content="black">
15+
<meta name="apple-mobile-web-app-title" content="Web Test">
16+
<link rel="manifest" href="manifest.json">
17+
<script>
18+
// The value below is injected by flutter build, do not touch.
19+
var serviceWorkerVersion = null;
20+
</script>
21+
<!-- This script adds the flutter initialization JS code -->
22+
<script src="flutter.js" defer></script>
23+
</head>
24+
<body>
25+
<script>
26+
window.addEventListener('load', function(ev) {
27+
// Download main.dart.js
28+
_flutter.loader.loadEntrypoint({
29+
serviceWorker: {
30+
serviceWorkerVersion: '123',
31+
},
32+
onEntrypointLoaded: function(engineInitializer) {
33+
return engineInitializer.autoStart();
34+
}
35+
});
36+
});
37+
</script>
38+
</body>
39+
</html>

packages/flutter_tools/lib/src/web/file_generators/js/flutter.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ _flutter.loader = null;
144144

145145
const serviceWorkerActivation = navigator.serviceWorker
146146
.register(url)
147-
.then(this._getNewServiceWorker)
147+
.then((serviceWorkerRegistration) => this._getNewServiceWorker(serviceWorkerRegistration, serviceWorkerVersion))
148148
.then(this._waitForServiceWorkerActivation);
149149

150150
// Timeout race promise
@@ -162,9 +162,10 @@ _flutter.loader = null;
162162
* awaiting to be installed/updated.
163163
*
164164
* @param {ServiceWorkerRegistration} serviceWorkerRegistration
165+
* @param {String} serviceWorkerVersion
165166
* @returns {Promise<ServiceWorker>}
166167
*/
167-
async _getNewServiceWorker(serviceWorkerRegistration) {
168+
async _getNewServiceWorker(serviceWorkerRegistration, serviceWorkerVersion) {
168169
if (!serviceWorkerRegistration.active && (serviceWorkerRegistration.installing || serviceWorkerRegistration.waiting)) {
169170
// No active web worker and we have installed or are installing
170171
// one for the first time. Simply wait for it to activate.

0 commit comments

Comments
 (0)