Commit 55a374d4 authored by Devon Carew's avatar Devon Carew Committed by GitHub

Reload pause (#6459)

* add a pause parameter to the reload command

* encode OperationResult as json

* reverse isOk logic
parent a8bf594e
......@@ -72,6 +72,8 @@ class DaemonCommand extends FlutterCommand {
dynamic _jsonEncodeObject(dynamic object) {
if (object is Device)
return _deviceToMap(object);
if (object is OperationResult)
return _operationResultToMap(object);
return object;
}
......@@ -81,7 +83,7 @@ class DaemonCommand extends FlutterCommand {
}
}
typedef void DispatchComand(Map<String, dynamic> command);
typedef void DispatchCommand(Map<String, dynamic> command);
typedef Future<dynamic> CommandHandler(Map<String, dynamic> args);
......@@ -109,7 +111,7 @@ class Daemon {
AppDomain appDomain;
DeviceDomain deviceDomain;
final DispatchComand sendCommand;
final DispatchCommand sendCommand;
final DaemonCommand daemonCommand;
final NotifyingLogger notifyingLogger;
......@@ -381,16 +383,17 @@ class AppDomain extends Domain {
};
}
Future<bool> restart(Map<String, dynamic> args) async {
Future<OperationResult> restart(Map<String, dynamic> args) async {
String appId = _getStringArg(args, 'appId', required: true);
bool fullRestart = _getBoolArg(args, 'fullRestart') ?? false;
bool pauseAfterRestart = _getBoolArg(args, 'pause') ?? false;
AppInstance app = _getApp(appId);
if (app == null)
throw "app '$appId' not found";
return app._runInZone(this, () {
return app.restart(fullRestart: fullRestart);
return app.restart(fullRestart: fullRestart, pauseAfterRestart: pauseAfterRestart);
});
}
......@@ -567,11 +570,20 @@ Map<String, dynamic> _deviceToMap(Device device) {
};
}
Map<String, dynamic> _operationResultToMap(OperationResult result) {
return <String, dynamic>{
'code': result.code,
'message': result.message
};
}
dynamic _toJsonable(dynamic obj) {
if (obj is String || obj is int || obj is bool || obj is Map<dynamic, dynamic> || obj is List<dynamic> || obj == null)
return obj;
if (obj is Device)
return obj;
if (obj is OperationResult)
return obj;
return '$obj';
}
......@@ -615,8 +627,8 @@ class AppInstance {
_AppRunLogger _logger;
Future<bool> restart({ bool fullRestart: false }) {
return runner.restart(fullRestart: fullRestart);
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false }) {
return runner.restart(fullRestart: fullRestart, pauseAfterRestart: pauseAfterRestart);
}
Future<Null> stop() => runner.stop();
......
......@@ -452,16 +452,16 @@ class HotRunner extends ResidentRunner {
}
@override
Future<bool> restart({ bool fullRestart: false }) async {
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false }) async {
if (fullRestart) {
await _restartFromSources();
return true;
return OperationResult.ok;
} else {
return _reloadSources();
return _reloadSources(pause: pauseAfterRestart);
}
}
Future<bool> _reloadSources() async {
Future<OperationResult> _reloadSources({ bool pause: false }) async {
if (currentView.uiIsolate == null)
throw 'Application isolate not found';
FirstFrameTimer firstFrameTimer = new FirstFrameTimer(vmService);
......@@ -471,28 +471,31 @@ class HotRunner extends ResidentRunner {
Status reloadStatus = logger.startProgress('Performing hot reload...');
try {
Map<String, dynamic> reloadReport =
await currentView.uiIsolate.reloadSources();
await currentView.uiIsolate.reloadSources(pause: pause);
reloadStatus.stop(showElapsedTime: true);
if (!_printReloadReport(reloadReport)) {
// Reload failed.
flutterUsage.sendEvent('hot', 'reload-reject');
return false;
return new OperationResult(1, 'reload rejected');
} else {
flutterUsage.sendEvent('hot', 'reload');
}
} catch (error, st) {
int errorCode = error['code'];
String errorMessage = error['message'];
reloadStatus.stop(showElapsedTime: true);
if (errorCode == Isolate.kIsolateReloadBarred) {
printError('Unable to hot reload app due to an unrecoverable error in '
'the source code. Please address the error and then use '
'"R" to restart the app.');
flutterUsage.sendEvent('hot', 'reload-barred');
return false;
return new OperationResult(errorCode, errorMessage);
}
String errorMessage = error['message'];
reloadStatus.stop(showElapsedTime: true);
printError('Hot reload failed:\ncode = $errorCode\nmessage = $errorMessage\n$st');
return false;
return new OperationResult(errorCode, errorMessage);
}
// Reload the isolate.
await currentView.uiIsolate.reload();
......@@ -501,7 +504,7 @@ class HotRunner extends ResidentRunner {
if ((pauseEvent != null) && (pauseEvent.isPauseEvent)) {
// Isolate is paused. Stop here.
printTrace('Skipping reassemble because isolate is paused.');
return true;
return OperationResult.ok;
}
await _evictDirtyAssets();
printTrace('Reassembling application');
......@@ -510,7 +513,7 @@ class HotRunner extends ResidentRunner {
waitForFrame = (await currentView.uiIsolate.flutterReassemble() != null);
} catch (_) {
printError('Reassembling application failed.');
return false;
return new OperationResult(1, 'error reassembling application');
}
try {
/* ensure that a frame is scheduled */
......@@ -530,7 +533,7 @@ class HotRunner extends ResidentRunner {
}
flutterUsage.sendTiming('hot', 'reload', firstFrameTimer.elapsed);
}
return true;
return OperationResult.ok;
}
@override
......
......@@ -38,7 +38,7 @@ abstract class ResidentRunner {
bool shouldBuild: true
});
Future<bool> restart({ bool fullRestart: false });
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false });
Future<Null> stop() async {
await stopEchoingDeviceLog();
......@@ -209,6 +209,17 @@ abstract class ResidentRunner {
Future<Null> handleTerminalCommand(String code);
}
class OperationResult {
static final OperationResult ok = new OperationResult(0, '');
OperationResult(this.code, this.message);
final int code;
final String message;
bool get isOk => code == 0;
}
/// Given the value of the --target option, return the path of the Dart file
/// where the app's main function should be.
String findMainDartFile([String target]) {
......
......@@ -64,10 +64,10 @@ class RunAndStayResident extends ResidentRunner {
}
@override
Future<bool> restart({ bool fullRestart: false }) async {
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false }) async {
if (vmService == null) {
printError('Debugging is not enabled.');
return false;
return new OperationResult(1, 'debugging not enabled');
} else {
Status status = logger.startProgress('Re-starting application...');
......@@ -79,7 +79,7 @@ class RunAndStayResident extends ResidentRunner {
.first;
}
bool restartResult = await device.restartApp(
bool result = await device.restartApp(
_package,
_result,
mainPath: _mainPath,
......@@ -89,12 +89,11 @@ class RunAndStayResident extends ResidentRunner {
status.stop(showElapsedTime: true);
if (restartResult && extensionAddedEvent != null) {
// TODO(devoncarew): We should restore the route here.
if (result && extensionAddedEvent != null) {
await extensionAddedEvent;
}
return restartResult;
return result ? OperationResult.ok : new OperationResult(1, 'restart error');
}
}
......@@ -229,9 +228,9 @@ class RunAndStayResident extends ResidentRunner {
mainFile.writeAsBytesSync(mainFile.readAsBytesSync());
Stopwatch restartTime = new Stopwatch()..start();
bool restarted = await restart();
OperationResult result = await restart();
restartTime.stop();
writeRunBenchmarkFile(startTime, restarted ? restartTime : null);
writeRunBenchmarkFile(startTime, result.isOk ? restartTime : null);
await new Future<Null>.delayed(new Duration(seconds: 2));
stop();
}
......
......@@ -754,9 +754,11 @@ class Isolate extends ServiceObjectOwner {
static final int kIsolateReloadBarred = 1005;
Future<Map<String, dynamic>> reloadSources() async {
Future<Map<String, dynamic>> reloadSources({ bool pause: false }) async {
try {
Map<String, dynamic> response = await invokeRpcRaw('_reloadSources');
Map<String, dynamic> response = await invokeRpcRaw(
'_reloadSources', <String, dynamic>{ 'pause': pause }
);
return response;
} on rpc.RpcException catch(e) {
return new Future<Map<String, dynamic>>.error(<String, dynamic>{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment