send ext.flutter.debugDumpApp; ext.flutter.reassemble (#4810)
* send ext.flutter.debugDumpApp; ext.flutter.reassemble * expose debugDumpRenderTree
This commit is contained in:
parent
3cbb20d176
commit
ec752d813d
@ -56,6 +56,14 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding,
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
assert(() {
|
||||||
|
registerSignalServiceExtension(
|
||||||
|
name: 'debugDumpRenderTree',
|
||||||
|
callback: debugDumpRenderTree
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
assert(() {
|
assert(() {
|
||||||
// this service extension only works in checked mode
|
// this service extension only works in checked mode
|
||||||
registerBoolServiceExtension(
|
registerBoolServiceExtension(
|
||||||
|
@ -72,6 +72,11 @@ abstract class WidgetsBinding extends BindingBase implements GestureBinding, Ren
|
|||||||
void initServiceExtensions() {
|
void initServiceExtensions() {
|
||||||
super.initServiceExtensions();
|
super.initServiceExtensions();
|
||||||
|
|
||||||
|
registerSignalServiceExtension(
|
||||||
|
name: 'debugDumpApp',
|
||||||
|
callback: debugDumpApp
|
||||||
|
);
|
||||||
|
|
||||||
registerBoolServiceExtension(
|
registerBoolServiceExtension(
|
||||||
name: 'showPerformanceOverlay',
|
name: 'showPerformanceOverlay',
|
||||||
getter: () => WidgetsApp.showPerformanceOverlayOverride,
|
getter: () => WidgetsApp.showPerformanceOverlayOverride,
|
||||||
|
@ -191,6 +191,8 @@ abstract class Device {
|
|||||||
|
|
||||||
bool get supportsRestart => false;
|
bool get supportsRestart => false;
|
||||||
|
|
||||||
|
bool get restartSendsFrameworkInitEvent => true;
|
||||||
|
|
||||||
/// Restart the given app; the application will already have been launched with
|
/// Restart the given app; the application will already have been launched with
|
||||||
/// [startApp].
|
/// [startApp].
|
||||||
Future<bool> restartApp(
|
Future<bool> restartApp(
|
||||||
|
@ -578,6 +578,9 @@ class IOSSimulator extends Device {
|
|||||||
@override
|
@override
|
||||||
bool get supportsRestart => run.useReloadSources;
|
bool get supportsRestart => run.useReloadSources;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get restartSendsFrameworkInitEvent => false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> restartApp(
|
Future<bool> restartApp(
|
||||||
ApplicationPackage package,
|
ApplicationPackage package,
|
||||||
@ -587,7 +590,15 @@ class IOSSimulator extends Device {
|
|||||||
}) async {
|
}) async {
|
||||||
if (observatory.firstIsolateId == null)
|
if (observatory.firstIsolateId == null)
|
||||||
throw 'Application isolate not found';
|
throw 'Application isolate not found';
|
||||||
return observatory.reloadSources(observatory.firstIsolateId);
|
Event result = await observatory.reloadSources(observatory.firstIsolateId);
|
||||||
|
dynamic error = result.response['reloadError'];
|
||||||
|
if (error != null) {
|
||||||
|
printError('Error reloading application sources: $error');
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
await observatory.flutterReassemble(observatory.firstIsolateId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -9,8 +9,6 @@ import 'dart:io';
|
|||||||
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
|
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
|
||||||
import 'package:web_socket_channel/io.dart';
|
import 'package:web_socket_channel/io.dart';
|
||||||
|
|
||||||
import 'globals.dart';
|
|
||||||
|
|
||||||
class Observatory {
|
class Observatory {
|
||||||
Observatory._(this.peer, this.port) {
|
Observatory._(this.peer, this.port) {
|
||||||
peer.registerMethod('streamNotify', (rpc.Parameters event) {
|
peer.registerMethod('streamNotify', (rpc.Parameters event) {
|
||||||
@ -115,7 +113,7 @@ class Observatory {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> reloadSources(String isolateId) async {
|
Future<Response> reloadSources(String isolateId) async {
|
||||||
Completer<Event> whenIsolateReloads = new Completer<Event>();
|
Completer<Event> whenIsolateReloads = new Completer<Event>();
|
||||||
StreamSubscription<Event> sub = onIsolateEvent
|
StreamSubscription<Event> sub = onIsolateEvent
|
||||||
.where((Event event) => event.kind == 'IsolateReload')
|
.where((Event event) => event.kind == 'IsolateReload')
|
||||||
@ -123,11 +121,7 @@ class Observatory {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await sendRequest('_reloadSources', <String, dynamic>{ 'isolateId': isolateId });
|
await sendRequest('_reloadSources', <String, dynamic>{ 'isolateId': isolateId });
|
||||||
Event event = await whenIsolateReloads.future.timeout(new Duration(seconds: 20));
|
return await whenIsolateReloads.future.timeout(new Duration(seconds: 20));
|
||||||
dynamic error = event.response['reloadError'];
|
|
||||||
if (error != null)
|
|
||||||
printError('Error reloading application sources: $error');
|
|
||||||
return error == null;
|
|
||||||
} finally {
|
} finally {
|
||||||
await sub.cancel();
|
await sub.cancel();
|
||||||
}
|
}
|
||||||
@ -215,6 +209,25 @@ class Observatory {
|
|||||||
|
|
||||||
// Flutter extension methods.
|
// Flutter extension methods.
|
||||||
|
|
||||||
|
Future<Response> flutterDebugDumpApp(String isolateId) {
|
||||||
|
return peer.sendRequest('ext.flutter.debugDumpApp', <String, dynamic>{
|
||||||
|
'isolateId': isolateId
|
||||||
|
}).then((dynamic result) => new Response(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> flutterDebugDumpRenderTree(String isolateId) {
|
||||||
|
return peer.sendRequest('ext.flutter.debugDumpRenderTree', <String, dynamic>{
|
||||||
|
'isolateId': isolateId
|
||||||
|
}).then((dynamic result) => new Response(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Causes the application to pick up any changed code.
|
||||||
|
Future<Response> flutterReassemble(String isolateId) {
|
||||||
|
return peer.sendRequest('ext.flutter.reassemble', <String, dynamic>{
|
||||||
|
'isolateId': isolateId
|
||||||
|
}).then((dynamic result) => new Response(result));
|
||||||
|
}
|
||||||
|
|
||||||
Future<Response> flutterExit(String isolateId) {
|
Future<Response> flutterExit(String isolateId) {
|
||||||
return peer.sendRequest('ext.flutter.exit', <String, dynamic>{
|
return peer.sendRequest('ext.flutter.exit', <String, dynamic>{
|
||||||
'isolateId': isolateId
|
'isolateId': isolateId
|
||||||
|
@ -82,9 +82,13 @@ class RunAndStayResident {
|
|||||||
} else {
|
} else {
|
||||||
Status status = logger.startProgress('Re-starting application...');
|
Status status = logger.startProgress('Re-starting application...');
|
||||||
|
|
||||||
Future<Event> extensionAddedEvent = observatory.onExtensionEvent
|
Future<Event> extensionAddedEvent;
|
||||||
.where((Event event) => event.extensionKind == 'Flutter.FrameworkInitialization')
|
|
||||||
.first;
|
if (device.restartSendsFrameworkInitEvent) {
|
||||||
|
extensionAddedEvent = observatory.onExtensionEvent
|
||||||
|
.where((Event event) => event.extensionKind == 'Flutter.FrameworkInitialization')
|
||||||
|
.first;
|
||||||
|
}
|
||||||
|
|
||||||
bool restartResult = await device.restartApp(
|
bool restartResult = await device.restartApp(
|
||||||
_package,
|
_package,
|
||||||
@ -95,7 +99,7 @@ class RunAndStayResident {
|
|||||||
|
|
||||||
status.stop(showElapsedTime: true);
|
status.stop(showElapsedTime: true);
|
||||||
|
|
||||||
if (restartResult) {
|
if (restartResult && extensionAddedEvent != null) {
|
||||||
// TODO(devoncarew): We should restore the route here.
|
// TODO(devoncarew): We should restore the route here.
|
||||||
await extensionAddedEvent;
|
await extensionAddedEvent;
|
||||||
}
|
}
|
||||||
@ -255,6 +259,10 @@ class RunAndStayResident {
|
|||||||
_stopApp();
|
_stopApp();
|
||||||
} else if (useDevFS && lower == 'd') {
|
} else if (useDevFS && lower == 'd') {
|
||||||
_updateDevFS();
|
_updateDevFS();
|
||||||
|
} else if (lower == 'w') {
|
||||||
|
_debugDumpApp();
|
||||||
|
} else if (lower == 't') {
|
||||||
|
_debugDumpRenderTree();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -293,6 +301,14 @@ class RunAndStayResident {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _debugDumpApp() {
|
||||||
|
observatory.flutterDebugDumpApp(observatory.firstIsolateId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _debugDumpRenderTree() {
|
||||||
|
observatory.flutterDebugDumpRenderTree(observatory.firstIsolateId);
|
||||||
|
}
|
||||||
|
|
||||||
DevFS devFS;
|
DevFS devFS;
|
||||||
|
|
||||||
Future<Null> _updateDevFS() async {
|
Future<Null> _updateDevFS() async {
|
||||||
@ -361,6 +377,7 @@ class RunAndStayResident {
|
|||||||
void _printHelp() {
|
void _printHelp() {
|
||||||
String restartText = device.supportsRestart ? ', "r" or F5 to restart the app,' : '';
|
String restartText = device.supportsRestart ? ', "r" or F5 to restart the app,' : '';
|
||||||
printStatus('Type "h" or F1 for help$restartText and "q", F10, or ctrl-c to quit.');
|
printStatus('Type "h" or F1 for help$restartText and "q", F10, or ctrl-c to quit.');
|
||||||
|
printStatus('Type "w" to print the widget hierarchy of the app, and "t" for the render tree.');
|
||||||
|
|
||||||
if (useDevFS)
|
if (useDevFS)
|
||||||
printStatus('Type "d" to send modified project files to the the client\'s DevFS.');
|
printStatus('Type "d" to send modified project files to the the client\'s DevFS.');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user