mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[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](94cb81c552/src/debug/run_daemon_base.ts (L100)
) request via stdin/out to flutter_tools * flutter_tools then [calls the "hotRestart" service extension](f3978c7a46/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: https://github.com/dart-lang/webdev/pull/2388). Previously, we registered the "hotRestart" service extension on a client that was directly connected to the VmService. With https://github.com/dart-lang/webdev/pull/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.
This commit is contained in:
parent
89e538da28
commit
b487b8c19a
@ -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;
|
||||
@ -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;
|
||||
@ -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 {
|
||||
@ -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.
|
||||
@ -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);
|
||||
@ -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) {
|
||||
|
@ -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',
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user