diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart index dae77dace1b..a637edc5ac0 100644 --- a/packages/flutter_tools/lib/src/vmservice.dart +++ b/packages/flutter_tools/lib/src/vmservice.dart @@ -123,16 +123,9 @@ class VMService { final bool force = params.asMap['force'] ?? false; final bool pause = params.asMap['pause'] ?? false; - if (isolateId is! String || isolateId.isEmpty) { + if (isolateId.isEmpty) { throw rpc.RpcException.invalidParams('Invalid \'isolateId\': $isolateId'); } - if (force is! bool) { - throw rpc.RpcException.invalidParams('Invalid \'force\': $force'); - } - if (pause is! bool) { - throw rpc.RpcException.invalidParams('Invalid \'pause\': $pause'); - } - try { await reloadSources(isolateId, force: force, pause: pause); return {'type': 'Success'}; @@ -148,6 +141,46 @@ class VMService { 'service': 'reloadSources', 'alias': 'Flutter Tools', }); + + // Register a special method for hot UI. while this is implemented + // currently in the same way as hot reload, it leaves the tool free + // to change to a more efficient implementation in the future. + _peer.registerMethod('reloadMethod', (rpc.Parameters params) async { + final String isolateId = params['isolateId'].value; + final String libraryId = params['library'].value; + final String classId = params['class'].value; + final String methodId = params['method'].value; + final String methodBody = params['methodBody'].value; + + if (libraryId.isEmpty) { + throw rpc.RpcException.invalidParams('Invalid \'libraryId\': $libraryId'); + } + if (classId.isEmpty) { + throw rpc.RpcException.invalidParams('Invalid \'classId\': $classId'); + } + if (methodId.isEmpty) { + throw rpc.RpcException.invalidParams('Invalid \'methodId\': $methodId'); + } + if (methodBody.isEmpty) { + throw rpc.RpcException.invalidParams('Invalid \'methodBody\': $methodBody'); + } + + printTrace('reloadMethod not yet supported, falling back to hot reload'); + + try { + await reloadSources(isolateId); + return {'type': 'Success'}; + } on rpc.RpcException { + rethrow; + } catch (e, st) { + throw rpc.RpcException(rpc_error_code.SERVER_ERROR, + 'Error during Sources Reload: $e\n$st'); + } + }); + _peer.sendNotification('registerService', { + 'service': 'reloadMethod', + 'alias': 'Flutter Tools', + }); } if (restart != null) { diff --git a/packages/flutter_tools/test/general.shard/vmservice_test.dart b/packages/flutter_tools/test/general.shard/vmservice_test.dart index 437bad06cd1..842802e49f9 100644 --- a/packages/flutter_tools/test/general.shard/vmservice_test.dart +++ b/packages/flutter_tools/test/general.shard/vmservice_test.dart @@ -47,7 +47,7 @@ class MockPeer implements rpc.Peer { @override void registerMethod(String name, Function callback) { - // this does get called + registeredMethods.add(name); } @override @@ -57,6 +57,7 @@ class MockPeer implements rpc.Peer { } Map> sentNotifications = >{}; + List registeredMethods = []; bool isolatesEnabled = false; @@ -263,5 +264,18 @@ void main() { Logger: () => StdoutLogger(), Stdio: () => mockStdio, }); + + testUsingContext('registers hot UI method', () { + FakeAsync().run((FakeAsync time) { + final MockPeer mockPeer = MockPeer(); + Future reloadSources(String isolateId, { bool pause, bool force}) async {} + VMService(mockPeer, null, null, reloadSources, null, null); + + expect(mockPeer.registeredMethods, contains('reloadMethod')); + }); + }, overrides: { + Logger: () => StdoutLogger(), + Stdio: () => mockStdio, + }); }); }