mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
This reverts commit 8e2ca93f52
.
Fixes https://github.com/flutter/flutter/issues/23172
This commit is contained in:
parent
b357b55904
commit
bb0290a4dc
|
@ -93,7 +93,9 @@ abstract class BindingBase {
|
|||
/// Implementations of this method must call their superclass
|
||||
/// implementation.
|
||||
///
|
||||
/// {@macro flutter.foundation.bindingBase.registerServiceExtension}
|
||||
/// Service extensions are only exposed when the observatory is
|
||||
/// included in the build, which should only happen in checked mode
|
||||
/// and in profile mode.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
|
@ -102,23 +104,18 @@ abstract class BindingBase {
|
|||
@mustCallSuper
|
||||
void initServiceExtensions() {
|
||||
assert(!_debugServiceExtensionsRegistered);
|
||||
|
||||
assert(() {
|
||||
registerSignalServiceExtension(
|
||||
name: 'reassemble',
|
||||
callback: reassembleApplication,
|
||||
);
|
||||
return true;
|
||||
}());
|
||||
|
||||
const bool isReleaseMode = bool.fromEnvironment('dart.vm.product');
|
||||
if (!isReleaseMode) {
|
||||
registerSignalServiceExtension(
|
||||
name: 'exit',
|
||||
callback: _exitApplication,
|
||||
);
|
||||
}
|
||||
|
||||
registerSignalServiceExtension(
|
||||
name: 'reassemble',
|
||||
callback: reassembleApplication,
|
||||
);
|
||||
registerSignalServiceExtension(
|
||||
name: 'exit',
|
||||
callback: _exitApplication,
|
||||
);
|
||||
registerSignalServiceExtension(
|
||||
name: 'frameworkPresent',
|
||||
callback: () => Future<void>.value(),
|
||||
);
|
||||
assert(() {
|
||||
registerServiceExtension(
|
||||
name: 'platformOverride',
|
||||
|
@ -242,8 +239,6 @@ abstract class BindingBase {
|
|||
/// no value.
|
||||
///
|
||||
/// Calls the `callback` callback when the service extension is called.
|
||||
///
|
||||
/// {@macro flutter.foundation.bindingBase.registerServiceExtension}
|
||||
@protected
|
||||
void registerSignalServiceExtension({
|
||||
@required String name,
|
||||
|
@ -272,8 +267,6 @@ abstract class BindingBase {
|
|||
///
|
||||
/// Calls the `setter` callback with the new value when the
|
||||
/// service extension method is called with a new value.
|
||||
///
|
||||
/// {@macro flutter.foundation.bindingBase.registerServiceExtension}
|
||||
@protected
|
||||
void registerBoolServiceExtension({
|
||||
@required String name,
|
||||
|
@ -304,8 +297,6 @@ abstract class BindingBase {
|
|||
///
|
||||
/// Calls the `setter` callback with the new value when the
|
||||
/// service extension method is called with a new value.
|
||||
///
|
||||
/// {@macro flutter.foundation.bindingBase.registerServiceExtension}
|
||||
@protected
|
||||
void registerNumericServiceExtension({
|
||||
@required String name,
|
||||
|
@ -335,8 +326,6 @@ abstract class BindingBase {
|
|||
///
|
||||
/// Calls the `setter` callback with the new value when the
|
||||
/// service extension method is called with a new value.
|
||||
///
|
||||
/// {@macro flutter.foundation.bindingBase.registerServiceExtension}
|
||||
@protected
|
||||
void registerStringServiceExtension({
|
||||
@required String name,
|
||||
|
@ -356,51 +345,16 @@ abstract class BindingBase {
|
|||
);
|
||||
}
|
||||
|
||||
/// Registers a service extension method with the given name (full name
|
||||
/// "ext.flutter.name").
|
||||
///
|
||||
/// The given callback is called when the extension method is called. The
|
||||
/// callback must return a [Future] that either eventually completes to a
|
||||
/// return value in the form of a name/value map where the values can all be
|
||||
/// converted to JSON using `json.encode()` (see [JsonEncoder]), or fails. In
|
||||
/// case of failure, the failure is reported to the remote caller and is
|
||||
/// dumped to the logs.
|
||||
/// Registers a service extension method with the given name (full
|
||||
/// name "ext.flutter.name"). The given callback is called when the
|
||||
/// extension method is called. The callback must return a [Future]
|
||||
/// that either eventually completes to a return value in the form
|
||||
/// of a name/value map where the values can all be converted to
|
||||
/// JSON using `json.encode()` (see [JsonEncoder]), or fails. In case of failure, the
|
||||
/// failure is reported to the remote caller and is dumped to the
|
||||
/// logs.
|
||||
///
|
||||
/// The returned map will be mutated.
|
||||
///
|
||||
/// {@template flutter.foundation.bindingBase.registerServiceExtension}
|
||||
/// A registered service extension can only be activated if the vm-service
|
||||
/// is included in the build, which only happens in debug and profile mode.
|
||||
/// Although a service extension cannot be used in release mode its code may
|
||||
/// still be included in the Dart snapshot and blow up binary size if it is
|
||||
/// not wrapped in a guard that allows the tree shaker to remove it (see
|
||||
/// sample code below).
|
||||
///
|
||||
/// ## Sample Code
|
||||
///
|
||||
/// The following code registers a service extension that is only included in
|
||||
/// debug builds:
|
||||
///
|
||||
/// ```dart
|
||||
/// assert(() {
|
||||
/// // Register your service extension here.
|
||||
/// return true;
|
||||
/// }());
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
/// A service extension registered with the following code snippet is
|
||||
/// available in debug and profile mode:
|
||||
///
|
||||
/// ```dart
|
||||
/// if (!const bool.fromEnvironment('dart.vm.product')) {
|
||||
// // Register your service extension here.
|
||||
// }
|
||||
/// ```
|
||||
///
|
||||
/// Both guards ensure that Dart's tree shaker can remove the code for the
|
||||
/// service extension in release builds.
|
||||
/// {@endTemplate}
|
||||
@protected
|
||||
void registerServiceExtension({
|
||||
@required String name,
|
||||
|
|
|
@ -51,7 +51,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Semanti
|
|||
super.initServiceExtensions();
|
||||
|
||||
assert(() {
|
||||
// these service extensions only work in debug mode
|
||||
// these service extensions only work in checked mode
|
||||
registerBoolServiceExtension(
|
||||
name: 'debugPaint',
|
||||
getter: () async => debugPaintSizeEnabled,
|
||||
|
@ -60,17 +60,17 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Semanti
|
|||
return Future<void>.value();
|
||||
debugPaintSizeEnabled = value;
|
||||
return _forceRepaint();
|
||||
},
|
||||
}
|
||||
);
|
||||
registerBoolServiceExtension(
|
||||
name: 'debugPaintBaselinesEnabled',
|
||||
getter: () async => debugPaintBaselinesEnabled,
|
||||
setter: (bool value) {
|
||||
name: 'debugPaintBaselinesEnabled',
|
||||
getter: () async => debugPaintBaselinesEnabled,
|
||||
setter: (bool value) {
|
||||
if (debugPaintBaselinesEnabled == value)
|
||||
return Future<void>.value();
|
||||
debugPaintBaselinesEnabled = value;
|
||||
return _forceRepaint();
|
||||
},
|
||||
}
|
||||
);
|
||||
registerBoolServiceExtension(
|
||||
name: 'repaintRainbow',
|
||||
|
@ -83,43 +83,28 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Semanti
|
|||
return Future<void>.value();
|
||||
},
|
||||
);
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpLayerTree',
|
||||
callback: () {
|
||||
debugDumpLayerTree();
|
||||
return debugPrintDone;
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}());
|
||||
|
||||
const bool isReleaseMode = bool.fromEnvironment('dart.vm.product');
|
||||
if (!isReleaseMode) {
|
||||
// these service extensions work in debug or profile mode
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpRenderTree',
|
||||
callback: () {
|
||||
debugDumpRenderTree();
|
||||
return debugPrintDone;
|
||||
},
|
||||
);
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpRenderTree',
|
||||
callback: () { debugDumpRenderTree(); return debugPrintDone; }
|
||||
);
|
||||
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpSemanticsTreeInTraversalOrder',
|
||||
callback: () {
|
||||
debugDumpSemanticsTree(DebugSemanticsDumpOrder.traversalOrder);
|
||||
return debugPrintDone;
|
||||
},
|
||||
);
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpLayerTree',
|
||||
callback: () { debugDumpLayerTree(); return debugPrintDone; }
|
||||
);
|
||||
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpSemanticsTreeInInverseHitTestOrder',
|
||||
callback: () {
|
||||
debugDumpSemanticsTree(DebugSemanticsDumpOrder.inverseHitTest);
|
||||
return debugPrintDone;
|
||||
},
|
||||
);
|
||||
}
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpSemanticsTreeInTraversalOrder',
|
||||
callback: () { debugDumpSemanticsTree(DebugSemanticsDumpOrder.traversalOrder); return debugPrintDone; }
|
||||
);
|
||||
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpSemanticsTreeInInverseHitTestOrder',
|
||||
callback: () { debugDumpSemanticsTree(DebugSemanticsDumpOrder.inverseHitTest); return debugPrintDone; }
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a [RenderView] object to be the root of the
|
||||
|
|
|
@ -203,17 +203,13 @@ mixin SchedulerBinding on BindingBase, ServicesBinding {
|
|||
@override
|
||||
void initServiceExtensions() {
|
||||
super.initServiceExtensions();
|
||||
|
||||
const bool isReleaseMode = bool.fromEnvironment('dart.vm.product');
|
||||
if (!isReleaseMode) {
|
||||
registerNumericServiceExtension(
|
||||
name: 'timeDilation',
|
||||
getter: () async => timeDilation,
|
||||
setter: (double value) async {
|
||||
timeDilation = value;
|
||||
},
|
||||
);
|
||||
}
|
||||
registerNumericServiceExtension(
|
||||
name: 'timeDilation',
|
||||
getter: () async => timeDilation,
|
||||
setter: (double value) async {
|
||||
timeDilation = value;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// Whether the application is visible, and if so, whether it is currently
|
||||
|
|
|
@ -86,21 +86,17 @@ mixin ServicesBinding on BindingBase {
|
|||
@override
|
||||
void initServiceExtensions() {
|
||||
super.initServiceExtensions();
|
||||
|
||||
assert(() {
|
||||
registerStringServiceExtension(
|
||||
// ext.flutter.evict value=foo.png will cause foo.png to be evicted from
|
||||
// the rootBundle cache and cause the entire image cache to be cleared.
|
||||
// This is used by hot reload mode to clear out the cache of resources
|
||||
// that have changed.
|
||||
name: 'evict',
|
||||
getter: () async => '',
|
||||
setter: (String value) async {
|
||||
evict(value);
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}());
|
||||
registerStringServiceExtension(
|
||||
// ext.flutter.evict value=foo.png will cause foo.png to be evicted from
|
||||
// the rootBundle cache and cause the entire image cache to be cleared.
|
||||
// This is used by hot reload mode to clear out the cache of resources
|
||||
// that have changed.
|
||||
name: 'evict',
|
||||
getter: () async => '',
|
||||
setter: (String value) async {
|
||||
evict(value);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// Called in response to the `ext.flutter.evict` service extension.
|
||||
|
|
|
@ -265,41 +265,37 @@ mixin WidgetsBinding on BindingBase, SchedulerBinding, GestureBinding, RendererB
|
|||
void initServiceExtensions() {
|
||||
super.initServiceExtensions();
|
||||
|
||||
const bool isReleaseMode = bool.fromEnvironment('dart.vm.product');
|
||||
if (!isReleaseMode) {
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpApp',
|
||||
callback: () {
|
||||
debugDumpApp();
|
||||
return debugPrintDone;
|
||||
},
|
||||
);
|
||||
registerSignalServiceExtension(
|
||||
name: 'debugDumpApp',
|
||||
callback: () {
|
||||
debugDumpApp();
|
||||
return debugPrintDone;
|
||||
}
|
||||
);
|
||||
|
||||
registerBoolServiceExtension(
|
||||
name: 'showPerformanceOverlay',
|
||||
getter: () =>
|
||||
Future<bool>.value(WidgetsApp.showPerformanceOverlayOverride),
|
||||
setter: (bool value) {
|
||||
if (WidgetsApp.showPerformanceOverlayOverride == value)
|
||||
return Future<void>.value();
|
||||
WidgetsApp.showPerformanceOverlayOverride = value;
|
||||
return _forceRebuild();
|
||||
},
|
||||
);
|
||||
}
|
||||
registerBoolServiceExtension(
|
||||
name: 'showPerformanceOverlay',
|
||||
getter: () => Future<bool>.value(WidgetsApp.showPerformanceOverlayOverride),
|
||||
setter: (bool value) {
|
||||
if (WidgetsApp.showPerformanceOverlayOverride == value)
|
||||
return Future<void>.value();
|
||||
WidgetsApp.showPerformanceOverlayOverride = value;
|
||||
return _forceRebuild();
|
||||
}
|
||||
);
|
||||
|
||||
registerBoolServiceExtension(
|
||||
name: 'debugAllowBanner',
|
||||
getter: () => Future<bool>.value(WidgetsApp.debugAllowBannerOverride),
|
||||
setter: (bool value) {
|
||||
if (WidgetsApp.debugAllowBannerOverride == value)
|
||||
return Future<void>.value();
|
||||
WidgetsApp.debugAllowBannerOverride = value;
|
||||
return _forceRebuild();
|
||||
}
|
||||
);
|
||||
|
||||
assert(() {
|
||||
registerBoolServiceExtension(
|
||||
name: 'debugAllowBanner',
|
||||
getter: () => Future<bool>.value(WidgetsApp.debugAllowBannerOverride),
|
||||
setter: (bool value) {
|
||||
if (WidgetsApp.debugAllowBannerOverride == value)
|
||||
return Future<void>.value();
|
||||
WidgetsApp.debugAllowBannerOverride = value;
|
||||
return _forceRebuild();
|
||||
},
|
||||
);
|
||||
|
||||
// Expose the ability to send Widget rebuilds as [Timeline] events.
|
||||
registerBoolServiceExtension(
|
||||
name: 'profileWidgetBuilds',
|
||||
|
@ -307,13 +303,25 @@ mixin WidgetsBinding on BindingBase, SchedulerBinding, GestureBinding, RendererB
|
|||
setter: (bool value) async {
|
||||
if (debugProfileBuildsEnabled != value)
|
||||
debugProfileBuildsEnabled = value;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
WidgetInspectorService.instance.initServiceExtensions(registerServiceExtension);
|
||||
|
||||
return true;
|
||||
}());
|
||||
|
||||
// This service extension is deprecated and will be removed by 7/1/2018.
|
||||
// Use ext.flutter.inspector.show instead.
|
||||
registerBoolServiceExtension(
|
||||
name: 'debugWidgetInspector',
|
||||
getter: () async => WidgetsApp.debugShowWidgetInspectorOverride,
|
||||
setter: (bool value) {
|
||||
if (WidgetsApp.debugShowWidgetInspectorOverride == value)
|
||||
return Future<void>.value();
|
||||
WidgetsApp.debugShowWidgetInspectorOverride = value;
|
||||
return _forceRebuild();
|
||||
}
|
||||
);
|
||||
|
||||
WidgetInspectorService.instance.initServiceExtensions(registerServiceExtension);
|
||||
}
|
||||
|
||||
Future<void> _forceRebuild() {
|
||||
|
|
|
@ -917,11 +917,13 @@ mixin WidgetInspectorService {
|
|||
|
||||
/// Called to register service extensions.
|
||||
///
|
||||
/// Service extensions are only exposed when the observatory is
|
||||
/// included in the build, which should only happen in checked mode
|
||||
/// and in profile mode.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * <https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#rpcs-requests-and-responses>
|
||||
/// * [BindingBase.initServiceExtensions], which explains when service
|
||||
/// extensions can be used.
|
||||
void initServiceExtensions(
|
||||
_RegisterServiceExtensionCallback registerServiceExtensionCallback) {
|
||||
_registerServiceExtensionCallback = registerServiceExtensionCallback;
|
||||
|
@ -1021,33 +1023,36 @@ mixin WidgetInspectorService {
|
|||
name: 'isWidgetCreationTracked',
|
||||
callback: isWidgetCreationTracked,
|
||||
);
|
||||
registerServiceExtension(
|
||||
name: 'screenshot',
|
||||
callback: (Map<String, String> parameters) async {
|
||||
assert(parameters.containsKey('id'));
|
||||
assert(parameters.containsKey('width'));
|
||||
assert(parameters.containsKey('height'));
|
||||
assert(() {
|
||||
registerServiceExtension(
|
||||
name: 'screenshot',
|
||||
callback: (Map<String, String> parameters) async {
|
||||
assert(parameters.containsKey('id'));
|
||||
assert(parameters.containsKey('width'));
|
||||
assert(parameters.containsKey('height'));
|
||||
|
||||
final ui.Image image = await screenshot(
|
||||
toObject(parameters['id']),
|
||||
width: double.parse(parameters['width']),
|
||||
height: double.parse(parameters['height']),
|
||||
margin: parameters.containsKey('margin') ?
|
||||
double.parse(parameters['margin']) : 0.0,
|
||||
maxPixelRatio: parameters.containsKey('maxPixelRatio') ?
|
||||
double.parse(parameters['maxPixelRatio']) : 1.0,
|
||||
debugPaint: parameters['debugPaint'] == 'true',
|
||||
);
|
||||
if (image == null) {
|
||||
return <String, Object>{'result': null};
|
||||
}
|
||||
final ByteData byteData = await image.toByteData(format:ui.ImageByteFormat.png);
|
||||
final ui.Image image = await screenshot(
|
||||
toObject(parameters['id']),
|
||||
width: double.parse(parameters['width']),
|
||||
height: double.parse(parameters['height']),
|
||||
margin: parameters.containsKey('margin') ?
|
||||
double.parse(parameters['margin']) : 0.0,
|
||||
maxPixelRatio: parameters.containsKey('maxPixelRatio') ?
|
||||
double.parse(parameters['maxPixelRatio']) : 1.0,
|
||||
debugPaint: parameters['debugPaint'] == 'true',
|
||||
);
|
||||
if (image == null) {
|
||||
return <String, Object>{'result': null};
|
||||
}
|
||||
final ByteData byteData = await image.toByteData(format:ui.ImageByteFormat.png);
|
||||
|
||||
return <String, Object>{
|
||||
'result': base64.encoder.convert(Uint8List.view(byteData.buffer)),
|
||||
};
|
||||
},
|
||||
);
|
||||
return <String, Object>{
|
||||
'result': base64.encoder.convert(Uint8List.view(byteData.buffer)),
|
||||
};
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
|
||||
/// Clear all InspectorService object references.
|
||||
|
|
|
@ -359,6 +359,13 @@ void main() {
|
|||
expect(binding.extensions.containsKey('exit'), isTrue);
|
||||
});
|
||||
|
||||
test('Service extensions - frameworkPresent', () async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
result = await binding.testExtension('frameworkPresent', <String, String>{});
|
||||
expect(result, <String, String>{});
|
||||
});
|
||||
|
||||
test('Service extensions - platformOverride', () async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
|
@ -482,6 +489,29 @@ void main() {
|
|||
expect(binding.frameScheduled, isFalse);
|
||||
});
|
||||
|
||||
test('Service extensions - debugWidgetInspector', () async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
|
||||
result = await binding.testExtension('debugWidgetInspector', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
|
||||
result = await binding.testExtension('debugWidgetInspector', <String, String>{ 'enabled': 'true' });
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(WidgetsApp.debugShowWidgetInspectorOverride, true);
|
||||
result = await binding.testExtension('debugWidgetInspector', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(WidgetsApp.debugShowWidgetInspectorOverride, true);
|
||||
result = await binding.testExtension('debugWidgetInspector', <String, String>{ 'enabled': 'false' });
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
|
||||
result = await binding.testExtension('debugWidgetInspector', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
});
|
||||
|
||||
test('Service extensions - timeDilation', () async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
|
@ -511,7 +541,7 @@ void main() {
|
|||
|
||||
// If you add a service extension... TEST IT! :-)
|
||||
// ...then increment this number.
|
||||
expect(binding.extensions.length, 37);
|
||||
expect(binding.extensions.length, 39);
|
||||
|
||||
expect(console, isEmpty);
|
||||
debugPrint = debugPrintThrottled;
|
||||
|
|
|
@ -1296,6 +1296,10 @@ class Isolate extends ServiceObjectOwner {
|
|||
);
|
||||
}
|
||||
|
||||
Future<bool> flutterFrameworkPresent() async {
|
||||
return await invokeFlutterExtensionRpcRaw('ext.flutter.frameworkPresent') != null;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> uiWindowScheduleFrame() async {
|
||||
return await invokeFlutterExtensionRpcRaw('ext.ui.window.scheduleFrame');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue