Skip to content

Commit 1590543

Browse files
jyameobkonyi
andauthored
Make device debuggable if useDwdsWebSocketConnection is true and added simple test case (flutter#171648)
- Make device debuggable if useDwdsWebSocketConnection is true - This change is needed to support hot reload on web-server devices over websocket-based DWDS. - Added simple test case to test hot reload over websocket related to dart-lang/webdev#2605, dart-lang/webdev#2645 and dart-lang/webdev#2646 --------- Co-authored-by: Ben Konyi <[email protected]>
1 parent d77a962 commit 1590543

File tree

5 files changed

+308
-92
lines changed

5 files changed

+308
-92
lines changed

packages/flutter_tools/lib/src/isolated/resident_web_runner.dart

Lines changed: 100 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,17 @@ class ResidentWebRunner extends ResidentRunner {
158158
@override
159159
bool get debuggingEnabled => isRunningDebug && deviceIsDebuggable;
160160

161-
/// WebServer device is debuggable when running with --start-paused.
162-
bool get deviceIsDebuggable => device!.device is! WebServerDevice || debuggingOptions.startPaused;
161+
/// Device is debuggable if not a WebServer device, or if running with
162+
/// --start-paused or using DWDS WebSocket connection (WebServer device).
163+
bool get deviceIsDebuggable =>
164+
device!.device is! WebServerDevice ||
165+
debuggingOptions.startPaused ||
166+
_useDwdsWebSocketConnection;
167+
168+
bool get _useDwdsWebSocketConnection {
169+
final DevFS? devFS = device?.devFS;
170+
return devFS is WebDevFS && devFS.useDwdsWebSocketConnection;
171+
}
163172

164173
@override
165174
// Web uses a different plugin registry.
@@ -790,86 +799,102 @@ class ResidentWebRunner extends ResidentRunner {
790799
Uri? websocketUri;
791800
if (supportsServiceProtocol) {
792801
assert(connectDebug != null);
793-
_connectionResult = await connectDebug;
794-
unawaited(_connectionResult!.debugConnection!.onDone.whenComplete(_cleanupAndExit));
802+
unawaited(
803+
connectDebug!.then((connectionResult) async {
804+
_connectionResult = connectionResult;
805+
unawaited(_connectionResult!.debugConnection!.onDone.whenComplete(_cleanupAndExit));
795806

796-
void onLogEvent(vmservice.Event event) {
797-
final String message = processVmServiceMessage(event);
798-
_logger.printStatus(message);
799-
}
807+
void onLogEvent(vmservice.Event event) {
808+
final String message = processVmServiceMessage(event);
809+
_logger.printStatus(message);
810+
}
800811

801-
// This flag is needed to manage breakpoints properly.
802-
if (debuggingOptions.startPaused && debuggingOptions.debuggingEnabled) {
803-
try {
804-
final vmservice.Response result = await _vmService.service.setFlag(
805-
'pause_isolates_on_start',
806-
'true',
807-
);
808-
if (result is! vmservice.Success) {
809-
_logger.printError('setFlag failure: $result');
812+
// This flag is needed to manage breakpoints properly.
813+
if (debuggingOptions.startPaused && debuggingOptions.debuggingEnabled) {
814+
try {
815+
final vmservice.Response result = await _vmService.service.setFlag(
816+
'pause_isolates_on_start',
817+
'true',
818+
);
819+
if (result is! vmservice.Success) {
820+
_logger.printError('setFlag failure: $result');
821+
}
822+
} on Exception catch (e) {
823+
_logger.printError(
824+
'Failed to set pause_isolates_on_start=true, proceeding. '
825+
'Error: $e',
826+
);
827+
}
810828
}
811-
} on Exception catch (e) {
812-
_logger.printError(
813-
'Failed to set pause_isolates_on_start=true, proceeding. '
814-
'Error: $e',
815-
);
816-
}
817-
}
818829

819-
_stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
820-
_stdErrSub = _vmService.service.onStderrEvent.listen(onLogEvent);
821-
_serviceSub = _vmService.service.onServiceEvent.listen(_onServiceEvent);
822-
try {
823-
await _vmService.service.streamListen(vmservice.EventStreams.kStdout);
824-
} on vmservice.RPCError {
825-
// It is safe to ignore this error because we expect an error to be
826-
// thrown if we're already subscribed.
827-
}
828-
try {
829-
await _vmService.service.streamListen(vmservice.EventStreams.kStderr);
830-
} on vmservice.RPCError {
831-
// It is safe to ignore this error because we expect an error to be
832-
// thrown if we're already subscribed.
833-
}
834-
try {
835-
await _vmService.service.streamListen(vmservice.EventStreams.kService);
836-
} on vmservice.RPCError {
837-
// It is safe to ignore this error because we expect an error to be
838-
// thrown if we're already subscribed.
839-
}
840-
try {
841-
await _vmService.service.streamListen(vmservice.EventStreams.kIsolate);
842-
} on vmservice.RPCError {
843-
// It is safe to ignore this error because we expect an error to be
844-
// thrown if we're not already subscribed.
845-
}
846-
await setUpVmService(
847-
reloadSources: (String isolateId, {bool? force, bool? pause}) async {
848-
await restart(pause: pause);
849-
},
850-
device: device!.device,
851-
flutterProject: flutterProject,
852-
printStructuredErrorLogMethod: printStructuredErrorLog,
853-
vmService: _vmService.service,
854-
);
830+
_stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
831+
_stdErrSub = _vmService.service.onStderrEvent.listen(onLogEvent);
832+
_serviceSub = _vmService.service.onServiceEvent.listen(_onServiceEvent);
833+
try {
834+
await _vmService.service.streamListen(vmservice.EventStreams.kStdout);
835+
} on vmservice.RPCError {
836+
// It is safe to ignore this error because we expect an error to be
837+
// thrown if we're already subscribed.
838+
}
839+
try {
840+
await _vmService.service.streamListen(vmservice.EventStreams.kStderr);
841+
} on vmservice.RPCError {
842+
// It is safe to ignore this error because we expect an error to be
843+
// thrown if we're already subscribed.
844+
}
845+
try {
846+
await _vmService.service.streamListen(vmservice.EventStreams.kService);
847+
} on vmservice.RPCError {
848+
// It is safe to ignore this error because we expect an error to be
849+
// thrown if we're already subscribed.
850+
}
851+
try {
852+
await _vmService.service.streamListen(vmservice.EventStreams.kIsolate);
853+
} on vmservice.RPCError {
854+
// It is safe to ignore this error because we expect an error to be
855+
// thrown if we're not already subscribed.
856+
}
857+
await setUpVmService(
858+
reloadSources: (String isolateId, {bool? force, bool? pause}) async {
859+
await restart(pause: pause);
860+
},
861+
device: device!.device,
862+
flutterProject: flutterProject,
863+
printStructuredErrorLogMethod: printStructuredErrorLog,
864+
vmService: _vmService.service,
865+
);
855866

856-
websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
857-
device!.vmService = _vmService;
867+
websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
868+
device!.vmService = _vmService;
858869

859-
// Run main immediately if the app is not started paused or if there
860-
// is no debugger attached. Otherwise, runMain when a resume event
861-
// is received.
862-
if (!debuggingOptions.startPaused || !supportsServiceProtocol) {
863-
_connectionResult!.appConnection!.runMain();
864-
} else {
865-
late StreamSubscription<void> resumeSub;
866-
resumeSub = _vmService.service.onDebugEvent.listen((vmservice.Event event) {
867-
if (event.type == vmservice.EventKind.kResume) {
870+
// Run main immediately if the app is not started paused or if there
871+
// is no debugger attached. Otherwise, runMain when a resume event
872+
// is received.
873+
if (!debuggingOptions.startPaused || !supportsServiceProtocol) {
868874
_connectionResult!.appConnection!.runMain();
869-
resumeSub.cancel();
875+
} else {
876+
late StreamSubscription<void> resumeSub;
877+
resumeSub = _vmService.service.onDebugEvent.listen((vmservice.Event event) {
878+
if (event.type == vmservice.EventKind.kResume) {
879+
_connectionResult!.appConnection!.runMain();
880+
resumeSub.cancel();
881+
}
882+
});
870883
}
871-
});
872-
}
884+
885+
if (websocketUri != null) {
886+
if (debuggingOptions.vmserviceOutFile != null) {
887+
_fileSystem.file(debuggingOptions.vmserviceOutFile)
888+
..createSync(recursive: true)
889+
..writeAsStringSync(websocketUri.toString());
890+
}
891+
_logger.printStatus('Debug service listening on $websocketUri');
892+
}
893+
connectionInfoCompleter?.complete(DebugConnectionInfo(wsUri: websocketUri));
894+
}),
895+
);
896+
} else {
897+
connectionInfoCompleter?.complete(DebugConnectionInfo());
873898
}
874899
// TODO(bkonyi): remove when ready to serve DevTools from DDS.
875900
if (debuggingOptions.enableDevTools) {
@@ -881,16 +906,8 @@ class ResidentWebRunner extends ResidentRunner {
881906
),
882907
);
883908
}
884-
if (websocketUri != null) {
885-
if (debuggingOptions.vmserviceOutFile != null) {
886-
_fileSystem.file(debuggingOptions.vmserviceOutFile)
887-
..createSync(recursive: true)
888-
..writeAsStringSync(websocketUri.toString());
889-
}
890-
_logger.printStatus('Debug service listening on $websocketUri');
891-
}
909+
892910
appStartedCompleter?.complete();
893-
connectionInfoCompleter?.complete(DebugConnectionInfo(wsUri: websocketUri));
894911
if (stayResident) {
895912
await waitForAppToFinish();
896913
} else {

packages/flutter_tools/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies:
1313
archive: 3.6.1
1414
args: 2.7.0
1515
dds: 5.0.3
16-
dwds: 24.4.0
16+
dwds: 24.4.1
1717
code_builder: 4.10.1
1818
collection: 1.19.1
1919
completion: 1.0.2
@@ -126,4 +126,4 @@ dev_dependencies:
126126
dartdoc:
127127
# Exclude this package from the hosted API docs.
128128
nodoc: true
129-
# PUBSPEC CHECKSUM: kav93d
129+
# PUBSPEC CHECKSUM: 932agm

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1665,7 +1665,9 @@ flutter:
16651665
mainLibName: 'my_app',
16661666
packages: <String, String>{'path_provider_linux': '../../path_provider_linux'},
16671667
);
1668-
expect(await residentWebRunner.run(), 0);
1668+
final connectionInfoCompleter = Completer<DebugConnectionInfo>();
1669+
expect(await residentWebRunner.run(connectionInfoCompleter: connectionInfoCompleter), 0);
1670+
await connectionInfoCompleter.future;
16691671
final File generatedLocalizationsFile = globals.fs
16701672
.directory('lib')
16711673
.childDirectory('l10n')
@@ -2055,6 +2057,9 @@ class FakeWebDevFS extends Fake implements WebDevFS {
20552057
@override
20562058
PackageConfig? lastPackageConfig = PackageConfig.empty;
20572059

2060+
@override
2061+
var useDwdsWebSocketConnection = false;
2062+
20582063
@override
20592064
Future<Uri> create() async {
20602065
return baseUri;

0 commit comments

Comments
 (0)