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
c11633e8
Unverified
Commit
c11633e8
authored
Nov 09, 2018
by
Jonah Williams
Committed by
GitHub
Nov 09, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Separate hot reload and hot restart capabilities. (#24122)
parent
9ecb4ce9
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
167 additions
and
20 deletions
+167
-20
android_device.dart
packages/flutter_tools/lib/src/android/android_device.dart
+4
-1
attach.dart
packages/flutter_tools/lib/src/commands/attach.dart
+3
-1
daemon.dart
packages/flutter_tools/lib/src/commands/daemon.dart
+1
-1
run.dart
packages/flutter_tools/lib/src/commands/run.dart
+2
-2
device.dart
packages/flutter_tools/lib/src/device.dart
+5
-2
fuchsia_device.dart
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
+4
-1
devices.dart
packages/flutter_tools/lib/src/ios/devices.dart
+4
-1
simulators.dart
packages/flutter_tools/lib/src/ios/simulators.dart
+4
-1
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+11
-0
run_hot.dart
packages/flutter_tools/lib/src/run_hot.dart
+18
-3
hot_test.dart
packages/flutter_tools/test/hot_test.dart
+111
-7
No files found.
packages/flutter_tools/lib/src/android/android_device.dart
View file @
c11633e8
...
...
@@ -469,7 +469,10 @@ class AndroidDevice extends Device {
}
@override
bool
get
supportsHotMode
=>
true
;
bool
get
supportsHotReload
=>
true
;
@override
bool
get
supportsHotRestart
=>
true
;
@override
Future
<
bool
>
stopApp
(
ApplicationPackage
app
)
{
...
...
packages/flutter_tools/lib/src/commands/attach.dart
View file @
c11633e8
...
...
@@ -209,7 +209,9 @@ class AttachCommand extends FlutterCommand {
}
}
finally
{
final
List
<
ForwardedPort
>
ports
=
device
.
portForwarder
.
forwardedPorts
.
toList
();
ports
.
forEach
(
device
.
portForwarder
.
unforward
);
for
(
ForwardedPort
port
in
ports
)
{
await
device
.
portForwarder
.
unforward
(
port
);
}
}
return
null
;
}
...
...
packages/flutter_tools/lib/src/commands/daemon.dart
View file @
c11633e8
...
...
@@ -458,7 +458,7 @@ class AppDomain extends Domain {
}
bool
isRestartSupported
(
bool
enableHotReload
,
Device
device
)
=>
enableHotReload
&&
device
.
supportsHot
Mode
;
enableHotReload
&&
device
.
supportsHot
Restart
;
Future
<
OperationResult
>
_inProgressHotReload
;
...
...
packages/flutter_tools/lib/src/commands/run.dart
View file @
c11633e8
...
...
@@ -336,8 +336,8 @@ class RunCommand extends RunCommandBase {
if
(
hotMode
)
{
for
(
Device
device
in
devices
)
{
if
(!
device
.
supportsHot
Mode
)
throwToolExit
(
'Hot
mode
is not supported by
${device.name}
. Run with --no-hot.'
);
if
(!
device
.
supportsHot
Reload
)
throwToolExit
(
'Hot
reload
is not supported by
${device.name}
. Run with --no-hot.'
);
}
}
...
...
packages/flutter_tools/lib/src/device.dart
View file @
c11633e8
...
...
@@ -270,8 +270,11 @@ abstract class Device {
bool
ipv6
=
false
,
});
/// Does this device implement support for hot reloading / restarting?
bool
get
supportsHotMode
=>
true
;
/// Whether this device implements support for hot reload.
bool
get
supportsHotReload
=>
true
;
/// Whether this device implements support for hot restart.
bool
get
supportsHotRestart
=>
true
;
/// Stop an app package on the current device.
Future
<
bool
>
stopApp
(
ApplicationPackage
app
);
...
...
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
View file @
c11633e8
...
...
@@ -97,7 +97,10 @@ class FuchsiaDevice extends Device {
FuchsiaDevice
(
String
id
,
{
this
.
name
})
:
super
(
id
);
@override
bool
get
supportsHotMode
=>
true
;
bool
get
supportsHotReload
=>
true
;
@override
bool
get
supportsHotRestart
=>
false
;
@override
final
String
name
;
...
...
packages/flutter_tools/lib/src/ios/devices.dart
View file @
c11633e8
...
...
@@ -124,7 +124,10 @@ class IOSDevice extends Device {
final
String
_sdkVersion
;
@override
bool
get
supportsHotMode
=>
true
;
bool
get
supportsHotReload
=>
true
;
@override
bool
get
supportsHotRestart
=>
true
;
@override
final
String
name
;
...
...
packages/flutter_tools/lib/src/ios/simulators.dart
View file @
c11633e8
...
...
@@ -223,7 +223,10 @@ class IOSSimulator extends Device {
Future
<
bool
>
get
isLocalEmulator
async
=>
true
;
@override
bool
get
supportsHotMode
=>
true
;
bool
get
supportsHotReload
=>
true
;
@override
bool
get
supportsHotRestart
=>
true
;
Map
<
ApplicationPackage
,
_IOSSimulatorLogReader
>
_logReaders
;
_IOSSimulatorDevicePortForwarder
_portForwarder
;
...
...
packages/flutter_tools/lib/src/resident_runner.dart
View file @
c11633e8
...
...
@@ -460,6 +460,17 @@ abstract class ResidentRunner {
bool
get
isRunningRelease
=>
debuggingOptions
.
buildInfo
.
isRelease
;
bool
get
supportsServiceProtocol
=>
isRunningDebug
||
isRunningProfile
;
/// Whether this runner can hot restart.
///
/// To prevent scenarios where only a subset of devices are hot restarted,
/// the runner requires that all attached devices can support hot restart
/// before enabling it.
bool
get
canHotRestart
{
return
flutterDevices
.
every
((
FlutterDevice
device
)
{
return
device
.
device
.
supportsHotRestart
;
});
}
/// Start the app and keep the process running during its lifetime.
Future
<
int
>
run
({
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
,
...
...
packages/flutter_tools/lib/src/run_hot.dart
View file @
c11633e8
...
...
@@ -289,7 +289,16 @@ class HotRunner extends ResidentRunner {
Future
<
void
>
handleTerminalCommand
(
String
code
)
async
{
final
String
lower
=
code
.
toLowerCase
();
if
(
lower
==
'r'
)
{
final
OperationResult
result
=
await
restart
(
fullRestart:
code
==
'R'
);
OperationResult
result
;
if
(
code
==
'R'
)
{
// If hot restart is not supported for all devices, ignore the command.
if
(!
canHotRestart
)
{
return
;
}
result
=
await
restart
(
fullRestart:
true
);
}
else
{
result
=
await
restart
(
fullRestart:
false
);
}
if
(!
result
.
isOk
)
{
// TODO(johnmccutchan): Attempt to determine the number of errors that
// occurred and tighten this message.
...
...
@@ -541,6 +550,9 @@ class HotRunner extends ResidentRunner {
Future
<
OperationResult
>
restart
({
bool
fullRestart
=
false
,
bool
pauseAfterRestart
=
false
,
String
reason
})
async
{
final
Stopwatch
timer
=
Stopwatch
()..
start
();
if
(
fullRestart
)
{
if
(!
canHotRestart
)
{
return
OperationResult
(
1
,
'hotRestart not supported'
);
}
final
Status
status
=
logger
.
startProgress
(
'Performing hot restart...'
,
progressId:
'hot.restart'
,
...
...
@@ -780,9 +792,12 @@ class HotRunner extends ResidentRunner {
@override
void
printHelp
({
@required
bool
details
})
{
const
String
fire
=
'🔥'
;
String
rawMessage
=
' To hot reload changes while running, press "r". '
;
if
(
canHotRestart
)
{
rawMessage
+=
'To hot restart (and rebuild state), press "R".'
;
}
final
String
message
=
terminal
.
color
(
fire
+
terminal
.
bolden
(
' To hot reload changes while running, press "r". '
'To hot restart (and rebuild state), press "R".'
),
fire
+
terminal
.
bolden
(
rawMessage
),
TerminalColor
.
red
,
);
printStatus
(
message
);
...
...
packages/flutter_tools/test/hot_test.dart
View file @
c11633e8
...
...
@@ -5,6 +5,7 @@
import
'dart:async'
;
import
'package:flutter_tools/src/artifacts.dart'
;
import
'package:flutter_tools/src/devfs.dart'
;
import
'package:flutter_tools/src/device.dart'
;
import
'package:flutter_tools/src/resident_runner.dart'
;
import
'package:flutter_tools/src/run_hot.dart'
;
...
...
@@ -94,32 +95,113 @@ void main() {
group
(
'hotRestart'
,
()
{
final
MockResidentCompiler
residentCompiler
=
MockResidentCompiler
();
final
MockDevFs
mockDevFs
=
MockDevFs
();
MockLocalEngineArtifacts
mockArtifacts
;
when
(
mockDevFs
.
update
(
mainPath:
anyNamed
(
'mainPath'
),
target:
anyNamed
(
'target'
),
bundle:
anyNamed
(
'bundle'
),
firstBuildTime:
anyNamed
(
'firstBuildTime'
),
bundleFirstUpload:
anyNamed
(
'bundleFirstUpload'
),
bundleDirty:
anyNamed
(
'bundleDirty'
),
fileFilter:
anyNamed
(
'fileFilter'
),
generator:
anyNamed
(
'generator'
),
fullRestart:
anyNamed
(
'fullRestart'
),
dillOutputPath:
anyNamed
(
'dillOutputPath'
),
trackWidgetCreation:
anyNamed
(
'trackWidgetCreation'
),
projectRootPath:
anyNamed
(
'projectRootPath'
),
pathToReload:
anyNamed
(
'pathToReload'
),
)).
thenAnswer
((
Invocation
_
)
=>
Future
<
int
>.
value
(
1000
));
when
(
mockDevFs
.
assetPathsToEvict
).
thenReturn
(
Set
<
String
>());
when
(
mockDevFs
.
baseUri
).
thenReturn
(
Uri
.
file
(
'test'
));
setUp
(()
{
mockArtifacts
=
MockLocalEngineArtifacts
();
when
(
mockArtifacts
.
getArtifactPath
(
Artifact
.
flutterPatchedSdkPath
)).
thenReturn
(
'some/path'
);
});
testUsingContext
(
'no setup'
,
()
async
{
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
MockDevice
(),
generator:
residentCompiler
,
trackWidgetCreation:
false
)];
final
MockDevice
mockDevice
=
MockDevice
();
when
(
mockDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
true
);
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
mockDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
),
];
expect
((
await
HotRunner
(
devices
).
restart
(
fullRestart:
true
)).
isOk
,
false
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
});
testUsingContext
(
'setup function succeeds'
,
()
async
{
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
MockDevice
(),
generator:
residentCompiler
,
trackWidgetCreation:
false
)];
testUsingContext
(
'Does not hot restart when device does not support it'
,
()
async
{
// Setup mocks
final
MockDevice
mockDevice
=
MockDevice
();
when
(
mockDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
false
);
// Trigger hot restart.
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
mockDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
)..
devFS
=
mockDevFs
];
final
OperationResult
result
=
await
HotRunner
(
devices
).
restart
(
fullRestart:
true
);
// Expect hot restart failed.
expect
(
result
.
isOk
,
false
);
expect
(
result
.
message
,
isNot
(
'setupHotRestart failed'
)
);
expect
(
result
.
message
,
'hotRestart not supported'
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
HotRunnerConfig:
()
=>
TestHotRunnerConfig
(
successfulSetup:
true
),
HotRunnerConfig:
()
=>
TestHotRunnerConfig
(
successfulSetup:
true
,
computeDartDependencies:
false
),
});
testUsingContext
(
'Does not hot restart when one of many devices does not support it'
,
()
async
{
// Setup mocks
final
MockDevice
mockDevice
=
MockDevice
();
final
MockDevice
mockHotDevice
=
MockDevice
();
when
(
mockDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
false
);
when
(
mockHotDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockHotDevice
.
supportsHotRestart
).
thenReturn
(
true
);
// Trigger hot restart.
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
mockDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
)..
devFS
=
mockDevFs
,
FlutterDevice
(
mockHotDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
)..
devFS
=
mockDevFs
,
];
final
OperationResult
result
=
await
HotRunner
(
devices
).
restart
(
fullRestart:
true
);
// Expect hot restart failed.
expect
(
result
.
isOk
,
false
);
expect
(
result
.
message
,
'hotRestart not supported'
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
HotRunnerConfig:
()
=>
TestHotRunnerConfig
(
successfulSetup:
true
,
computeDartDependencies:
false
),
});
testUsingContext
(
'Does hot restarts when all devices support it'
,
()
async
{
// Setup mocks
final
MockDevice
mockDevice
=
MockDevice
();
final
MockDevice
mockHotDevice
=
MockDevice
();
when
(
mockDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
true
);
when
(
mockHotDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockHotDevice
.
supportsHotRestart
).
thenReturn
(
true
);
// Trigger a restart.
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
mockDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
)..
devFS
=
mockDevFs
,
FlutterDevice
(
mockHotDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
)..
devFS
=
mockDevFs
,
];
final
OperationResult
result
=
await
HotRunner
(
devices
).
restart
(
fullRestart:
true
);
// Expect hot restart was successful.
expect
(
result
.
isOk
,
true
);
expect
(
result
.
message
,
isNot
(
'hotRestart not supported'
));
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
HotRunnerConfig:
()
=>
TestHotRunnerConfig
(
successfulSetup:
true
,
computeDartDependencies:
false
),
});
testUsingContext
(
'setup function fails'
,
()
async
{
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
MockDevice
(),
generator:
residentCompiler
,
trackWidgetCreation:
false
)];
final
MockDevice
mockDevice
=
MockDevice
();
when
(
mockDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
true
);
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
mockDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
)
];
final
OperationResult
result
=
await
HotRunner
(
devices
).
restart
(
fullRestart:
true
);
expect
(
result
.
isOk
,
false
);
expect
(
result
.
message
,
'setupHotRestart failed'
);
...
...
@@ -127,9 +209,29 @@ void main() {
Artifacts:
()
=>
mockArtifacts
,
HotRunnerConfig:
()
=>
TestHotRunnerConfig
(
successfulSetup:
false
),
});
testUsingContext
(
'hot restart supported'
,
()
async
{
// Setup mocks
final
MockDevice
mockDevice
=
MockDevice
();
when
(
mockDevice
.
supportsHotReload
).
thenReturn
(
true
);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
true
);
// Trigger hot restart.
final
List
<
FlutterDevice
>
devices
=
<
FlutterDevice
>[
FlutterDevice
(
mockDevice
,
generator:
residentCompiler
,
trackWidgetCreation:
false
)..
devFS
=
mockDevFs
];
final
OperationResult
result
=
await
HotRunner
(
devices
).
restart
(
fullRestart:
true
);
// Expect hot restart successful.
expect
(
result
.
isOk
,
true
);
expect
(
result
.
message
,
isNot
(
'setupHotRestart failed'
));
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
HotRunnerConfig:
()
=>
TestHotRunnerConfig
(
successfulSetup:
true
,
computeDartDependencies:
false
),
});
});
}
class
MockDevFs
extends
Mock
implements
DevFS
{}
class
MockLocalEngineArtifacts
extends
Mock
implements
LocalEngineArtifacts
{}
class
MockDevice
extends
Mock
implements
Device
{
...
...
@@ -139,7 +241,9 @@ class MockDevice extends Mock implements Device {
}
class
TestHotRunnerConfig
extends
HotRunnerConfig
{
TestHotRunnerConfig
({
@required
this
.
successfulSetup
});
TestHotRunnerConfig
({
@required
this
.
successfulSetup
,
bool
computeDartDependencies
=
true
})
{
this
.
computeDartDependencies
=
computeDartDependencies
;
}
bool
successfulSetup
;
...
...
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