Skip to content

Commit 735966b

Browse files
arpitgandhi9gemini-code-assist[bot]bkonyi
authored
feat: add reloadIsRestart to handle hot reload as a restart for web flutter#179448 (flutter#183233)
This PR fixes the --no-hot flag on web-server not working properly. When running flutter run -d web-server --no-hot, the flag was ignored and hot reload still occurred instead of performing hot restart. Problem When --no-hot was passed to disable hot reload on web, pressing 'r' in the console would be ignored entirely. The terminal handler was checking canHotReload, which was false when --no-hot was set, but it didn't account for platforms like web where hot reload must always be implemented as a hot restart. Solution Added a reloadIsRestart property to the ResidentHandlers abstract class to indicate platforms where hot reload should be treated as restart. Updated the terminal handler's 'r' key logic to allow the command when either canHotReload is true OR reloadIsRestart is true. The web runner already automatically converts reloads to restarts when needed. Changes Made [resident_runner.dart]: Added reloadIsRestart to ResidentHandlers abstract class and implemented in ResidentRunner (returns false by default) [run_cold.dart]: Implemented reloadIsRestart getter (returns false) [run_hot.dart]: Implemented reloadIsRestart getter (returns false) [resident_web_runner.dart]: Already had proper reloadIsRestart implementation [terminal_handler_test.dart]: Added test case to verify 'r' key works when reloadIsRestart=true and canHotReload=false Before/After Behavior Before: ``` $ flutter run -d web-server --no-hot > r # User presses 'r' # Nothing happens - command is ignored ``` After: ``` $ flutter run -d web-server --no-hot > r # User presses 'r' Performing hot restart... # ✅ Correctly performs hot restart ``` Testing Added comprehensive test coverage with a new test case: "r - reloadIsRestart when canHotReload is false (web --no-hot case)". All 96 existing terminal handler tests pass. Fixes Fixes flutter#179448 --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Ben Konyi <bkonyi@google.com>
1 parent 9724add commit 735966b

4 files changed

Lines changed: 43 additions & 1 deletion

File tree

packages/flutter_tools/lib/src/resident_runner.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,12 @@ abstract class ResidentHandlers {
576576
/// Whether an application can be detached without being stopped.
577577
bool get supportsDetach;
578578

579+
/// Whether a hot reload should be treated as a hot restart.
580+
///
581+
/// This is used by platforms like web where hot reload must always perform
582+
/// a full restart instead of updating code in-place.
583+
bool get reloadIsRestart;
584+
579585
@protected
580586
Logger get logger;
581587

@@ -1101,6 +1107,7 @@ abstract class ResidentRunner extends ResidentHandlers {
11011107
bool get canHotReload => hotMode;
11021108

11031109
/// Whether the hot reload support is implemented as hot restart.
1110+
@override
11041111
bool get reloadIsRestart => false;
11051112

11061113
/// Start the app and keep the process running during its lifetime.
@@ -1729,7 +1736,10 @@ class TerminalHandler {
17291736
await residentRunner.exit();
17301737
return true;
17311738
case 'r':
1732-
if (!residentRunner.canHotReload) {
1739+
// Allow hot reload if enabled. Also allow it if reloadIsRestart is true
1740+
// (e.g., web with --no-hot), since in that case the reload will be
1741+
// converted to a restart internally.
1742+
if (!(residentRunner.canHotReload || residentRunner.reloadIsRestart)) {
17331743
return false;
17341744
}
17351745
final OperationResult result = await residentRunner.restart();

packages/flutter_tools/lib/src/run_cold.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class ColdRunner extends ResidentRunner {
3636
@override
3737
bool get canHotReload => false;
3838

39+
@override
40+
bool get reloadIsRestart => false;
41+
3942
@override
4043
Logger get logger => globals.logger;
4144

packages/flutter_tools/lib/src/run_hot.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ class HotRunner extends ResidentRunner {
145145
@override
146146
bool get supportsDetach => stopAppDuringCleanup;
147147

148+
@override
149+
bool get reloadIsRestart => false;
150+
148151
Future<void> _calculateTargetPlatform() async {
149152
if (_targetPlatformName != null) {
150153
return;

packages/flutter_tools/test/general.shard/terminal_handler_test.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,25 @@ void main() {
863863
expect(runner.calledRestart, false);
864864
});
865865

866+
testWithoutContext(
867+
'r - reloadIsRestart when canHotReload is false (web --no-hot case)',
868+
() async {
869+
final TerminalHandler terminalHandler = setUpTerminalHandler(
870+
<FakeVmServiceRequest>[],
871+
supportsHotReload: false,
872+
);
873+
final runner = terminalHandler.residentRunner as FakeResidentRunner;
874+
runner.reloadIsRestart = true;
875+
876+
await terminalHandler.processTerminalInput('r');
877+
878+
// When reloadIsRestart is true, 'r' should still trigger a restart
879+
// even though canHotReload is false
880+
expect(runner.calledReload, false);
881+
expect(runner.calledRestart, true);
882+
},
883+
);
884+
866885
testWithoutContext('R - hotRestart', () async {
867886
final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]);
868887
final runner = terminalHandler.residentRunner as FakeResidentRunner;
@@ -1532,6 +1551,9 @@ class FakeResidentRunner extends ResidentHandlers {
15321551
@override
15331552
bool supportsServiceProtocol = true;
15341553

1554+
@override
1555+
bool reloadIsRestart = false; // Defaults to false, only true when web --no-hot
1556+
15351557
@override
15361558
Future<void> cleanupAfterSignal() async {}
15371559

@@ -1563,6 +1585,10 @@ class FakeResidentRunner extends ResidentHandlers {
15631585
bool pause = false,
15641586
String? reason,
15651587
}) async {
1588+
// When reloadIsRestart is true, treat a reload as a restart
1589+
if (reloadIsRestart && !fullRestart) {
1590+
fullRestart = true;
1591+
}
15661592
if (fullRestart && !supportsRestart) {
15671593
throw StateError('illegal restart');
15681594
}

0 commit comments

Comments
 (0)