Skip to content

Commit b487b8c

Browse files
authored
[flutter web] Listen for service extension registration events to determine hot-restart method name (#147897)
### Some background: * Flutter registers the hot-restart service extension for all devices **except** web devices. For web devices, DWDS registers the service extensions. * When a user is debugging their code via VS Code, the VS Code Dart extension [sends a hot-restart](https://github.com/Dart-Code/Dart-Code/blob/94cb81c5526adc7c8a1203cba201e8c1d99adf82/src/debug/run_daemon_base.ts#L100) request via stdin/out to flutter_tools * flutter_tools then [calls the "hotRestart" service extension](https://github.com/flutter/flutter/blob/f3978c7a46f083c8e91690b8b8be3e03b1e38155/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart#L447) (which, again, has been registered by DWDS) ### Why is this change necessary? In DWDS, we are changing how we register the "hotRestart" service extension (here is the PR for that: dart-lang/webdev#2388). Previously, we registered the "hotRestart" service extension on a client that was directly connected to the VmService. With dart-lang/webdev#2388, we will be registering the "hotRestart" service extension on a client that is connected to DDS. When a service extension is registered against DDS, DDS adds a prefix to the service extension method name (e.g. "hotRestart" becomes "s0.hotRestart"). It informs clients of the service extension name via `kServiceRegistered` events sent to the `Service` stream. Therefore, this change simply listens to those service extension registered events, and uses them to determine the "hotRestart" service extension's method name.
1 parent 89e538d commit b487b8c

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

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

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ class ResidentWebRunner extends ResidentRunner {
130130
FlutterDevice? get device => flutterDevices.first;
131131
final FlutterProject flutterProject;
132132

133+
// Mapping from service name to service method.
134+
final Map<String, String> _registeredMethodsForService = <String, String>{};
135+
133136
// Used with the new compiler to generate a bootstrap file containing plugins
134137
// and platform initialization.
135138
Directory? _generatedEntrypointDirectory;
@@ -156,6 +159,7 @@ class ResidentWebRunner extends ResidentRunner {
156159
ConnectionResult? _connectionResult;
157160
StreamSubscription<vmservice.Event>? _stdOutSub;
158161
StreamSubscription<vmservice.Event>? _stdErrSub;
162+
StreamSubscription<vmservice.Event>? _serviceSub;
159163
StreamSubscription<vmservice.Event>? _extensionEventSub;
160164
bool _exited = false;
161165
WipConnection? _wipConnection;
@@ -190,8 +194,10 @@ class ResidentWebRunner extends ResidentRunner {
190194
await residentDevtoolsHandler!.shutdown();
191195
await _stdOutSub?.cancel();
192196
await _stdErrSub?.cancel();
197+
await _serviceSub?.cancel();
193198
await _extensionEventSub?.cancel();
194199
await device!.device!.stopApp(null);
200+
_registeredMethodsForService.clear();
195201
try {
196202
_generatedEntrypointDirectory?.deleteSync(recursive: true);
197203
} on FileSystemException {
@@ -444,7 +450,11 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
444450
if (!deviceIsDebuggable) {
445451
_logger.printStatus('Recompile complete. Page requires refresh.');
446452
} else if (isRunningDebug) {
447-
await _vmService.service.callMethod('hotRestart');
453+
// If the hot-restart service extension method is registered, then use
454+
// it. Otherwise, default to calling "hotRestart" without a namespace.
455+
final String hotRestartMethod =
456+
_registeredMethodsForService['hotRestart'] ?? 'hotRestart';
457+
await _vmService.service.callMethod(hotRestartMethod);
448458
} else {
449459
// On non-debug builds, a hard refresh is required to ensure the
450460
// up to date sources are loaded.
@@ -615,17 +625,24 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
615625

616626
_stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
617627
_stdErrSub = _vmService.service.onStderrEvent.listen(onLogEvent);
628+
_serviceSub = _vmService.service.onServiceEvent.listen(_onServiceEvent);
618629
try {
619630
await _vmService.service.streamListen(vmservice.EventStreams.kStdout);
620631
} on vmservice.RPCError {
621632
// It is safe to ignore this error because we expect an error to be
622-
// thrown if we're not already subscribed.
633+
// thrown if we're already subscribed.
623634
}
624635
try {
625636
await _vmService.service.streamListen(vmservice.EventStreams.kStderr);
626637
} on vmservice.RPCError {
627638
// It is safe to ignore this error because we expect an error to be
628-
// thrown if we're not already subscribed.
639+
// thrown if we're already subscribed.
640+
}
641+
try {
642+
await _vmService.service.streamListen(vmservice.EventStreams.kService);
643+
} on vmservice.RPCError {
644+
// It is safe to ignore this error because we expect an error to be
645+
// thrown if we're already subscribed.
629646
}
630647
try {
631648
await _vmService.service.streamListen(vmservice.EventStreams.kIsolate);
@@ -703,6 +720,18 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
703720
await device!.exitApps();
704721
appFinished();
705722
}
723+
724+
void _onServiceEvent(vmservice.Event e) {
725+
if (e.kind == vmservice.EventKind.kServiceRegistered) {
726+
final String serviceName = e.service!;
727+
_registeredMethodsForService[serviceName] = e.method!;
728+
}
729+
730+
if (e.kind == vmservice.EventKind.kServiceUnregistered) {
731+
final String serviceName = e.service!;
732+
_registeredMethodsForService.remove(serviceName);
733+
}
734+
}
706735
}
707736

708737
Uri _httpUriFromWebsocketUri(Uri websocketUri) {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ const List<VmServiceExpectation> kAttachLogExpectations =
6262

6363
const List<VmServiceExpectation> kAttachIsolateExpectations =
6464
<VmServiceExpectation>[
65+
FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
66+
'streamId': 'Service',
67+
}),
6568
FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
6669
'streamId': 'Isolate',
6770
}),

0 commit comments

Comments
 (0)