From 33bfa6a7c5a77277e91b6207f30ffcb4ef8be1b6 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll <43759233+kenzieschmoll@users.noreply.github.com> Date: Thu, 17 Jan 2019 08:28:54 -0800 Subject: [PATCH] Register hotRestart service in flutter_tools. (#26669) * Register hot restart service in flutter_tools. --- .../lib/src/resident_runner.dart | 20 ++++++++--- packages/flutter_tools/lib/src/run_hot.dart | 12 +++++++ packages/flutter_tools/lib/src/vmservice.dart | 34 +++++++++++++++++-- .../flutter_tools/test/vmservice_test.dart | 2 +- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 82f5a0f07b9..d5928e325a9 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -68,7 +68,11 @@ class FlutterDevice { /// expressions requested during debugging of the application. /// This ensures that the reload process follows the normal orchestration of /// the Flutter Tools and not just the VM internal service. - Future _connect({ReloadSources reloadSources, CompileExpression compileExpression}) async { + Future _connect({ + ReloadSources reloadSources, + Restart restart, + CompileExpression compileExpression, + }) async { if (vmServices != null) return; final List localVmServices = List(observatoryUris.length); @@ -76,6 +80,7 @@ class FlutterDevice { printTrace('Connecting to service protocol: ${observatoryUris[i]}'); localVmServices[i] = await VMService.connect(observatoryUris[i], reloadSources: reloadSources, + restart: restart, compileExpression: compileExpression); printTrace('Successfully connected to service protocol: ${observatoryUris[i]}'); } @@ -677,14 +682,21 @@ abstract class ResidentRunner { /// If the [reloadSources] parameter is not null the 'reloadSources' service /// will be registered - Future connectToServiceProtocol({ReloadSources reloadSources, CompileExpression compileExpression}) async { + Future connectToServiceProtocol({ + ReloadSources reloadSources, + Restart restart, + CompileExpression compileExpression, + }) async { if (!debuggingOptions.debuggingEnabled) return Future.error('Error the service protocol is not enabled.'); bool viewFound = false; for (FlutterDevice device in flutterDevices) { - await device._connect(reloadSources: reloadSources, - compileExpression: compileExpression); + await device._connect( + reloadSources: reloadSources, + restart: restart, + compileExpression: compileExpression, + ); await device.getVMs(); await device.refreshViews(); if (device.views.isEmpty) diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index 08b93b45ae5..3127b37d86e 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -143,6 +143,17 @@ class HotRunner extends ResidentRunner { } } + Future _restartService({ bool pause = false }) async { + final OperationResult result = + await restart(fullRestart: true, pauseAfterRestart: pause); + if (!result.isOk) { + throw rpc.RpcException( + rpc_error_code.INTERNAL_ERROR, + 'Unable to restart', + ); + } + } + Future _compileExpressionService(String isolateId, String expression, List definitions, List typeDefinitions, String libraryUri, String klass, bool isStatic, @@ -168,6 +179,7 @@ class HotRunner extends ResidentRunner { try { await connectToServiceProtocol( reloadSources: _reloadSourcesService, + restart: _restartService, compileExpression: _compileExpressionService, ); } catch (error) { diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart index 83f837a6824..48a8c8a059e 100644 --- a/packages/flutter_tools/lib/src/vmservice.dart +++ b/packages/flutter_tools/lib/src/vmservice.dart @@ -43,6 +43,8 @@ typedef ReloadSources = Future Function( bool pause, }); +typedef Restart = Future Function({ bool pause }); + typedef CompileExpression = Future Function( String isolateId, String expression, @@ -111,6 +113,7 @@ class VMService { this.wsAddress, this._requestTimeout, ReloadSources reloadSources, + Restart restart, CompileExpression compileExpression, ) { _vm = VM._empty(this); @@ -148,7 +151,33 @@ class VMService { // have no effect _peer.sendNotification('_registerService', { 'service': 'reloadSources', - 'alias': 'Flutter Tools' + 'alias': 'Flutter Tools', + }); + } + + if (restart != null) { + _peer.registerMethod('hotRestart', (rpc.Parameters params) async { + final bool pause = params.asMap['pause'] ?? false; + + if (pause is! bool) + throw rpc.RpcException.invalidParams('Invalid \'pause\': $pause'); + + try { + await restart(pause: pause); + return {'type': 'Success'}; + } on rpc.RpcException { + rethrow; + } catch (e, st) { + throw rpc.RpcException(rpc_error_code.SERVER_ERROR, + 'Error during Hot Restart: $e\n$st'); + } + }); + + // If the Flutter Engine doesn't support service registration this will + // have no effect + _peer.sendNotification('_registerService', { + 'service': 'hotRestart', + 'alias': 'Flutter Tools', }); } @@ -231,12 +260,13 @@ class VMService { Uri httpUri, { Duration requestTimeout = kDefaultRequestTimeout, ReloadSources reloadSources, + Restart restart, CompileExpression compileExpression, }) async { final Uri wsUri = httpUri.replace(scheme: 'ws', path: fs.path.join(httpUri.path, 'ws')); final StreamChannel channel = await _openChannel(wsUri); final rpc.Peer peer = rpc.Peer.withoutJson(jsonDocument.bind(channel)); - final VMService service = VMService(peer, httpUri, wsUri, requestTimeout, reloadSources, compileExpression); + final VMService service = VMService(peer, httpUri, wsUri, requestTimeout, reloadSources, restart, compileExpression); // This call is to ensure we are able to establish a connection instead of // keeping on trucking and failing farther down the process. await service._sendRequest('getVersion', const {}); diff --git a/packages/flutter_tools/test/vmservice_test.dart b/packages/flutter_tools/test/vmservice_test.dart index 6f056ce59be..04217643fdf 100644 --- a/packages/flutter_tools/test/vmservice_test.dart +++ b/packages/flutter_tools/test/vmservice_test.dart @@ -167,7 +167,7 @@ void main() { bool done = false; final MockPeer mockPeer = MockPeer(); expect(mockPeer.returnedFromSendRequest, 0); - final VMService vmService = VMService(mockPeer, null, null, const Duration(seconds: 1), null, null); + final VMService vmService = VMService(mockPeer, null, null, const Duration(seconds: 1), null, null, null); vmService.getVM().then((void value) { done = true; }); expect(done, isFalse); expect(mockPeer.returnedFromSendRequest, 0);