Skip to content

Commit

Permalink
[flutter web] Listen for service extension registration events to det…
Browse files Browse the repository at this point in the history
…ermine 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.
  • Loading branch information
elliette committed May 7, 2024
1 parent 89e538d commit b487b8c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
35 changes: 32 additions & 3 deletions packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ class ResidentWebRunner extends ResidentRunner {
FlutterDevice? get device => flutterDevices.first;
final FlutterProject flutterProject;

// Mapping from service name to service method.
final Map<String, String> _registeredMethodsForService = <String, String>{};

// Used with the new compiler to generate a bootstrap file containing plugins
// and platform initialization.
Directory? _generatedEntrypointDirectory;
Expand All @@ -156,6 +159,7 @@ class ResidentWebRunner extends ResidentRunner {
ConnectionResult? _connectionResult;
StreamSubscription<vmservice.Event>? _stdOutSub;
StreamSubscription<vmservice.Event>? _stdErrSub;
StreamSubscription<vmservice.Event>? _serviceSub;
StreamSubscription<vmservice.Event>? _extensionEventSub;
bool _exited = false;
WipConnection? _wipConnection;
Expand Down Expand Up @@ -190,8 +194,10 @@ class ResidentWebRunner extends ResidentRunner {
await residentDevtoolsHandler!.shutdown();
await _stdOutSub?.cancel();
await _stdErrSub?.cancel();
await _serviceSub?.cancel();
await _extensionEventSub?.cancel();
await device!.device!.stopApp(null);
_registeredMethodsForService.clear();
try {
_generatedEntrypointDirectory?.deleteSync(recursive: true);
} on FileSystemException {
Expand Down Expand Up @@ -444,7 +450,11 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
if (!deviceIsDebuggable) {
_logger.printStatus('Recompile complete. Page requires refresh.');
} else if (isRunningDebug) {
await _vmService.service.callMethod('hotRestart');
// If the hot-restart service extension method is registered, then use
// it. Otherwise, default to calling "hotRestart" without a namespace.
final String hotRestartMethod =
_registeredMethodsForService['hotRestart'] ?? 'hotRestart';
await _vmService.service.callMethod(hotRestartMethod);
} else {
// On non-debug builds, a hard refresh is required to ensure the
// up to date sources are loaded.
Expand Down Expand Up @@ -615,17 +625,24 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).

_stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
_stdErrSub = _vmService.service.onStderrEvent.listen(onLogEvent);
_serviceSub = _vmService.service.onServiceEvent.listen(_onServiceEvent);
try {
await _vmService.service.streamListen(vmservice.EventStreams.kStdout);
} on vmservice.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're not already subscribed.
// thrown if we're already subscribed.
}
try {
await _vmService.service.streamListen(vmservice.EventStreams.kStderr);
} on vmservice.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're not already subscribed.
// thrown if we're already subscribed.
}
try {
await _vmService.service.streamListen(vmservice.EventStreams.kService);
} on vmservice.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're already subscribed.
}
try {
await _vmService.service.streamListen(vmservice.EventStreams.kIsolate);
Expand Down Expand Up @@ -703,6 +720,18 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
await device!.exitApps();
appFinished();
}

void _onServiceEvent(vmservice.Event e) {
if (e.kind == vmservice.EventKind.kServiceRegistered) {
final String serviceName = e.service!;
_registeredMethodsForService[serviceName] = e.method!;
}

if (e.kind == vmservice.EventKind.kServiceUnregistered) {
final String serviceName = e.service!;
_registeredMethodsForService.remove(serviceName);
}
}
}

Uri _httpUriFromWebsocketUri(Uri websocketUri) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ const List<VmServiceExpectation> kAttachLogExpectations =

const List<VmServiceExpectation> kAttachIsolateExpectations =
<VmServiceExpectation>[
FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Service',
}),
FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Isolate',
}),
Expand Down

0 comments on commit b487b8c

Please sign in to comment.