diff --git a/packages/flutter/lib/src/foundation/binding.dart b/packages/flutter/lib/src/foundation/binding.dart index 83204bd57b..e898b808e5 100644 --- a/packages/flutter/lib/src/foundation/binding.dart +++ b/packages/flutter/lib/src/foundation/binding.dart @@ -168,13 +168,6 @@ abstract class BindingBase { static Type? _debugInitializedType; static bool _debugServiceExtensionsRegistered = false; - /// Additional configuration used by the framework during hot reload. - /// - /// See also: - /// - /// * [DebugReassembleConfig], which describes the configuration. - static DebugReassembleConfig? debugReassembleConfig; - /// Deprecated. Will be removed in a future version of Flutter. /// /// This property has been deprecated to prepare for Flutter's upcoming @@ -989,23 +982,3 @@ abstract class BindingBase { Future _exitApplication() async { exit(0); } - -/// Additional configuration used for hot reload reassemble optimizations. -/// -/// Do not extend, implement, or mixin this class. This may only be instantiated -/// in debug mode. -class DebugReassembleConfig { - /// Create a new [DebugReassembleConfig]. - /// - /// Throws a [FlutterError] if this is called in profile or release mode. - DebugReassembleConfig({ - this.widgetName, - }) { - if (!kDebugMode) { - throw FlutterError('Cannot instantiate DebugReassembleConfig in profile or release mode.'); - } - } - - /// The name of the widget that was modified, or `null` if the change was elsewhere. - final String? widgetName; -} diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 8b14588b78..5d1552ec3c 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -603,18 +603,16 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture @override Future performReassemble() async { await super.performReassemble(); - if (BindingBase.debugReassembleConfig?.widgetName == null) { - if (!kReleaseMode) { - FlutterTimeline.startSync('Preparing Hot Reload (layout)'); + if (!kReleaseMode) { + FlutterTimeline.startSync('Preparing Hot Reload (layout)'); + } + try { + for (final RenderView renderView in renderViews) { + renderView.reassemble(); } - try { - for (final RenderView renderView in renderViews) { - renderView.reassemble(); - } - } finally { - if (!kReleaseMode) { - FlutterTimeline.finishSync(); - } + } finally { + if (!kReleaseMode) { + FlutterTimeline.finishSync(); } } scheduleWarmUpFrame(); diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart index 900d34fe77..ca8347edbe 100644 --- a/packages/flutter/lib/src/widgets/binding.dart +++ b/packages/flutter/lib/src/widgets/binding.dart @@ -505,23 +505,6 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB }, ); - registerServiceExtension( - name: WidgetsServiceExtensions.fastReassemble.name, - callback: (Map params) async { - // This mirrors the implementation of the 'reassemble' callback registration - // in lib/src/foundation/binding.dart, but with the extra binding config used - // to skip some reassemble work. - final String? className = params['className'] as String?; - BindingBase.debugReassembleConfig = DebugReassembleConfig(widgetName: className); - try { - await reassembleApplication(); - } finally { - BindingBase.debugReassembleConfig = null; - } - return {'type': 'Success'}; - }, - ); - // Expose the ability to send Widget rebuilds as [Timeline] events. registerBoolServiceExtension( name: WidgetsServiceExtensions.profileWidgetBuilds.name, @@ -560,7 +543,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB Future _forceRebuild() { if (rootElement != null) { - buildOwner!.reassemble(rootElement!, null); + buildOwner!.reassemble(rootElement!); return endOfFrame; } return Future.value(); @@ -1090,7 +1073,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB }()); if (rootElement != null) { - buildOwner!.reassemble(rootElement!, BindingBase.debugReassembleConfig); + buildOwner!.reassemble(rootElement!); } return super.performReassemble(); } diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 6c5c231a34..c1c45fcbfa 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -3252,14 +3252,13 @@ class BuildOwner { /// changed implementations. /// /// This is expensive and should not be called except during development. - void reassemble(Element root, DebugReassembleConfig? reassembleConfig) { + void reassemble(Element root) { if (!kReleaseMode) { FlutterTimeline.startSync('Preparing Hot Reload (widgets)'); } try { assert(root._parent == null); assert(root.owner == this); - root._debugReassembleConfig = reassembleConfig; root.reassemble(); } finally { if (!kReleaseMode) { @@ -3374,7 +3373,6 @@ abstract class Element extends DiagnosticableTree implements BuildContext { } Element? _parent; - DebugReassembleConfig? _debugReassembleConfig; _NotificationNode? _notificationTree; /// Compare two widgets for equality. @@ -3526,15 +3524,10 @@ abstract class Element extends DiagnosticableTree implements BuildContext { @mustCallSuper @protected void reassemble() { - if (_debugShouldReassemble(_debugReassembleConfig, _widget)) { - markNeedsBuild(); - _debugReassembleConfig = null; - } + markNeedsBuild(); visitChildren((Element child) { - child._debugReassembleConfig = _debugReassembleConfig; child.reassemble(); }); - _debugReassembleConfig = null; } bool _debugIsInScope(Element target) { @@ -5585,9 +5578,7 @@ class StatefulElement extends ComponentElement { @override void reassemble() { - if (_debugShouldReassemble(_debugReassembleConfig, _widget)) { - state.reassemble(); - } + state.reassemble(); super.reassemble(); } @@ -6952,9 +6943,3 @@ class _NullWidget extends Widget { @override Element createElement() => throw UnimplementedError(); } - -// Whether a [DebugReassembleConfig] indicates that an element holding [widget] can skip -// a reassemble. -bool _debugShouldReassemble(DebugReassembleConfig? config, Widget? widget) { - return config == null || config.widgetName == null || widget?.runtimeType.toString() == config.widgetName; -} diff --git a/packages/flutter/lib/src/widgets/widget_inspector.dart b/packages/flutter/lib/src/widgets/widget_inspector.dart index 7c56bed8ec..5873aaab7e 100644 --- a/packages/flutter/lib/src/widgets/widget_inspector.dart +++ b/packages/flutter/lib/src/widgets/widget_inspector.dart @@ -970,7 +970,7 @@ mixin WidgetInspectorService { Future forceRebuild() { final WidgetsBinding binding = WidgetsBinding.instance; if (binding.rootElement != null) { - binding.buildOwner!.reassemble(binding.rootElement!, null); + binding.buildOwner!.reassemble(binding.rootElement!); return binding.endOfFrame; } return Future.value(); diff --git a/packages/flutter/test/foundation/service_extensions_test.dart b/packages/flutter/test/foundation/service_extensions_test.dart index b97a70a74a..7b6d36a835 100644 --- a/packages/flutter/test/foundation/service_extensions_test.dart +++ b/packages/flutter/test/foundation/service_extensions_test.dart @@ -116,6 +116,7 @@ Future> hasReassemble(Future> pendingR } void main() { + final Set testedExtensions = {}; // Add the name of an extension to this set in the test where it is tested. final List console = []; late PipelineOwner owner; @@ -153,6 +154,9 @@ void main() { expect(binding.frameScheduled, isFalse); + testedExtensions.add(WidgetsServiceExtensions.didSendFirstFrameEvent.name); + testedExtensions.add(WidgetsServiceExtensions.didSendFirstFrameRasterizedEvent.name); + expect(debugPrint, equals(debugPrintThrottled)); debugPrint = (String? message, { int? wrapWidth }) { console.add(message); @@ -162,12 +166,13 @@ void main() { tearDownAll(() async { // See widget_inspector_test.dart for tests of the ext.flutter.inspector // service extensions included in this count. - int widgetInspectorExtensionCount = 20; + int widgetInspectorExtensionCount = 28; if (WidgetInspectorService.instance.isWidgetCreationTracked()) { // Some inspector extensions are only exposed if widget creation locations // are tracked. widgetInspectorExtensionCount += 2; } + expect(binding.extensions.keys.where((String name) => name.startsWith('inspector.')), hasLength(widgetInspectorExtensionCount)); // The following service extensions are disabled in web: // 1. exit @@ -175,12 +180,13 @@ void main() { const int disabledExtensions = kIsWeb ? 2 : 0; // The expected number of registered service extensions in the Flutter - // framework, excluding any that are for the widget inspector - // (see widget_inspector_test.dart for tests of the ext.flutter.inspector - // service extensions). - const int serviceExtensionCount = 38; + // framework, excluding any that are for the widget inspector (see + // widget_inspector_test.dart for tests of the ext.flutter.inspector service + // extensions). Any test counted here must be tested in this file! + const int serviceExtensionCount = 29; expect(binding.extensions.length, serviceExtensionCount + widgetInspectorExtensionCount - disabledExtensions); + expect(testedExtensions, hasLength(serviceExtensionCount)); expect(console, isEmpty); debugPrint = debugPrintThrottled; @@ -213,6 +219,8 @@ void main() { expect(result, {'enabled': 'true'}); expect(WidgetsApp.debugAllowBannerOverride, true); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(WidgetsServiceExtensions.debugAllowBanner.name); }); test('Service extensions - debugDumpApp', () async { @@ -221,6 +229,8 @@ void main() { expect(result, { 'data': matches('TestServiceExtensionsBinding - DEBUG MODE\n'), }); + + testedExtensions.add(WidgetsServiceExtensions.debugDumpApp.name); }); test('Service extensions - debugDumpFocusTree', () async { @@ -234,6 +244,8 @@ void main() { r'$', ), }); + + testedExtensions.add(WidgetsServiceExtensions.debugDumpFocusTree.name); }); test('Service extensions - debugDumpRenderTree', () async { @@ -251,6 +263,8 @@ void main() { r'$', ), }); + + testedExtensions.add(RenderingServiceExtensions.debugDumpRenderTree.name); }); test('Service extensions - debugDumpLayerTree', () async { @@ -274,6 +288,8 @@ void main() { r'$', ), }); + + testedExtensions.add(RenderingServiceExtensions.debugDumpLayerTree.name); }); test('Service extensions - debugDumpSemanticsTreeInTraversalOrder', () async { @@ -288,6 +304,8 @@ void main() { r'To generate semantics, try turning on an assistive technology \(like VoiceOver or TalkBack\) on your device.' ) }); + + testedExtensions.add(RenderingServiceExtensions.debugDumpSemanticsTreeInTraversalOrder.name); }); test('Service extensions - debugDumpSemanticsTreeInInverseHitTestOrder', () async { @@ -302,10 +320,12 @@ void main() { r'To generate semantics, try turning on an assistive technology \(like VoiceOver or TalkBack\) on your device.' ) }); + + testedExtensions.add(RenderingServiceExtensions.debugDumpSemanticsTreeInInverseHitTestOrder.name); }); test('Service extensions - debugPaint', () async { - final Iterable> extensionChangedEvents = binding.getServiceExtensionStateChangedEvents('ext.flutter.debugPaint'); + final Iterable> extensionChangedEvents = binding.getServiceExtensionStateChangedEvents('ext.flutter.${RenderingServiceExtensions.debugPaint.name}'); Map extensionChangedEvent; Map result; Future> pendingResult; @@ -357,6 +377,8 @@ void main() { expect(debugPaintSizeEnabled, false); expect(extensionChangedEvents.length, 2); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.debugPaint.name); }); test('Service extensions - debugPaintBaselinesEnabled', () async { @@ -399,6 +421,8 @@ void main() { expect(result, {'enabled': 'false'}); expect(debugPaintBaselinesEnabled, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.debugPaintBaselinesEnabled.name); }); test('Service extensions - invertOversizedImages', () async { @@ -445,6 +469,8 @@ void main() { expect(result, {'enabled': 'false'}); expect(debugInvertOversizedImages, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.invertOversizedImages.name); }); test('Service extensions - profileWidgetBuilds', () async { @@ -474,6 +500,8 @@ void main() { expect(debugProfileBuildsEnabled, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(WidgetsServiceExtensions.profileWidgetBuilds.name); }); test('Service extensions - profileUserWidgetBuilds', () async { @@ -503,6 +531,8 @@ void main() { expect(debugProfileBuildsEnabledUserWidgets, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(WidgetsServiceExtensions.profileUserWidgetBuilds.name); }); test('Service extensions - profileRenderObjectPaints', () async { @@ -532,6 +562,8 @@ void main() { expect(debugProfilePaintsEnabled, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.profileRenderObjectPaints.name); }); test('Service extensions - profileRenderObjectLayouts', () async { @@ -561,6 +593,8 @@ void main() { expect(debugProfileLayoutsEnabled, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.profileRenderObjectLayouts.name); }); test('Service extensions - evict', () async { @@ -596,12 +630,16 @@ void main() { expect(data, isFalse); expect(completed, isTrue); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', null); + + testedExtensions.add(ServicesServiceExtensions.evict.name); }); test('Service extensions - exit', () async { // no test for _calling_ 'exit', because that should terminate the process! // Not expecting extension to be available for web platform. expect(binding.extensions.containsKey(FoundationServiceExtensions.exit.name), !isBrowser); + + testedExtensions.add(FoundationServiceExtensions.exit.name); }); test('Service extensions - platformOverride', () async { @@ -688,6 +726,8 @@ void main() { expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride'); expect(extensionChangedEvent['value'], 'android'); binding.reassembled = 0; + + testedExtensions.add(FoundationServiceExtensions.platformOverride.name); }); test('Service extensions - repaintRainbow', () async { @@ -731,6 +771,8 @@ void main() { expect(result, {'enabled': 'false'}); expect(debugRepaintRainbowEnabled, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.repaintRainbow.name); }); test('Service extensions - debugDisableClipLayers', () async { @@ -773,6 +815,8 @@ void main() { expect(result, {'enabled': 'false'}); expect(debugDisableClipLayers, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.debugDisableClipLayers.name); }); test('Service extensions - debugDisablePhysicalShapeLayers', () async { @@ -815,6 +859,8 @@ void main() { expect(result, {'enabled': 'false'}); expect(debugDisablePhysicalShapeLayers, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.debugDisablePhysicalShapeLayers.name); }); test('Service extensions - debugDisableOpacityLayers', () async { @@ -857,6 +903,8 @@ void main() { expect(result, {'enabled': 'false'}); expect(debugDisableOpacityLayers, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(RenderingServiceExtensions.debugDisableOpacityLayers.name); }); test('Service extensions - reassemble', () async { @@ -880,6 +928,8 @@ void main() { expect(result, {}); expect(binding.reassembled, 1); binding.reassembled = 0; + + testedExtensions.add(FoundationServiceExtensions.reassemble.name); }); test('Service extensions - showPerformanceOverlay', () async { @@ -888,6 +938,7 @@ void main() { // The performance overlay service extension is disabled on the web. if (kIsWeb) { expect(binding.extensions.containsKey(WidgetsServiceExtensions.showPerformanceOverlay.name), isFalse); + testedExtensions.add(WidgetsServiceExtensions.showPerformanceOverlay.name); return; } @@ -909,6 +960,8 @@ void main() { expect(result, {'enabled': 'false'}); expect(WidgetsApp.showPerformanceOverlayOverride, false); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(WidgetsServiceExtensions.showPerformanceOverlay.name); }); test('Service extensions - timeDilation', () async { @@ -945,6 +998,8 @@ void main() { expect(timeDilation, 1.0); expect(extensionChangedEvents.length, 2); expect(binding.frameScheduled, isFalse); + + testedExtensions.add(SchedulerServiceExtensions.timeDilation.name); }); test('Service extensions - brightnessOverride', () async { @@ -953,6 +1008,8 @@ void main() { final String brightnessValue = result['value'] as String; expect(brightnessValue, 'Brightness.light'); + + testedExtensions.add(FoundationServiceExtensions.brightnessOverride.name); }); test('Service extensions - activeDevToolsServerAddress', () async { @@ -966,6 +1023,8 @@ void main() { result = await binding.testExtension(FoundationServiceExtensions.activeDevToolsServerAddress.name, {'value': 'http://127.0.0.1:9102'}); serverAddress = result['value'] as String; expect(serverAddress, 'http://127.0.0.1:9102'); + + testedExtensions.add(FoundationServiceExtensions.activeDevToolsServerAddress.name); }); test('Service extensions - connectedVmServiceUri', () async { @@ -979,5 +1038,7 @@ void main() { result = await binding.testExtension(FoundationServiceExtensions.connectedVmServiceUri.name, {'value': 'http://127.0.0.1:54000/kMUMseKAnog=/'}); serverAddress = result['value'] as String; expect(serverAddress, 'http://127.0.0.1:54000/kMUMseKAnog=/'); + + testedExtensions.add(FoundationServiceExtensions.connectedVmServiceUri.name); }); } diff --git a/packages/flutter/test/widgets/fast_reassemble_test.dart b/packages/flutter/test/widgets/fast_reassemble_test.dart deleted file mode 100644 index 1269992c11..0000000000 --- a/packages/flutter/test/widgets/fast_reassemble_test.dart +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - testWidgets('reassemble with a className only marks subtrees from the first matching element as dirty', (WidgetTester tester) async { - await tester.pumpWidget( - const Foo(Bar(Fizz(SizedBox()))) - ); - - expect(Foo.count, 0); - expect(Bar.count, 0); - expect(Fizz.count, 0); - - DebugReassembleConfig config = DebugReassembleConfig(widgetName: 'Bar'); - WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config); - - expect(Foo.count, 0); - expect(Bar.count, 1); - expect(Fizz.count, 1); - - config = DebugReassembleConfig(widgetName: 'Fizz'); - WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config); - - expect(Foo.count, 0); - expect(Bar.count, 1); - expect(Fizz.count, 2); - - config = DebugReassembleConfig(widgetName: 'NoMatch'); - WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config); - - expect(Foo.count, 0); - expect(Bar.count, 1); - expect(Fizz.count, 2); - - config = DebugReassembleConfig(); - WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config); - - expect(Foo.count, 1); - expect(Bar.count, 2); - expect(Fizz.count, 3); - - WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, null); - - expect(Foo.count, 2); - expect(Bar.count, 3); - expect(Fizz.count, 4); - }); -} - -class Foo extends StatefulWidget { - const Foo(this.child, {super.key}); - - final Widget child; - static int count = 0; - - @override - State createState() => _FooState(); -} - -class _FooState extends State { - @override - void reassemble() { - Foo.count += 1; - super.reassemble(); - } - - @override - Widget build(BuildContext context) { - return widget.child; - } -} - - -class Bar extends StatefulWidget { - const Bar(this.child, {super.key}); - - final Widget child; - static int count = 0; - - @override - State createState() => _BarState(); -} - -class _BarState extends State { - @override - void reassemble() { - Bar.count += 1; - super.reassemble(); - } - - @override - Widget build(BuildContext context) { - return widget.child; - } -} - -class Fizz extends StatefulWidget { - const Fizz(this.child, {super.key}); - - final Widget child; - static int count = 0; - - @override - State createState() => _FizzState(); -} - -class _FizzState extends State { - @override - void reassemble() { - Fizz.count += 1; - super.reassemble(); - } - - @override - Widget build(BuildContext context) { - return widget.child; - } -} diff --git a/packages/flutter/test/widgets/widget_inspector_test_utils.dart b/packages/flutter/test/widgets/widget_inspector_test_utils.dart index 843b76e3e8..19370bfa77 100644 --- a/packages/flutter/test/widgets/widget_inspector_test_utils.dart +++ b/packages/flutter/test/widgets/widget_inspector_test_utils.dart @@ -115,7 +115,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { final WidgetsBinding binding = WidgetsBinding.instance; if (binding.rootElement != null) { - binding.buildOwner!.reassemble(binding.rootElement!, null); + binding.buildOwner!.reassemble(binding.rootElement!); } } diff --git a/packages/flutter_tools/lib/src/bundle.dart b/packages/flutter_tools/lib/src/bundle.dart index 6eed94ee93..ef7bfdbddb 100644 --- a/packages/flutter_tools/lib/src/bundle.dart +++ b/packages/flutter_tools/lib/src/bundle.dart @@ -33,7 +33,7 @@ String getDefaultCachedKernelPath({ }) { final StringBuffer buffer = StringBuffer(); final List cacheFrontEndOptions = extraFrontEndOptions.toList() - ..removeWhere((String arg) => arg.startsWith('--enable-experiment=') || arg == '--flutter-widget-cache'); + ..removeWhere((String arg) => arg.startsWith('--enable-experiment=')); buffer.writeAll(dartDefines); buffer.writeAll(cacheFrontEndOptions); String buildPrefix = ''; diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart index 4136071ee2..93e0f3a363 100644 --- a/packages/flutter_tools/lib/src/devfs.dart +++ b/packages/flutter_tools/lib/src/devfs.dart @@ -401,7 +401,6 @@ class UpdateFSReport { bool success = false, int invalidatedSourcesCount = 0, int syncedBytes = 0, - this.fastReassembleClassName, int scannedSourcesCount = 0, Duration compileDuration = Duration.zero, Duration transferDuration = Duration.zero, @@ -423,7 +422,6 @@ class UpdateFSReport { Duration get findInvalidatedDuration => _findInvalidatedDuration; bool _success; - String? fastReassembleClassName; int _invalidatedSourcesCount; int _syncedBytes; int _scannedSourcesCount; @@ -435,7 +433,6 @@ class UpdateFSReport { if (!report._success) { _success = false; } - fastReassembleClassName ??= report.fastReassembleClassName; _invalidatedSourcesCount += report._invalidatedSourcesCount; _syncedBytes += report._syncedBytes; _scannedSourcesCount += report._scannedSourcesCount; @@ -495,7 +492,6 @@ class DevFS { DateTime? lastCompiled; DateTime? _previousCompiled; PackageConfig? lastPackageConfig; - File? _widgetCacheOutputFile; Uri? _baseUri; Uri? get baseUri => _baseUri; @@ -555,22 +551,6 @@ class DevFS { lastCompiled = _previousCompiled; } - - /// If the build method of a single widget was modified, return the widget name. - /// - /// If any other changes were made, or there is an error scanning the file, - /// return `null`. - String? _checkIfSingleWidgetReloadApplied() { - final File? widgetCacheOutputFile = _widgetCacheOutputFile; - if (widgetCacheOutputFile != null && widgetCacheOutputFile.existsSync()) { - final String widget = widgetCacheOutputFile.readAsStringSync().trim(); - if (widget.isNotEmpty) { - return widget; - } - } - return null; - } - /// Updates files on the device. /// /// Returns the number of bytes synced. @@ -596,7 +576,6 @@ class DevFS { final DateTime candidateCompileTime = DateTime.now(); didUpdateFontManifest = false; lastPackageConfig = packageConfig; - _widgetCacheOutputFile = _fileSystem.file('$dillOutputPath.incremental.dill.widget_cache'); // Update modified files final Map dirtyEntries = {}; @@ -741,7 +720,6 @@ class DevFS { success: true, syncedBytes: syncedBytes, invalidatedSourcesCount: invalidatedFiles.length, - fastReassembleClassName: _checkIfSingleWidgetReloadApplied(), compileDuration: compileTimer.elapsed, transferDuration: transferTimer.elapsed, ); diff --git a/packages/flutter_tools/lib/src/features.dart b/packages/flutter_tools/lib/src/features.dart index 97be411a54..2c5a1b3c10 100644 --- a/packages/flutter_tools/lib/src/features.dart +++ b/packages/flutter_tools/lib/src/features.dart @@ -44,9 +44,6 @@ abstract class FeatureFlags { /// Whether custom devices are enabled. bool get areCustomDevicesEnabled => false; - /// Whether fast single widget reloads are enabled. - bool get isSingleWidgetReloadEnabled => false; - /// Whether WebAssembly compilation for Flutter Web is enabled. bool get isFlutterWebWasmEnabled => false; @@ -62,7 +59,6 @@ const List allFeatures = [ flutterLinuxDesktopFeature, flutterMacOSDesktopFeature, flutterWindowsDesktopFeature, - singleWidgetReload, flutterAndroidFeature, flutterIOSFeature, flutterFuchsiaFeature, @@ -140,20 +136,6 @@ const Feature flutterCustomDevicesFeature = Feature( ), ); -/// The fast hot reload feature for https://github.com/flutter/flutter/issues/61407. -const Feature singleWidgetReload = Feature( - name: 'Hot reload optimization for changes to class body of a single widget', - configSetting: 'single-widget-reload-optimization', - environmentOverride: 'FLUTTER_SINGLE_WIDGET_RELOAD', - master: FeatureChannelSetting( - available: true, - enabledByDefault: true, - ), - beta: FeatureChannelSetting( - available: true, - ), -); - /// Enabling WebAssembly compilation from `flutter build web` const Feature flutterWebWasm = Feature( name: 'WebAssembly compilation from flutter build web', diff --git a/packages/flutter_tools/lib/src/flutter_features.dart b/packages/flutter_tools/lib/src/flutter_features.dart index 672a81855d..e4102bdfe8 100644 --- a/packages/flutter_tools/lib/src/flutter_features.dart +++ b/packages/flutter_tools/lib/src/flutter_features.dart @@ -44,9 +44,6 @@ class FlutterFeatureFlags implements FeatureFlags { @override bool get areCustomDevicesEnabled => isEnabled(flutterCustomDevicesFeature); - @override - bool get isSingleWidgetReloadEnabled => isEnabled(singleWidgetReload); - @override bool get isFlutterWebWasmEnabled => isEnabled(flutterWebWasm); diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart index a44b803320..2c81eb2c91 100644 --- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart @@ -446,7 +446,6 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). fullRestart: true, reason: reason, overallTimeInMs: elapsed.inMilliseconds, - fastReassemble: false, ).send(); } return OperationResult.ok; diff --git a/packages/flutter_tools/lib/src/reporting/custom_dimensions.dart b/packages/flutter_tools/lib/src/reporting/custom_dimensions.dart index 9a31fcd575..4ee8c9e342 100644 --- a/packages/flutter_tools/lib/src/reporting/custom_dimensions.dart +++ b/packages/flutter_tools/lib/src/reporting/custom_dimensions.dart @@ -58,7 +58,6 @@ class CustomDimensions { this.commandRunAndroidEmbeddingVersion, this.commandPackagesAndroidEmbeddingVersion, this.nullSafety, - this.fastReassemble, this.nullSafeMigratedLibraries, this.nullSafeTotalLibraries, this.hotEventCompileTimeInMs, @@ -118,17 +117,17 @@ class CustomDimensions { final String? commandRunAndroidEmbeddingVersion; // cd45 final String? commandPackagesAndroidEmbeddingVersion; // cd46 final bool? nullSafety; // cd47 - final bool? fastReassemble; // cd48 + // cd48 was fastReassemble but that feature was removed final int? nullSafeMigratedLibraries; // cd49 final int? nullSafeTotalLibraries; // cd50 - final int? hotEventCompileTimeInMs; // cd 51 - final int? hotEventFindInvalidatedTimeInMs; // cd 52 - final int? hotEventScannedSourcesCount; // cd 53 - final int? hotEventReassembleTimeInMs; // cd 54 - final int? hotEventReloadVMTimeInMs; // cd 55 - final bool? commandRunEnableImpeller; // cd 56 - final String? commandRunIOSInterfaceType; // cd 57 - final bool? commandRunIsTest; // cd 58 + final int? hotEventCompileTimeInMs; // cd51 + final int? hotEventFindInvalidatedTimeInMs; // cd52 + final int? hotEventScannedSourcesCount; // cd53 + final int? hotEventReassembleTimeInMs; // cd54 + final int? hotEventReloadVMTimeInMs; // cd55 + final bool? commandRunEnableImpeller; // cd56 + final String? commandRunIOSInterfaceType; // cd57 + final bool? commandRunIsTest; // cd58 /// Convert to a map that will be used to upload to the analytics backend. Map toMap() => { @@ -179,7 +178,6 @@ class CustomDimensions { if (commandRunAndroidEmbeddingVersion != null) CustomDimensionsEnum.commandRunAndroidEmbeddingVersion.cdKey: commandRunAndroidEmbeddingVersion.toString(), if (commandPackagesAndroidEmbeddingVersion != null) CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion.cdKey: commandPackagesAndroidEmbeddingVersion.toString(), if (nullSafety != null) CustomDimensionsEnum.nullSafety.cdKey: nullSafety.toString(), - if (fastReassemble != null) CustomDimensionsEnum.fastReassemble.cdKey: fastReassemble.toString(), if (nullSafeMigratedLibraries != null) CustomDimensionsEnum.nullSafeMigratedLibraries.cdKey: nullSafeMigratedLibraries.toString(), if (nullSafeTotalLibraries != null) CustomDimensionsEnum.nullSafeTotalLibraries.cdKey: nullSafeTotalLibraries.toString(), if (hotEventCompileTimeInMs != null) CustomDimensionsEnum.hotEventCompileTimeInMs.cdKey: hotEventCompileTimeInMs.toString(), @@ -247,7 +245,6 @@ class CustomDimensions { commandRunAndroidEmbeddingVersion: other.commandRunAndroidEmbeddingVersion ?? commandRunAndroidEmbeddingVersion, commandPackagesAndroidEmbeddingVersion: other.commandPackagesAndroidEmbeddingVersion ?? commandPackagesAndroidEmbeddingVersion, nullSafety: other.nullSafety ?? nullSafety, - fastReassemble: other.fastReassemble ?? fastReassemble, nullSafeMigratedLibraries: other.nullSafeMigratedLibraries ?? nullSafeMigratedLibraries, nullSafeTotalLibraries: other.nullSafeTotalLibraries ?? nullSafeTotalLibraries, hotEventCompileTimeInMs: other.hotEventCompileTimeInMs ?? hotEventCompileTimeInMs, @@ -309,7 +306,6 @@ class CustomDimensions { commandRunAndroidEmbeddingVersion: _extractString(map, CustomDimensionsEnum.commandRunAndroidEmbeddingVersion), commandPackagesAndroidEmbeddingVersion: _extractString(map, CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion), nullSafety: _extractBool(map, CustomDimensionsEnum.nullSafety), - fastReassemble: _extractBool(map, CustomDimensionsEnum.fastReassemble), nullSafeMigratedLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeMigratedLibraries), nullSafeTotalLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeTotalLibraries), hotEventCompileTimeInMs: _extractInt(map, CustomDimensionsEnum.hotEventCompileTimeInMs), @@ -397,7 +393,7 @@ enum CustomDimensionsEnum { commandRunAndroidEmbeddingVersion, // cd45 commandPackagesAndroidEmbeddingVersion, // cd46 nullSafety, // cd47 - fastReassemble, // cd48 + obsolete1, // cd48 (was fastReassemble) nullSafeMigratedLibraries, // cd49 nullSafeTotalLibraries, // cd50 hotEventCompileTimeInMs, // cd51 diff --git a/packages/flutter_tools/lib/src/reporting/events.dart b/packages/flutter_tools/lib/src/reporting/events.dart index ae0028f214..ec3933ed5d 100644 --- a/packages/flutter_tools/lib/src/reporting/events.dart +++ b/packages/flutter_tools/lib/src/reporting/events.dart @@ -39,7 +39,6 @@ class HotEvent extends UsageEvent { required this.sdkName, required this.emulator, required this.fullRestart, - required this.fastReassemble, this.reason, this.finalLibraryCount, this.syncedLibraryCount, @@ -63,7 +62,6 @@ class HotEvent extends UsageEvent { final String sdkName; final bool emulator; final bool fullRestart; - final bool fastReassemble; final int? finalLibraryCount; final int? syncedLibraryCount; final int? syncedClassesCount; @@ -94,7 +92,6 @@ class HotEvent extends UsageEvent { hotEventInvalidatedSourcesCount: invalidatedSourcesCount, hotEventTransferTimeInMs: transferTimeInMs, hotEventOverallTimeInMs: overallTimeInMs, - fastReassemble: fastReassemble, hotEventCompileTimeInMs: compileTimeInMs, hotEventFindInvalidatedTimeInMs: findInvalidatedTimeInMs, hotEventScannedSourcesCount: scannedSourcesCount, diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 1d55e0d567..a3de310f5a 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -34,7 +34,6 @@ import 'compile.dart'; import 'convert.dart'; import 'devfs.dart'; import 'device.dart'; -import 'features.dart'; import 'globals.dart' as globals; import 'ios/application_package.dart'; import 'ios/devices.dart'; @@ -169,11 +168,8 @@ class FlutterDevice { platform: platform, ); } else { - // The flutter-widget-cache feature only applies to run mode. List extraFrontEndOptions = buildInfo.extraFrontEndOptions; extraFrontEndOptions = [ - if (featureFlags.isSingleWidgetReloadEnabled) - '--flutter-widget-cache', '--enable-experiment=alternative-invalidation-strategy', ...extraFrontEndOptions, ]; diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index d687012fde..fdebdcab73 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -20,7 +20,6 @@ import 'convert.dart'; import 'dart/package_map.dart'; import 'devfs.dart'; import 'device.dart'; -import 'features.dart'; import 'globals.dart' as globals; import 'project.dart'; import 'reporting/reporting.dart'; @@ -415,7 +414,6 @@ class HotRunner extends ResidentRunner { sdkName: _sdkName!, emulator: _emulator!, fullRestart: false, - fastReassemble: false, overallTimeInMs: appStartedTimer.elapsed.inMilliseconds, compileTimeInMs: totalCompileTime.inMilliseconds, transferTimeInMs: totalLaunchAppTime.inMilliseconds, @@ -802,7 +800,6 @@ class HotRunner extends ResidentRunner { emulator: emulator!, fullRestart: true, reason: reason, - fastReassemble: false, overallTimeInMs: restartTimer.elapsed.inMilliseconds, syncedBytes: result.updateFSReport?.syncedBytes, invalidatedSourcesCount: result.updateFSReport?.invalidatedSourcesCount, @@ -828,7 +825,6 @@ class HotRunner extends ResidentRunner { emulator: emulator!, fullRestart: true, reason: reason, - fastReassemble: false, ).send(); } status?.cancel(); @@ -878,7 +874,6 @@ class HotRunner extends ResidentRunner { emulator: emulator!, fullRestart: false, reason: reason, - fastReassemble: false, ).send(); } else { HotEvent('exception', @@ -887,7 +882,6 @@ class HotRunner extends ResidentRunner { emulator: emulator!, fullRestart: false, reason: reason, - fastReassemble: false, ).send(); } return OperationResult(errorCode, errorMessage, fatal: true); @@ -971,7 +965,6 @@ class HotRunner extends ResidentRunner { viewCache, onSlow, reloadMessage, - updatedDevFS.fastReassembleClassName, ); shouldReportReloadTime = reassembleResult.shouldReportReloadTime; if (reassembleResult.reassembleViews.isEmpty) { @@ -1005,7 +998,6 @@ class HotRunner extends ResidentRunner { syncedBytes: updatedDevFS.syncedBytes, invalidatedSourcesCount: updatedDevFS.invalidatedSourcesCount, transferTimeInMs: updatedDevFS.transferDuration.inMilliseconds, - fastReassemble: featureFlags.isSingleWidgetReloadEnabled && updatedDevFS.fastReassembleClassName != null, compileTimeInMs: updatedDevFS.compileDuration.inMilliseconds, findInvalidatedTimeInMs: updatedDevFS.findInvalidatedDuration.inMilliseconds, scannedSourcesCount: updatedDevFS.scannedSourcesCount, @@ -1225,7 +1217,6 @@ Future defaultReloadSourcesHelper( emulator: emulator!, fullRestart: false, reason: reason, - fastReassemble: false, usage: usage, ).send(); // Reset devFS lastCompileTime to ensure the file will still be marked @@ -1288,7 +1279,6 @@ typedef ReassembleHelper = Future Function( Map> viewCache, void Function(String message)? onSlow, String reloadMessage, - String? fastReassembleClassName, ); Future _defaultReassembleHelper( @@ -1296,7 +1286,6 @@ Future _defaultReassembleHelper( Map> viewCache, void Function(String message)? onSlow, String reloadMessage, - String? fastReassembleClassName, ) async { // Check if any isolates are paused and reassemble those that aren't. final Map reassembleViews = {}; @@ -1325,17 +1314,9 @@ Future _defaultReassembleHelper( reassembleViews[view] = device.vmService; // If the tool identified a change in a single widget, do a fast instead // of a full reassemble. - Future reassembleWork; - if (fastReassembleClassName != null) { - reassembleWork = device.vmService!.flutterFastReassemble( - isolateId: view.uiIsolate!.id!, - className: fastReassembleClassName, - ); - } else { - reassembleWork = device.vmService!.flutterReassemble( - isolateId: view.uiIsolate!.id!, - ); - } + final Future reassembleWork = device.vmService!.flutterReassemble( + isolateId: view.uiIsolate!.id!, + ); reassembleFutures.add(reassembleWork.then( (Object? obj) => obj, onError: (Object error, StackTrace stackTrace) { diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart index 6da8494d24..57228a9bdf 100644 --- a/packages/flutter_tools/lib/src/vmservice.dart +++ b/packages/flutter_tools/lib/src/vmservice.dart @@ -809,19 +809,6 @@ class FlutterVmService { ); } - Future?> flutterFastReassemble({ - required String isolateId, - required String className, - }) { - return invokeFlutterExtensionRpcRaw( - 'ext.flutter.fastReassemble', - isolateId: isolateId, - args: { - 'className': className, - }, - ); - } - Future flutterAlreadyPaintedFirstUsefulFrame({ required String isolateId, }) async { diff --git a/packages/flutter_tools/test/general.shard/bundle_builder_test.dart b/packages/flutter_tools/test/general.shard/bundle_builder_test.dart index 190400acb5..335354026f 100644 --- a/packages/flutter_tools/test/general.shard/bundle_builder_test.dart +++ b/packages/flutter_tools/test/general.shard/bundle_builder_test.dart @@ -118,14 +118,14 @@ void main() { ProcessManager: () => FakeProcessManager.any(), }); - testWithoutContext('--flutter-widget-cache and --enable-experiment are removed from getDefaultCachedKernelPath hash', () { + testWithoutContext('--enable-experiment is removed from getDefaultCachedKernelPath hash', () { final FileSystem fileSystem = MemoryFileSystem.test(); final Config config = Config.test(); expect(getDefaultCachedKernelPath( trackWidgetCreation: true, dartDefines: [], - extraFrontEndOptions: ['--enable-experiment=foo', '--flutter-widget-cache'], + extraFrontEndOptions: ['--enable-experiment=foo'], fileSystem: fileSystem, config: config, ), 'build/cache.dill.track.dill'); @@ -133,7 +133,7 @@ void main() { expect(getDefaultCachedKernelPath( trackWidgetCreation: true, dartDefines: ['foo=bar'], - extraFrontEndOptions: ['--enable-experiment=foo', '--flutter-widget-cache'], + extraFrontEndOptions: ['--enable-experiment=foo'], fileSystem: fileSystem, config: config, ), 'build/06ad47d8e64bd28de537b62ff85357c4.cache.dill.track.dill'); @@ -141,7 +141,7 @@ void main() { expect(getDefaultCachedKernelPath( trackWidgetCreation: false, dartDefines: [], - extraFrontEndOptions: ['--enable-experiment=foo', '--flutter-widget-cache'], + extraFrontEndOptions: ['--enable-experiment=foo'], fileSystem: fileSystem, config: config, ), 'build/cache.dill'); @@ -149,7 +149,7 @@ void main() { expect(getDefaultCachedKernelPath( trackWidgetCreation: true, dartDefines: [], - extraFrontEndOptions: ['--enable-experiment=foo', '--flutter-widget-cache', '--foo=bar'], + extraFrontEndOptions: ['--enable-experiment=foo', '--foo=bar'], fileSystem: fileSystem, config: config, ), 'build/95b595cca01caa5f0ca0a690339dd7f6.cache.dill.track.dill'); diff --git a/packages/flutter_tools/test/general.shard/hot_test.dart b/packages/flutter_tools/test/general.shard/hot_test.dart index 110b59a08c..b8be90ff0b 100644 --- a/packages/flutter_tools/test/general.shard/hot_test.dart +++ b/packages/flutter_tools/test/general.shard/hot_test.dart @@ -178,7 +178,6 @@ void main() { Map> viewCache, void Function(String message)? onSlow, String reloadMessage, - String? fastReassembleClassName, ) async => ReassembleResult( {null: null}, false, @@ -296,7 +295,6 @@ void main() { hotEventSdkName: 'Tester', hotEventEmulator: false, hotEventFullRestart: true, - fastReassemble: false, hotEventOverallTimeInMs: 64000, hotEventSyncedBytes: 4, hotEventInvalidatedSourcesCount: 2, @@ -379,7 +377,6 @@ void main() { Map> viewCache, void Function(String message)? onSlow, String reloadMessage, - String? fastReassembleClassName, ) async => ReassembleResult( {null: null}, false, @@ -402,7 +399,6 @@ void main() { hotEventSdkName: 'Tester', hotEventEmulator: false, hotEventFullRestart: false, - fastReassemble: false, hotEventCompileTimeInMs: 16000, hotEventFindInvalidatedTimeInMs: 64000, hotEventScannedSourcesCount: 16, diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart index 35970ba5c1..6723487850 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart @@ -25,7 +25,6 @@ import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device_port_forwarder.dart'; -import 'package:flutter_tools/src/features.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/reporting/reporting.dart'; @@ -424,7 +423,6 @@ void main() { hotEventSdkName: 'Android', hotEventEmulator: false, hotEventFullRestart: false, - fastReassemble: false, )), )); expect(fakeVmServiceHost?.hasRemainingExpectations, false); @@ -480,7 +478,6 @@ void main() { hotEventSdkName: 'Android', hotEventEmulator: false, hotEventFullRestart: false, - fastReassemble: false, )), )); expect(fakeVmServiceHost?.hasRemainingExpectations, false); @@ -527,7 +524,6 @@ void main() { hotEventSdkName: 'Android', hotEventEmulator: false, hotEventFullRestart: false, - fastReassemble: false, )), )); expect(fakeVmServiceHost?.hasRemainingExpectations, false); @@ -766,96 +762,6 @@ void main() { Usage: () => TestUsage(), })); - testUsingContext('ResidentRunner can perform fast reassemble', () => testbed.run(() async { - fakeVmServiceHost = FakeVmServiceHost(requests: [ - listViews, - FakeVmServiceRequest( - method: 'getVM', - jsonResponse: fakeVM.toJson(), - ), - listViews, - listViews, - FakeVmServiceRequest( - method: 'getVM', - jsonResponse: fakeVM.toJson(), - ), - const FakeVmServiceRequest( - method: kReloadSourcesServiceName, - args: { - 'isolateId': '1', - 'pause': false, - 'rootLibUri': 'main.dart.incremental.dill', - }, - jsonResponse: { - 'type': 'ReloadReport', - 'success': true, - 'details': { - 'loadedLibraryCount': 1, - }, - }, - ), - FakeVmServiceRequest( - method: 'getIsolatePauseEvent', - args: { - 'isolateId': '1', - }, - jsonResponse: fakeUnpausedEvent.toJson(), - ), - FakeVmServiceRequest( - method: 'ext.flutter.fastReassemble', - args: { - 'isolateId': fakeUnpausedIsolate.id, - 'className': 'FOO', - }, - ), - ]); - final FakeDelegateFlutterDevice flutterDevice = FakeDelegateFlutterDevice( - device, - BuildInfo.debug, - FakeResidentCompiler(), - devFS, - )..vmService = fakeVmServiceHost!.vmService; - residentRunner = HotRunner( - [ - flutterDevice, - ], - stayResident: false, - debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), - target: 'main.dart', - devtoolsHandler: createNoOpHandler, - ); - devFS.nextUpdateReport = UpdateFSReport( - success: true, - fastReassembleClassName: 'FOO', - invalidatedSourcesCount: 1, - ); - - final Completer futureConnectionInfo = Completer.sync(); - final Completer futureAppStart = Completer.sync(); - unawaited(residentRunner.attach( - appStartedCompleter: futureAppStart, - connectionInfoCompleter: futureConnectionInfo, - enableDevTools: true, - )); - - await futureAppStart.future; - final OperationResult result = await residentRunner.restart(); - - expect(result.fatal, false); - expect(result.code, 0); - - final TestUsageEvent event = (globals.flutterUsage as TestUsage).events.first; - expect(event.category, 'hot'); - expect(event.parameter, 'reload'); - expect(event.parameters?.fastReassemble, true); - }, overrides: { - FileSystem: () => MemoryFileSystem.test(), - Platform: () => FakePlatform(), - ProjectFileInvalidator: () => FakeProjectFileInvalidator(), - Usage: () => TestUsage(), - FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true), - })); - testUsingContext('ResidentRunner reports hot reload time details', () => testbed.run(() async { fakeVmServiceHost = FakeVmServiceHost(requests: [ listViews, @@ -893,10 +799,9 @@ void main() { jsonResponse: fakeUnpausedEvent.toJson(), ), FakeVmServiceRequest( - method: 'ext.flutter.fastReassemble', + method: 'ext.flutter.reassemble', args: { 'isolateId': fakeUnpausedIsolate.id, - 'className': 'FOO', }, ), ]); @@ -917,7 +822,6 @@ void main() { ); devFS.nextUpdateReport = UpdateFSReport( success: true, - fastReassembleClassName: 'FOO', invalidatedSourcesCount: 1, ); @@ -942,7 +846,6 @@ void main() { Platform: () => FakePlatform(), ProjectFileInvalidator: () => FakeProjectFileInvalidator(), Usage: () => TestUsage(), - FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true), })); testUsingContext('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async { @@ -1225,7 +1128,6 @@ void main() { hotEventSdkName: 'Android', hotEventEmulator: false, hotEventFullRestart: true, - fastReassemble: false, )), )); expect(fakeVmServiceHost?.hasRemainingExpectations, false); @@ -1984,31 +1886,7 @@ flutter: ProcessManager: () => FakeProcessManager.any(), }); - testUsingContext('FlutterDevice passes flutter-widget-cache flag when feature is enabled', () async { - fakeVmServiceHost = FakeVmServiceHost(requests: []); - final FakeDevice device = FakeDevice(); - - final DefaultResidentCompiler? residentCompiler = (await FlutterDevice.create( - device, - buildInfo: const BuildInfo( - BuildMode.debug, - '', - treeShakeIcons: false, - extraFrontEndOptions: [], - ), - target: null, platform: FakePlatform(), - )).generator as DefaultResidentCompiler?; - - expect(residentCompiler!.extraFrontEndOptions, - contains('--flutter-widget-cache')); - }, overrides: { - Artifacts: () => Artifacts.test(), - FileSystem: () => MemoryFileSystem.test(), - ProcessManager: () => FakeProcessManager.any(), - FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true), - }); - - testUsingContext('FlutterDevice passes alternative-invalidation-strategy flag', () async { + testUsingContext('FlutterDevice passes alternative-invalidation-strategy flag', () async { fakeVmServiceHost = FakeVmServiceHost(requests: []); final FakeDevice device = FakeDevice(); @@ -2032,7 +1910,7 @@ flutter: ProcessManager: () => FakeProcessManager.any(), }); - testUsingContext('FlutterDevice passes initializeFromDill parameter if specified', () async { + testUsingContext('FlutterDevice passes initializeFromDill parameter if specified', () async { fakeVmServiceHost = FakeVmServiceHost(requests: []); final FakeDevice device = FakeDevice(); diff --git a/packages/flutter_tools/test/integration.shard/single_widget_reload_test.dart b/packages/flutter_tools/test/integration.shard/single_widget_reload_test.dart deleted file mode 100644 index 85ec32c59e..0000000000 --- a/packages/flutter_tools/test/integration.shard/single_widget_reload_test.dart +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; - -import 'package:flutter_tools/src/base/file_system.dart'; - -import '../src/common.dart'; -import 'test_data/single_widget_reload_project.dart'; -import 'test_driver.dart'; -import 'test_utils.dart'; - -void main() { - late Directory tempDir; - final SingleWidgetReloadProject project = SingleWidgetReloadProject(); - late FlutterRunTestDriver flutter; - - setUp(() async { - tempDir = createResolvedTempDirectorySync('hot_reload_test.'); - await project.setUpIn(tempDir); - flutter = FlutterRunTestDriver(tempDir); - }); - - tearDown(() async { - await flutter.stop(); - tryToDelete(tempDir); - }); - - testWithoutContext('newly added code executes during hot reload with single widget reloads, but only invalidated widget', () async { - final StringBuffer stdout = StringBuffer(); - final StreamSubscription subscription = flutter.stdout.listen(stdout.writeln); - await flutter.run(singleWidgetReloads: true); - project.uncommentHotReloadPrint(); - try { - await flutter.hotReload(); - expect(stdout.toString(), allOf( - contains('(((TICK 1)))'), - contains('(((((RELOAD WORKED)))))'), - // Does not invalidate parent widget, so second tick is not output. - isNot(contains('(((TICK 2)))'), - ))); - } finally { - await subscription.cancel(); - } - }); - - testWithoutContext('changes outside of the class body triggers a full reload', () async { - final StringBuffer stdout = StringBuffer(); - final StreamSubscription subscription = flutter.stdout.listen(stdout.writeln); - await flutter.run(singleWidgetReloads: true); - project.modifyFunction(); - try { - await flutter.hotReload(); - expect(stdout.toString(), allOf( - contains('(((TICK 1)))'), - contains('(((TICK 2)))'), - )); - } finally { - await subscription.cancel(); - } - }); -} diff --git a/packages/flutter_tools/test/integration.shard/test_data/single_widget_reload_project.dart b/packages/flutter_tools/test/integration.shard/test_data/single_widget_reload_project.dart deleted file mode 100644 index 2a48a090ea..0000000000 --- a/packages/flutter_tools/test/integration.shard/test_data/single_widget_reload_project.dart +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import '../test_utils.dart'; -import 'project.dart'; - -class SingleWidgetReloadProject extends Project { - @override - final String pubspec = ''' - name: test - environment: - sdk: '>=3.0.0-0 <4.0.0' - - dependencies: - flutter: - sdk: flutter - '''; - - @override - final String main = r''' - import 'package:flutter/material.dart'; - import 'package:flutter/scheduler.dart'; - import 'package:flutter/services.dart'; - import 'package:flutter/widgets.dart'; - - void main() async { - WidgetsFlutterBinding.ensureInitialized(); - final ByteData message = const StringCodec().encodeMessage('AppLifecycleState.resumed')!; - await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); - runApp(MyApp()); - } - - int count = 1; - - class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - // PARENT WIDGET - - print('((((TICK $count))))'); - count += 1; - - return MaterialApp( - title: 'Flutter Demo', - home: SecondWidget(), - ); - } - } - - class SecondWidget extends StatelessWidget { - @override - Widget build(BuildContext context) { - // Do not remove the next line, it's uncommented by a test to verify that - // hot reloading worked: - // printHotReloadWorked(); - return Container(); - } - } - - void printHotReloadWorked() { - // The call to this function is uncommented by a test to verify that hot - // reloading worked. - print('(((((RELOAD WORKED)))))'); - } - '''; - - Uri get parentWidgetUri => mainDart; - int get parentWidgetLine => lineContaining(main, '// PARENT WIDGET'); - - void uncommentHotReloadPrint() { - final String newMainContents = main.replaceAll( - '// printHotReloadWorked();', - 'printHotReloadWorked();', - ); - writeFile( - fileSystem.path.join(dir.path, 'lib', 'main.dart'), - newMainContents, - writeFutureModifiedDate: true, - ); - } - - void modifyFunction() { - final String newMainContents = main.replaceAll( - '(((((RELOAD WORKED)))))', - '(((((RELOAD WORKED 2)))))', - ); - writeFile( - fileSystem.path.join(dir.path, 'lib', 'main.dart'), - newMainContents, - writeFutureModifiedDate: true, - ); - } -} diff --git a/packages/flutter_tools/test/integration.shard/test_driver.dart b/packages/flutter_tools/test/integration.shard/test_driver.dart index 24a8e59575..6be229d2d5 100644 --- a/packages/flutter_tools/test/integration.shard/test_driver.dart +++ b/packages/flutter_tools/test/integration.shard/test_driver.dart @@ -90,7 +90,6 @@ abstract class FlutterTestDriver { List arguments, { String? script, bool withDebugger = false, - bool singleWidgetReloads = false, }) async { final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter'); if (withDebugger) { @@ -114,8 +113,6 @@ abstract class FlutterTestDriver { environment: { 'FLUTTER_TEST': 'true', 'FLUTTER_WEB': 'true', - if (singleWidgetReloads) - 'FLUTTER_SINGLE_WIDGET_RELOAD': 'true', }, ); @@ -511,7 +508,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { bool chrome = false, bool expressionEvaluation = true, bool structuredErrors = false, - bool singleWidgetReloads = false, bool serveObservatory = false, String? script, List? additionalCommandArgs, @@ -542,7 +538,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { startPaused: startPaused, pauseOnExceptions: pauseOnExceptions, script: script, - singleWidgetReloads: singleWidgetReloads, ); } @@ -551,7 +546,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { bool withDebugger = false, bool startPaused = false, bool pauseOnExceptions = false, - bool singleWidgetReloads = false, bool serveObservatory = false, List? additionalCommandArgs, }) async { @@ -573,7 +567,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { withDebugger: withDebugger, startPaused: startPaused, pauseOnExceptions: pauseOnExceptions, - singleWidgetReloads: singleWidgetReloads, attachPort: port, ); } @@ -585,7 +578,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { bool withDebugger = false, bool startPaused = false, bool pauseOnExceptions = false, - bool singleWidgetReloads = false, int? attachPort, }) async { assert(!startPaused || withDebugger); @@ -593,7 +585,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { args, script: script, withDebugger: withDebugger, - singleWidgetReloads: singleWidgetReloads, ); final Completer prematureExitGuard = Completer(); @@ -806,13 +797,11 @@ class FlutterTestTestDriver extends FlutterTestDriver { bool withDebugger = false, bool pauseOnExceptions = false, Future Function()? beforeStart, - bool singleWidgetReloads = false, }) async { await super._setupProcess( args, script: script, withDebugger: withDebugger, - singleWidgetReloads: singleWidgetReloads, ); // Stash the PID so that we can terminate the VM more reliably than using diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart index 65fb5578cf..d51ec236dc 100644 --- a/packages/flutter_tools/test/src/fakes.dart +++ b/packages/flutter_tools/test/src/fakes.dart @@ -443,7 +443,6 @@ class TestFeatureFlags implements FeatureFlags { this.isMacOSEnabled = false, this.isWebEnabled = false, this.isWindowsEnabled = false, - this.isSingleWidgetReloadEnabled = false, this.isAndroidEnabled = true, this.isIOSEnabled = true, this.isFuchsiaEnabled = false, @@ -463,9 +462,6 @@ class TestFeatureFlags implements FeatureFlags { @override final bool isWindowsEnabled; - @override - final bool isSingleWidgetReloadEnabled; - @override final bool isAndroidEnabled; @@ -492,8 +488,6 @@ class TestFeatureFlags implements FeatureFlags { return isMacOSEnabled; case flutterWindowsDesktopFeature: return isWindowsEnabled; - case singleWidgetReload: - return isSingleWidgetReloadEnabled; case flutterAndroidFeature: return isAndroidEnabled; case flutterIOSFeature: