Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
9cb9f6bc
Unverified
Commit
9cb9f6bc
authored
Sep 01, 2022
by
David Iglesias
Committed by
GitHub
Sep 01, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[tool] Fix flutter.js regression with hot-reload on promise-based init. (#110805)
parent
822f6e35
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
217 additions
and
6 deletions
+217
-6
flutter_js.dart
...flutter_tools/lib/src/web/file_generators/flutter_js.dart
+2
-0
hot_reload_project.dart
.../test/integration.shard/test_data/hot_reload_project.dart
+2
-0
project.dart
...utter_tools/test/integration.shard/test_data/project.dart
+18
-1
hot_reload_web_test.dart
...ges/flutter_tools/test/web.shard/hot_reload_web_test.dart
+16
-5
hot_reload_index_html_samples.dart
...st/web.shard/test_data/hot_reload_index_html_samples.dart
+179
-0
No files found.
packages/flutter_tools/lib/src/web/file_generators/flutter_js.dart
View file @
9cb9f6bc
...
...
@@ -205,6 +205,8 @@ _flutter.loader = null;
this
.
_didCreateEngineInitializerResolve
(
engineInitializer
);
// Remove the resolver after the first time, so Flutter Web can hot restart.
this
.
_didCreateEngineInitializerResolve
=
null
;
// Make the engine revert to "auto" initialization on hot restart.
delete
_flutter
.
loader
.
didCreateEngineInitializer
;
}
if
(
typeof
this
.
_onEntrypointLoaded
===
"function"
)
{
this
.
_onEntrypointLoaded
(
engineInitializer
);
...
...
packages/flutter_tools/test/integration.shard/test_data/hot_reload_project.dart
View file @
9cb9f6bc
...
...
@@ -6,6 +6,8 @@ import '../test_utils.dart';
import
'project.dart'
;
class
HotReloadProject
extends
Project
{
HotReloadProject
({
super
.
indexHtml
});
@override
final
String
pubspec
=
'''
name: test
...
...
packages/flutter_tools/test/integration.shard/test_data/project.dart
View file @
9cb9f6bc
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'package:file/file.dart'
;
import
'package:flutter_tools/src/web/file_generators/flutter_js.dart'
;
import
'../test_utils.dart'
;
import
'deferred_components_config.dart'
;
...
...
@@ -19,6 +20,11 @@ const String _kDefaultHtml = '''
'''
;
abstract
class
Project
{
/// Creates a flutter Project for testing.
///
/// If passed, `indexHtml` is used as the contents of the web/index.html file.
Project
({
this
.
indexHtml
=
_kDefaultHtml
});
late
Directory
dir
;
String
get
pubspec
;
...
...
@@ -29,6 +35,13 @@ abstract class Project {
Uri
get
mainDart
=>
Uri
.
parse
(
'package:test/main.dart'
);
/// The contents for the index.html file of this `Project`.
///
/// Defaults to [_kDefaultHtml] via the Project constructor.
///
/// (Used by [HotReloadProject].)
final
String
indexHtml
;
Future
<
void
>
setUpIn
(
Directory
dir
)
async
{
this
.
dir
=
dir
;
writeFile
(
fileSystem
.
path
.
join
(
dir
.
path
,
'pubspec.yaml'
),
pubspec
);
...
...
@@ -45,7 +58,11 @@ abstract class Project {
writeFile
(
fileSystem
.
path
.
join
(
dir
.
path
,
'.dart_tool'
,
'flutter_gen'
,
'flutter_gen.dart'
),
generatedFile
);
}
deferredComponents
?.
setUpIn
(
dir
);
writeFile
(
fileSystem
.
path
.
join
(
dir
.
path
,
'web'
,
'index.html'
),
_kDefaultHtml
);
// Setup for different flutter web initializations
writeFile
(
fileSystem
.
path
.
join
(
dir
.
path
,
'web'
,
'index.html'
),
indexHtml
);
writeFile
(
fileSystem
.
path
.
join
(
dir
.
path
,
'web'
,
'flutter.js'
),
generateFlutterJsFile
());
writeFile
(
fileSystem
.
path
.
join
(
dir
.
path
,
'web'
,
'flutter_service_worker.js'
),
''
);
writePackages
(
dir
.
path
);
await
getPackages
(
dir
.
path
);
}
...
...
packages/flutter_tools/test/web.shard/hot_reload_web_test.dart
View file @
9cb9f6bc
...
...
@@ -11,11 +11,22 @@ import '../integration.shard/test_driver.dart';
import
'../integration.shard/test_utils.dart'
;
import
'../src/common.dart'
;
void
main
(
)
{
import
'test_data/hot_reload_index_html_samples.dart'
;
void
main
(
)
async
{
await
_testProject
(
HotReloadProject
());
// default
await
_testProject
(
HotReloadProject
(
indexHtml:
indexHtmlFlutterJsCallback
),
name:
'flutter.js (callback)'
);
await
_testProject
(
HotReloadProject
(
indexHtml:
indexHtmlFlutterJsPromisesFull
),
name:
'flutter.js (promises)'
);
await
_testProject
(
HotReloadProject
(
indexHtml:
indexHtmlFlutterJsPromisesShort
),
name:
'flutter.js (promises, short)'
);
await
_testProject
(
HotReloadProject
(
indexHtml:
indexHtmlNoFlutterJs
),
name:
'No flutter.js'
);
}
Future
<
void
>
_testProject
(
HotReloadProject
project
,
{
String
name
=
'Default'
})
async
{
late
Directory
tempDir
;
final
HotReloadProject
project
=
HotReloadProject
();
late
FlutterRunTestDriver
flutter
;
final
String
testName
=
'Hot reload (index.html:
$name
)'
;
setUp
(()
async
{
tempDir
=
createResolvedTempDirectorySync
(
'hot_reload_test.'
);
await
project
.
setUpIn
(
tempDir
);
...
...
@@ -28,12 +39,12 @@ void main() {
tryToDelete
(
tempDir
);
});
testWithoutContext
(
'hot restart works without error'
,
()
async
{
testWithoutContext
(
'
$testName
:
hot restart works without error'
,
()
async
{
await
flutter
.
run
(
chrome:
true
,
additionalCommandArgs:
<
String
>[
'--verbose'
,
'--web-renderer=html'
]);
await
flutter
.
hotRestart
();
});
testWithoutContext
(
'newly added code executes during hot restart'
,
()
async
{
testWithoutContext
(
'
$testName
:
newly added code executes during hot restart'
,
()
async
{
final
Completer
<
void
>
completer
=
Completer
<
void
>();
final
StreamSubscription
<
String
>
subscription
=
flutter
.
stdout
.
listen
((
String
line
)
{
if
(
line
.
contains
(
'(((((RELOAD WORKED)))))'
))
{
...
...
@@ -50,7 +61,7 @@ void main() {
}
});
testWithoutContext
(
'newly added code executes during hot restart - canvaskit'
,
()
async
{
testWithoutContext
(
'
$testName
:
newly added code executes during hot restart - canvaskit'
,
()
async
{
final
Completer
<
void
>
completer
=
Completer
<
void
>();
final
StreamSubscription
<
String
>
subscription
=
flutter
.
stdout
.
listen
((
String
line
)
{
if
(
line
.
contains
(
'(((((RELOAD WORKED)))))'
))
{
...
...
packages/flutter_tools/test/web.shard/test_data/hot_reload_index_html_samples.dart
0 → 100644
View file @
9cb9f6bc
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains a bunch of different index.html "styles" that can be written
// by Flutter Web users.
// This should be somewhat kept in sync with the different index.html files present
// in `flutter/dev/integration_tests/web/web`.
// @see https://github.com/flutter/flutter/tree/master/dev/integration_tests/web/web
/// index_with_flutterjs_entrypoint_loaded.html
String
indexHtmlFlutterJsCallback
=
_generateFlutterJsIndexHtml
(
'''
window.addEventListener('
load
', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
onEntrypointLoaded: onEntrypointLoaded,
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
});
// Once the entrypoint is ready, do things!
async function onEntrypointLoaded(engineInitializer) {
const appRunner = await engineInitializer.initializeEngine();
appRunner.runApp();
}
});
'''
);
/// index_with_flutterjs_short.html
String
indexHtmlFlutterJsPromisesShort
=
_generateFlutterJsIndexHtml
(
'''
window.addEventListener('
load
', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
}).then(function(engineInitializer) {
return engineInitializer.autoStart();
});
});
'''
);
/// index_with_flutterjs.html
String
indexHtmlFlutterJsPromisesFull
=
_generateFlutterJsIndexHtml
(
'''
window.addEventListener('
load
', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
}).then(function(engineInitializer) {
return engineInitializer.initializeEngine();
}).then(function(appRunner) {
return appRunner.runApp();
});
});
'''
);
/// index_without_flutterjs.html
String
indexHtmlNoFlutterJs
=
'''
<!DOCTYPE HTML>
<!-- Copyright 2014 The Flutter Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<html>
<head>
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<title>Web Test</title>
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Web Test">
<link rel="manifest" href="manifest.json">
</head>
<body>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('
script
');
scriptTag.src = '
main
.
dart
.
js
';
scriptTag.type = '
application
/
javascript
';
document.body.append(scriptTag);
}
if ('
serviceWorker
' in navigator) {
// Service workers are supported. Use them.
window.addEventListener('
load
', function () {
// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = '
flutter_service_worker
.
js
?
v
=
' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl)
.then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('
statechange
', () => {
if (serviceWorker.state == '
activated
') {
console.log('
Installed
new
service
worker
.
');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing ?? reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('
New
service
worker
available
.
');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('
Loading
app
from
service
worker
.
');
loadMainDartJs();
}
});
// If service worker doesn'
t
succeed
in
a
reasonable
amount
of
time
,
// fallback to plaint <script> tag.
setTimeout
(()
=>
{
if
(!
scriptLoaded
)
{
console
.
warn
(
'Failed to load app from service worker. Falling back to plain <script> tag.'
,
);
loadMainDartJs
();
}
},
4000
);
});
}
else
{
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs
();
}
</
script
>
</
body
>
</
html
>
''';
// Generates the scaffolding of an index.html file, with a configurable `initScript`.
String _generateFlutterJsIndexHtml(String initScript) => '''
<!
DOCTYPE
HTML
>
<!--
Copyright
2014
The
Flutter
Authors
.
All
rights
reserved
.
Use
of
this
source
code
is
governed
by
a
BSD
-
style
license
that
can
be
found
in
the
LICENSE
file
.
-->
<
html
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
meta
content
=
"IE=Edge"
http
-
equiv
=
"X-UA-Compatible"
>
<
title
>
Integration
test
.
App
load
with
flutter
.
js
and
onEntrypointLoaded
API
</
title
>
<!--
iOS
meta
tags
&
icons
-->
<
meta
name
=
"apple-mobile-web-app-capable"
content
=
"yes"
>
<
meta
name
=
"apple-mobile-web-app-status-bar-style"
content
=
"black"
>
<
meta
name
=
"apple-mobile-web-app-title"
content
=
"Web Test"
>
<
link
rel
=
"manifest"
href
=
"manifest.json"
>
<
script
>
// The value below is injected by flutter build, do not touch.
var
serviceWorkerVersion
=
null
;
</
script
>
<!--
This
script
adds
the
flutter
initialization
JS
code
-->
<
script
src
=
"flutter.js"
defer
></
script
>
</
head
>
<
body
>
<
script
>
$initScript
</
script
>
</
body
>
</
html
>
''';
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment