Unverified Commit a2e25749 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Remove the fast reassemble / single widget reload feature (#132255)

Fixes https://github.com/flutter/flutter/issues/132157
parent 6cf5dbe3
...@@ -168,13 +168,6 @@ abstract class BindingBase { ...@@ -168,13 +168,6 @@ abstract class BindingBase {
static Type? _debugInitializedType; static Type? _debugInitializedType;
static bool _debugServiceExtensionsRegistered = false; 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. /// Deprecated. Will be removed in a future version of Flutter.
/// ///
/// This property has been deprecated to prepare for Flutter's upcoming /// This property has been deprecated to prepare for Flutter's upcoming
...@@ -989,23 +982,3 @@ abstract class BindingBase { ...@@ -989,23 +982,3 @@ abstract class BindingBase {
Future<void> _exitApplication() async { Future<void> _exitApplication() async {
exit(0); 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;
}
...@@ -603,18 +603,16 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture ...@@ -603,18 +603,16 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
@override @override
Future<void> performReassemble() async { Future<void> performReassemble() async {
await super.performReassemble(); await super.performReassemble();
if (BindingBase.debugReassembleConfig?.widgetName == null) { if (!kReleaseMode) {
if (!kReleaseMode) { FlutterTimeline.startSync('Preparing Hot Reload (layout)');
FlutterTimeline.startSync('Preparing Hot Reload (layout)'); }
try {
for (final RenderView renderView in renderViews) {
renderView.reassemble();
} }
try { } finally {
for (final RenderView renderView in renderViews) { if (!kReleaseMode) {
renderView.reassemble(); FlutterTimeline.finishSync();
}
} finally {
if (!kReleaseMode) {
FlutterTimeline.finishSync();
}
} }
} }
scheduleWarmUpFrame(); scheduleWarmUpFrame();
......
...@@ -505,23 +505,6 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB ...@@ -505,23 +505,6 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
}, },
); );
registerServiceExtension(
name: WidgetsServiceExtensions.fastReassemble.name,
callback: (Map<String, Object> 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 <String, String>{'type': 'Success'};
},
);
// Expose the ability to send Widget rebuilds as [Timeline] events. // Expose the ability to send Widget rebuilds as [Timeline] events.
registerBoolServiceExtension( registerBoolServiceExtension(
name: WidgetsServiceExtensions.profileWidgetBuilds.name, name: WidgetsServiceExtensions.profileWidgetBuilds.name,
...@@ -560,7 +543,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB ...@@ -560,7 +543,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
Future<void> _forceRebuild() { Future<void> _forceRebuild() {
if (rootElement != null) { if (rootElement != null) {
buildOwner!.reassemble(rootElement!, null); buildOwner!.reassemble(rootElement!);
return endOfFrame; return endOfFrame;
} }
return Future<void>.value(); return Future<void>.value();
...@@ -1090,7 +1073,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB ...@@ -1090,7 +1073,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
}()); }());
if (rootElement != null) { if (rootElement != null) {
buildOwner!.reassemble(rootElement!, BindingBase.debugReassembleConfig); buildOwner!.reassemble(rootElement!);
} }
return super.performReassemble(); return super.performReassemble();
} }
......
...@@ -3252,14 +3252,13 @@ class BuildOwner { ...@@ -3252,14 +3252,13 @@ class BuildOwner {
/// changed implementations. /// changed implementations.
/// ///
/// This is expensive and should not be called except during development. /// This is expensive and should not be called except during development.
void reassemble(Element root, DebugReassembleConfig? reassembleConfig) { void reassemble(Element root) {
if (!kReleaseMode) { if (!kReleaseMode) {
FlutterTimeline.startSync('Preparing Hot Reload (widgets)'); FlutterTimeline.startSync('Preparing Hot Reload (widgets)');
} }
try { try {
assert(root._parent == null); assert(root._parent == null);
assert(root.owner == this); assert(root.owner == this);
root._debugReassembleConfig = reassembleConfig;
root.reassemble(); root.reassemble();
} finally { } finally {
if (!kReleaseMode) { if (!kReleaseMode) {
...@@ -3374,7 +3373,6 @@ abstract class Element extends DiagnosticableTree implements BuildContext { ...@@ -3374,7 +3373,6 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
} }
Element? _parent; Element? _parent;
DebugReassembleConfig? _debugReassembleConfig;
_NotificationNode? _notificationTree; _NotificationNode? _notificationTree;
/// Compare two widgets for equality. /// Compare two widgets for equality.
...@@ -3526,15 +3524,10 @@ abstract class Element extends DiagnosticableTree implements BuildContext { ...@@ -3526,15 +3524,10 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
@mustCallSuper @mustCallSuper
@protected @protected
void reassemble() { void reassemble() {
if (_debugShouldReassemble(_debugReassembleConfig, _widget)) { markNeedsBuild();
markNeedsBuild();
_debugReassembleConfig = null;
}
visitChildren((Element child) { visitChildren((Element child) {
child._debugReassembleConfig = _debugReassembleConfig;
child.reassemble(); child.reassemble();
}); });
_debugReassembleConfig = null;
} }
bool _debugIsInScope(Element target) { bool _debugIsInScope(Element target) {
...@@ -5585,9 +5578,7 @@ class StatefulElement extends ComponentElement { ...@@ -5585,9 +5578,7 @@ class StatefulElement extends ComponentElement {
@override @override
void reassemble() { void reassemble() {
if (_debugShouldReassemble(_debugReassembleConfig, _widget)) { state.reassemble();
state.reassemble();
}
super.reassemble(); super.reassemble();
} }
...@@ -6952,9 +6943,3 @@ class _NullWidget extends Widget { ...@@ -6952,9 +6943,3 @@ class _NullWidget extends Widget {
@override @override
Element createElement() => throw UnimplementedError(); 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;
}
...@@ -970,7 +970,7 @@ mixin WidgetInspectorService { ...@@ -970,7 +970,7 @@ mixin WidgetInspectorService {
Future<void> forceRebuild() { Future<void> forceRebuild() {
final WidgetsBinding binding = WidgetsBinding.instance; final WidgetsBinding binding = WidgetsBinding.instance;
if (binding.rootElement != null) { if (binding.rootElement != null) {
binding.buildOwner!.reassemble(binding.rootElement!, null); binding.buildOwner!.reassemble(binding.rootElement!);
return binding.endOfFrame; return binding.endOfFrame;
} }
return Future<void>.value(); return Future<void>.value();
......
// 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<Foo> createState() => _FooState();
}
class _FooState extends State<Foo> {
@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<Bar> createState() => _BarState();
}
class _BarState extends State<Bar> {
@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<Fizz> createState() => _FizzState();
}
class _FizzState extends State<Fizz> {
@override
void reassemble() {
Fizz.count += 1;
super.reassemble();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
...@@ -115,7 +115,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -115,7 +115,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final WidgetsBinding binding = WidgetsBinding.instance; final WidgetsBinding binding = WidgetsBinding.instance;
if (binding.rootElement != null) { if (binding.rootElement != null) {
binding.buildOwner!.reassemble(binding.rootElement!, null); binding.buildOwner!.reassemble(binding.rootElement!);
} }
} }
......
...@@ -33,7 +33,7 @@ String getDefaultCachedKernelPath({ ...@@ -33,7 +33,7 @@ String getDefaultCachedKernelPath({
}) { }) {
final StringBuffer buffer = StringBuffer(); final StringBuffer buffer = StringBuffer();
final List<String> cacheFrontEndOptions = extraFrontEndOptions.toList() final List<String> 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(dartDefines);
buffer.writeAll(cacheFrontEndOptions); buffer.writeAll(cacheFrontEndOptions);
String buildPrefix = ''; String buildPrefix = '';
......
...@@ -401,7 +401,6 @@ class UpdateFSReport { ...@@ -401,7 +401,6 @@ class UpdateFSReport {
bool success = false, bool success = false,
int invalidatedSourcesCount = 0, int invalidatedSourcesCount = 0,
int syncedBytes = 0, int syncedBytes = 0,
this.fastReassembleClassName,
int scannedSourcesCount = 0, int scannedSourcesCount = 0,
Duration compileDuration = Duration.zero, Duration compileDuration = Duration.zero,
Duration transferDuration = Duration.zero, Duration transferDuration = Duration.zero,
...@@ -423,7 +422,6 @@ class UpdateFSReport { ...@@ -423,7 +422,6 @@ class UpdateFSReport {
Duration get findInvalidatedDuration => _findInvalidatedDuration; Duration get findInvalidatedDuration => _findInvalidatedDuration;
bool _success; bool _success;
String? fastReassembleClassName;
int _invalidatedSourcesCount; int _invalidatedSourcesCount;
int _syncedBytes; int _syncedBytes;
int _scannedSourcesCount; int _scannedSourcesCount;
...@@ -435,7 +433,6 @@ class UpdateFSReport { ...@@ -435,7 +433,6 @@ class UpdateFSReport {
if (!report._success) { if (!report._success) {
_success = false; _success = false;
} }
fastReassembleClassName ??= report.fastReassembleClassName;
_invalidatedSourcesCount += report._invalidatedSourcesCount; _invalidatedSourcesCount += report._invalidatedSourcesCount;
_syncedBytes += report._syncedBytes; _syncedBytes += report._syncedBytes;
_scannedSourcesCount += report._scannedSourcesCount; _scannedSourcesCount += report._scannedSourcesCount;
...@@ -495,7 +492,6 @@ class DevFS { ...@@ -495,7 +492,6 @@ class DevFS {
DateTime? lastCompiled; DateTime? lastCompiled;
DateTime? _previousCompiled; DateTime? _previousCompiled;
PackageConfig? lastPackageConfig; PackageConfig? lastPackageConfig;
File? _widgetCacheOutputFile;
Uri? _baseUri; Uri? _baseUri;
Uri? get baseUri => _baseUri; Uri? get baseUri => _baseUri;
...@@ -555,22 +551,6 @@ class DevFS { ...@@ -555,22 +551,6 @@ class DevFS {
lastCompiled = _previousCompiled; 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. /// Updates files on the device.
/// ///
/// Returns the number of bytes synced. /// Returns the number of bytes synced.
...@@ -596,7 +576,6 @@ class DevFS { ...@@ -596,7 +576,6 @@ class DevFS {
final DateTime candidateCompileTime = DateTime.now(); final DateTime candidateCompileTime = DateTime.now();
didUpdateFontManifest = false; didUpdateFontManifest = false;
lastPackageConfig = packageConfig; lastPackageConfig = packageConfig;
_widgetCacheOutputFile = _fileSystem.file('$dillOutputPath.incremental.dill.widget_cache');
// Update modified files // Update modified files
final Map<Uri, DevFSContent> dirtyEntries = <Uri, DevFSContent>{}; final Map<Uri, DevFSContent> dirtyEntries = <Uri, DevFSContent>{};
...@@ -741,7 +720,6 @@ class DevFS { ...@@ -741,7 +720,6 @@ class DevFS {
success: true, success: true,
syncedBytes: syncedBytes, syncedBytes: syncedBytes,
invalidatedSourcesCount: invalidatedFiles.length, invalidatedSourcesCount: invalidatedFiles.length,
fastReassembleClassName: _checkIfSingleWidgetReloadApplied(),
compileDuration: compileTimer.elapsed, compileDuration: compileTimer.elapsed,
transferDuration: transferTimer.elapsed, transferDuration: transferTimer.elapsed,
); );
......
...@@ -44,9 +44,6 @@ abstract class FeatureFlags { ...@@ -44,9 +44,6 @@ abstract class FeatureFlags {
/// Whether custom devices are enabled. /// Whether custom devices are enabled.
bool get areCustomDevicesEnabled => false; bool get areCustomDevicesEnabled => false;
/// Whether fast single widget reloads are enabled.
bool get isSingleWidgetReloadEnabled => false;
/// Whether WebAssembly compilation for Flutter Web is enabled. /// Whether WebAssembly compilation for Flutter Web is enabled.
bool get isFlutterWebWasmEnabled => false; bool get isFlutterWebWasmEnabled => false;
...@@ -62,7 +59,6 @@ const List<Feature> allFeatures = <Feature>[ ...@@ -62,7 +59,6 @@ const List<Feature> allFeatures = <Feature>[
flutterLinuxDesktopFeature, flutterLinuxDesktopFeature,
flutterMacOSDesktopFeature, flutterMacOSDesktopFeature,
flutterWindowsDesktopFeature, flutterWindowsDesktopFeature,
singleWidgetReload,
flutterAndroidFeature, flutterAndroidFeature,
flutterIOSFeature, flutterIOSFeature,
flutterFuchsiaFeature, flutterFuchsiaFeature,
...@@ -140,20 +136,6 @@ const Feature flutterCustomDevicesFeature = Feature( ...@@ -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` /// Enabling WebAssembly compilation from `flutter build web`
const Feature flutterWebWasm = Feature( const Feature flutterWebWasm = Feature(
name: 'WebAssembly compilation from flutter build web', name: 'WebAssembly compilation from flutter build web',
......
...@@ -44,9 +44,6 @@ class FlutterFeatureFlags implements FeatureFlags { ...@@ -44,9 +44,6 @@ class FlutterFeatureFlags implements FeatureFlags {
@override @override
bool get areCustomDevicesEnabled => isEnabled(flutterCustomDevicesFeature); bool get areCustomDevicesEnabled => isEnabled(flutterCustomDevicesFeature);
@override
bool get isSingleWidgetReloadEnabled => isEnabled(singleWidgetReload);
@override @override
bool get isFlutterWebWasmEnabled => isEnabled(flutterWebWasm); bool get isFlutterWebWasmEnabled => isEnabled(flutterWebWasm);
......
...@@ -446,7 +446,6 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). ...@@ -446,7 +446,6 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
fullRestart: true, fullRestart: true,
reason: reason, reason: reason,
overallTimeInMs: elapsed.inMilliseconds, overallTimeInMs: elapsed.inMilliseconds,
fastReassemble: false,
).send(); ).send();
} }
return OperationResult.ok; return OperationResult.ok;
......
...@@ -58,7 +58,6 @@ class CustomDimensions { ...@@ -58,7 +58,6 @@ class CustomDimensions {
this.commandRunAndroidEmbeddingVersion, this.commandRunAndroidEmbeddingVersion,
this.commandPackagesAndroidEmbeddingVersion, this.commandPackagesAndroidEmbeddingVersion,
this.nullSafety, this.nullSafety,
this.fastReassemble,
this.nullSafeMigratedLibraries, this.nullSafeMigratedLibraries,
this.nullSafeTotalLibraries, this.nullSafeTotalLibraries,
this.hotEventCompileTimeInMs, this.hotEventCompileTimeInMs,
...@@ -118,17 +117,17 @@ class CustomDimensions { ...@@ -118,17 +117,17 @@ class CustomDimensions {
final String? commandRunAndroidEmbeddingVersion; // cd45 final String? commandRunAndroidEmbeddingVersion; // cd45
final String? commandPackagesAndroidEmbeddingVersion; // cd46 final String? commandPackagesAndroidEmbeddingVersion; // cd46
final bool? nullSafety; // cd47 final bool? nullSafety; // cd47
final bool? fastReassemble; // cd48 // cd48 was fastReassemble but that feature was removed
final int? nullSafeMigratedLibraries; // cd49 final int? nullSafeMigratedLibraries; // cd49
final int? nullSafeTotalLibraries; // cd50 final int? nullSafeTotalLibraries; // cd50
final int? hotEventCompileTimeInMs; // cd 51 final int? hotEventCompileTimeInMs; // cd51
final int? hotEventFindInvalidatedTimeInMs; // cd 52 final int? hotEventFindInvalidatedTimeInMs; // cd52
final int? hotEventScannedSourcesCount; // cd 53 final int? hotEventScannedSourcesCount; // cd53
final int? hotEventReassembleTimeInMs; // cd 54 final int? hotEventReassembleTimeInMs; // cd54
final int? hotEventReloadVMTimeInMs; // cd 55 final int? hotEventReloadVMTimeInMs; // cd55
final bool? commandRunEnableImpeller; // cd 56 final bool? commandRunEnableImpeller; // cd56
final String? commandRunIOSInterfaceType; // cd 57 final String? commandRunIOSInterfaceType; // cd57
final bool? commandRunIsTest; // cd 58 final bool? commandRunIsTest; // cd58
/// Convert to a map that will be used to upload to the analytics backend. /// Convert to a map that will be used to upload to the analytics backend.
Map<String, String> toMap() => <String, String>{ Map<String, String> toMap() => <String, String>{
...@@ -179,7 +178,6 @@ class CustomDimensions { ...@@ -179,7 +178,6 @@ class CustomDimensions {
if (commandRunAndroidEmbeddingVersion != null) CustomDimensionsEnum.commandRunAndroidEmbeddingVersion.cdKey: commandRunAndroidEmbeddingVersion.toString(), if (commandRunAndroidEmbeddingVersion != null) CustomDimensionsEnum.commandRunAndroidEmbeddingVersion.cdKey: commandRunAndroidEmbeddingVersion.toString(),
if (commandPackagesAndroidEmbeddingVersion != null) CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion.cdKey: commandPackagesAndroidEmbeddingVersion.toString(), if (commandPackagesAndroidEmbeddingVersion != null) CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion.cdKey: commandPackagesAndroidEmbeddingVersion.toString(),
if (nullSafety != null) CustomDimensionsEnum.nullSafety.cdKey: nullSafety.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 (nullSafeMigratedLibraries != null) CustomDimensionsEnum.nullSafeMigratedLibraries.cdKey: nullSafeMigratedLibraries.toString(),
if (nullSafeTotalLibraries != null) CustomDimensionsEnum.nullSafeTotalLibraries.cdKey: nullSafeTotalLibraries.toString(), if (nullSafeTotalLibraries != null) CustomDimensionsEnum.nullSafeTotalLibraries.cdKey: nullSafeTotalLibraries.toString(),
if (hotEventCompileTimeInMs != null) CustomDimensionsEnum.hotEventCompileTimeInMs.cdKey: hotEventCompileTimeInMs.toString(), if (hotEventCompileTimeInMs != null) CustomDimensionsEnum.hotEventCompileTimeInMs.cdKey: hotEventCompileTimeInMs.toString(),
...@@ -247,7 +245,6 @@ class CustomDimensions { ...@@ -247,7 +245,6 @@ class CustomDimensions {
commandRunAndroidEmbeddingVersion: other.commandRunAndroidEmbeddingVersion ?? commandRunAndroidEmbeddingVersion, commandRunAndroidEmbeddingVersion: other.commandRunAndroidEmbeddingVersion ?? commandRunAndroidEmbeddingVersion,
commandPackagesAndroidEmbeddingVersion: other.commandPackagesAndroidEmbeddingVersion ?? commandPackagesAndroidEmbeddingVersion, commandPackagesAndroidEmbeddingVersion: other.commandPackagesAndroidEmbeddingVersion ?? commandPackagesAndroidEmbeddingVersion,
nullSafety: other.nullSafety ?? nullSafety, nullSafety: other.nullSafety ?? nullSafety,
fastReassemble: other.fastReassemble ?? fastReassemble,
nullSafeMigratedLibraries: other.nullSafeMigratedLibraries ?? nullSafeMigratedLibraries, nullSafeMigratedLibraries: other.nullSafeMigratedLibraries ?? nullSafeMigratedLibraries,
nullSafeTotalLibraries: other.nullSafeTotalLibraries ?? nullSafeTotalLibraries, nullSafeTotalLibraries: other.nullSafeTotalLibraries ?? nullSafeTotalLibraries,
hotEventCompileTimeInMs: other.hotEventCompileTimeInMs ?? hotEventCompileTimeInMs, hotEventCompileTimeInMs: other.hotEventCompileTimeInMs ?? hotEventCompileTimeInMs,
...@@ -309,7 +306,6 @@ class CustomDimensions { ...@@ -309,7 +306,6 @@ class CustomDimensions {
commandRunAndroidEmbeddingVersion: _extractString(map, CustomDimensionsEnum.commandRunAndroidEmbeddingVersion), commandRunAndroidEmbeddingVersion: _extractString(map, CustomDimensionsEnum.commandRunAndroidEmbeddingVersion),
commandPackagesAndroidEmbeddingVersion: _extractString(map, CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion), commandPackagesAndroidEmbeddingVersion: _extractString(map, CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion),
nullSafety: _extractBool(map, CustomDimensionsEnum.nullSafety), nullSafety: _extractBool(map, CustomDimensionsEnum.nullSafety),
fastReassemble: _extractBool(map, CustomDimensionsEnum.fastReassemble),
nullSafeMigratedLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeMigratedLibraries), nullSafeMigratedLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeMigratedLibraries),
nullSafeTotalLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeTotalLibraries), nullSafeTotalLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeTotalLibraries),
hotEventCompileTimeInMs: _extractInt(map, CustomDimensionsEnum.hotEventCompileTimeInMs), hotEventCompileTimeInMs: _extractInt(map, CustomDimensionsEnum.hotEventCompileTimeInMs),
...@@ -397,7 +393,7 @@ enum CustomDimensionsEnum { ...@@ -397,7 +393,7 @@ enum CustomDimensionsEnum {
commandRunAndroidEmbeddingVersion, // cd45 commandRunAndroidEmbeddingVersion, // cd45
commandPackagesAndroidEmbeddingVersion, // cd46 commandPackagesAndroidEmbeddingVersion, // cd46
nullSafety, // cd47 nullSafety, // cd47
fastReassemble, // cd48 obsolete1, // cd48 (was fastReassemble)
nullSafeMigratedLibraries, // cd49 nullSafeMigratedLibraries, // cd49
nullSafeTotalLibraries, // cd50 nullSafeTotalLibraries, // cd50
hotEventCompileTimeInMs, // cd51 hotEventCompileTimeInMs, // cd51
......
...@@ -39,7 +39,6 @@ class HotEvent extends UsageEvent { ...@@ -39,7 +39,6 @@ class HotEvent extends UsageEvent {
required this.sdkName, required this.sdkName,
required this.emulator, required this.emulator,
required this.fullRestart, required this.fullRestart,
required this.fastReassemble,
this.reason, this.reason,
this.finalLibraryCount, this.finalLibraryCount,
this.syncedLibraryCount, this.syncedLibraryCount,
...@@ -63,7 +62,6 @@ class HotEvent extends UsageEvent { ...@@ -63,7 +62,6 @@ class HotEvent extends UsageEvent {
final String sdkName; final String sdkName;
final bool emulator; final bool emulator;
final bool fullRestart; final bool fullRestart;
final bool fastReassemble;
final int? finalLibraryCount; final int? finalLibraryCount;
final int? syncedLibraryCount; final int? syncedLibraryCount;
final int? syncedClassesCount; final int? syncedClassesCount;
...@@ -94,7 +92,6 @@ class HotEvent extends UsageEvent { ...@@ -94,7 +92,6 @@ class HotEvent extends UsageEvent {
hotEventInvalidatedSourcesCount: invalidatedSourcesCount, hotEventInvalidatedSourcesCount: invalidatedSourcesCount,
hotEventTransferTimeInMs: transferTimeInMs, hotEventTransferTimeInMs: transferTimeInMs,
hotEventOverallTimeInMs: overallTimeInMs, hotEventOverallTimeInMs: overallTimeInMs,
fastReassemble: fastReassemble,
hotEventCompileTimeInMs: compileTimeInMs, hotEventCompileTimeInMs: compileTimeInMs,
hotEventFindInvalidatedTimeInMs: findInvalidatedTimeInMs, hotEventFindInvalidatedTimeInMs: findInvalidatedTimeInMs,
hotEventScannedSourcesCount: scannedSourcesCount, hotEventScannedSourcesCount: scannedSourcesCount,
......
...@@ -34,7 +34,6 @@ import 'compile.dart'; ...@@ -34,7 +34,6 @@ import 'compile.dart';
import 'convert.dart'; import 'convert.dart';
import 'devfs.dart'; import 'devfs.dart';
import 'device.dart'; import 'device.dart';
import 'features.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
import 'ios/application_package.dart'; import 'ios/application_package.dart';
import 'ios/devices.dart'; import 'ios/devices.dart';
...@@ -169,11 +168,8 @@ class FlutterDevice { ...@@ -169,11 +168,8 @@ class FlutterDevice {
platform: platform, platform: platform,
); );
} else { } else {
// The flutter-widget-cache feature only applies to run mode.
List<String> extraFrontEndOptions = buildInfo.extraFrontEndOptions; List<String> extraFrontEndOptions = buildInfo.extraFrontEndOptions;
extraFrontEndOptions = <String>[ extraFrontEndOptions = <String>[
if (featureFlags.isSingleWidgetReloadEnabled)
'--flutter-widget-cache',
'--enable-experiment=alternative-invalidation-strategy', '--enable-experiment=alternative-invalidation-strategy',
...extraFrontEndOptions, ...extraFrontEndOptions,
]; ];
......
...@@ -20,7 +20,6 @@ import 'convert.dart'; ...@@ -20,7 +20,6 @@ import 'convert.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'devfs.dart'; import 'devfs.dart';
import 'device.dart'; import 'device.dart';
import 'features.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
import 'project.dart'; import 'project.dart';
import 'reporting/reporting.dart'; import 'reporting/reporting.dart';
...@@ -415,7 +414,6 @@ class HotRunner extends ResidentRunner { ...@@ -415,7 +414,6 @@ class HotRunner extends ResidentRunner {
sdkName: _sdkName!, sdkName: _sdkName!,
emulator: _emulator!, emulator: _emulator!,
fullRestart: false, fullRestart: false,
fastReassemble: false,
overallTimeInMs: appStartedTimer.elapsed.inMilliseconds, overallTimeInMs: appStartedTimer.elapsed.inMilliseconds,
compileTimeInMs: totalCompileTime.inMilliseconds, compileTimeInMs: totalCompileTime.inMilliseconds,
transferTimeInMs: totalLaunchAppTime.inMilliseconds, transferTimeInMs: totalLaunchAppTime.inMilliseconds,
...@@ -802,7 +800,6 @@ class HotRunner extends ResidentRunner { ...@@ -802,7 +800,6 @@ class HotRunner extends ResidentRunner {
emulator: emulator!, emulator: emulator!,
fullRestart: true, fullRestart: true,
reason: reason, reason: reason,
fastReassemble: false,
overallTimeInMs: restartTimer.elapsed.inMilliseconds, overallTimeInMs: restartTimer.elapsed.inMilliseconds,
syncedBytes: result.updateFSReport?.syncedBytes, syncedBytes: result.updateFSReport?.syncedBytes,
invalidatedSourcesCount: result.updateFSReport?.invalidatedSourcesCount, invalidatedSourcesCount: result.updateFSReport?.invalidatedSourcesCount,
...@@ -828,7 +825,6 @@ class HotRunner extends ResidentRunner { ...@@ -828,7 +825,6 @@ class HotRunner extends ResidentRunner {
emulator: emulator!, emulator: emulator!,
fullRestart: true, fullRestart: true,
reason: reason, reason: reason,
fastReassemble: false,
).send(); ).send();
} }
status?.cancel(); status?.cancel();
...@@ -878,7 +874,6 @@ class HotRunner extends ResidentRunner { ...@@ -878,7 +874,6 @@ class HotRunner extends ResidentRunner {
emulator: emulator!, emulator: emulator!,
fullRestart: false, fullRestart: false,
reason: reason, reason: reason,
fastReassemble: false,
).send(); ).send();
} else { } else {
HotEvent('exception', HotEvent('exception',
...@@ -887,7 +882,6 @@ class HotRunner extends ResidentRunner { ...@@ -887,7 +882,6 @@ class HotRunner extends ResidentRunner {
emulator: emulator!, emulator: emulator!,
fullRestart: false, fullRestart: false,
reason: reason, reason: reason,
fastReassemble: false,
).send(); ).send();
} }
return OperationResult(errorCode, errorMessage, fatal: true); return OperationResult(errorCode, errorMessage, fatal: true);
...@@ -971,7 +965,6 @@ class HotRunner extends ResidentRunner { ...@@ -971,7 +965,6 @@ class HotRunner extends ResidentRunner {
viewCache, viewCache,
onSlow, onSlow,
reloadMessage, reloadMessage,
updatedDevFS.fastReassembleClassName,
); );
shouldReportReloadTime = reassembleResult.shouldReportReloadTime; shouldReportReloadTime = reassembleResult.shouldReportReloadTime;
if (reassembleResult.reassembleViews.isEmpty) { if (reassembleResult.reassembleViews.isEmpty) {
...@@ -1005,7 +998,6 @@ class HotRunner extends ResidentRunner { ...@@ -1005,7 +998,6 @@ class HotRunner extends ResidentRunner {
syncedBytes: updatedDevFS.syncedBytes, syncedBytes: updatedDevFS.syncedBytes,
invalidatedSourcesCount: updatedDevFS.invalidatedSourcesCount, invalidatedSourcesCount: updatedDevFS.invalidatedSourcesCount,
transferTimeInMs: updatedDevFS.transferDuration.inMilliseconds, transferTimeInMs: updatedDevFS.transferDuration.inMilliseconds,
fastReassemble: featureFlags.isSingleWidgetReloadEnabled && updatedDevFS.fastReassembleClassName != null,
compileTimeInMs: updatedDevFS.compileDuration.inMilliseconds, compileTimeInMs: updatedDevFS.compileDuration.inMilliseconds,
findInvalidatedTimeInMs: updatedDevFS.findInvalidatedDuration.inMilliseconds, findInvalidatedTimeInMs: updatedDevFS.findInvalidatedDuration.inMilliseconds,
scannedSourcesCount: updatedDevFS.scannedSourcesCount, scannedSourcesCount: updatedDevFS.scannedSourcesCount,
...@@ -1225,7 +1217,6 @@ Future<OperationResult> defaultReloadSourcesHelper( ...@@ -1225,7 +1217,6 @@ Future<OperationResult> defaultReloadSourcesHelper(
emulator: emulator!, emulator: emulator!,
fullRestart: false, fullRestart: false,
reason: reason, reason: reason,
fastReassemble: false,
usage: usage, usage: usage,
).send(); ).send();
// Reset devFS lastCompileTime to ensure the file will still be marked // Reset devFS lastCompileTime to ensure the file will still be marked
...@@ -1288,7 +1279,6 @@ typedef ReassembleHelper = Future<ReassembleResult> Function( ...@@ -1288,7 +1279,6 @@ typedef ReassembleHelper = Future<ReassembleResult> Function(
Map<FlutterDevice?, List<FlutterView>> viewCache, Map<FlutterDevice?, List<FlutterView>> viewCache,
void Function(String message)? onSlow, void Function(String message)? onSlow,
String reloadMessage, String reloadMessage,
String? fastReassembleClassName,
); );
Future<ReassembleResult> _defaultReassembleHelper( Future<ReassembleResult> _defaultReassembleHelper(
...@@ -1296,7 +1286,6 @@ Future<ReassembleResult> _defaultReassembleHelper( ...@@ -1296,7 +1286,6 @@ Future<ReassembleResult> _defaultReassembleHelper(
Map<FlutterDevice?, List<FlutterView>> viewCache, Map<FlutterDevice?, List<FlutterView>> viewCache,
void Function(String message)? onSlow, void Function(String message)? onSlow,
String reloadMessage, String reloadMessage,
String? fastReassembleClassName,
) async { ) async {
// Check if any isolates are paused and reassemble those that aren't. // Check if any isolates are paused and reassemble those that aren't.
final Map<FlutterView, FlutterVmService?> reassembleViews = <FlutterView, FlutterVmService?>{}; final Map<FlutterView, FlutterVmService?> reassembleViews = <FlutterView, FlutterVmService?>{};
...@@ -1325,17 +1314,9 @@ Future<ReassembleResult> _defaultReassembleHelper( ...@@ -1325,17 +1314,9 @@ Future<ReassembleResult> _defaultReassembleHelper(
reassembleViews[view] = device.vmService; reassembleViews[view] = device.vmService;
// If the tool identified a change in a single widget, do a fast instead // If the tool identified a change in a single widget, do a fast instead
// of a full reassemble. // of a full reassemble.
Future<void> reassembleWork; final Future<void> reassembleWork = device.vmService!.flutterReassemble(
if (fastReassembleClassName != null) { isolateId: view.uiIsolate!.id!,
reassembleWork = device.vmService!.flutterFastReassemble( );
isolateId: view.uiIsolate!.id!,
className: fastReassembleClassName,
);
} else {
reassembleWork = device.vmService!.flutterReassemble(
isolateId: view.uiIsolate!.id!,
);
}
reassembleFutures.add(reassembleWork.then( reassembleFutures.add(reassembleWork.then(
(Object? obj) => obj, (Object? obj) => obj,
onError: (Object error, StackTrace stackTrace) { onError: (Object error, StackTrace stackTrace) {
......
...@@ -809,19 +809,6 @@ class FlutterVmService { ...@@ -809,19 +809,6 @@ class FlutterVmService {
); );
} }
Future<Map<String, Object?>?> flutterFastReassemble({
required String isolateId,
required String className,
}) {
return invokeFlutterExtensionRpcRaw(
'ext.flutter.fastReassemble',
isolateId: isolateId,
args: <String, Object>{
'className': className,
},
);
}
Future<bool> flutterAlreadyPaintedFirstUsefulFrame({ Future<bool> flutterAlreadyPaintedFirstUsefulFrame({
required String isolateId, required String isolateId,
}) async { }) async {
......
...@@ -118,14 +118,14 @@ void main() { ...@@ -118,14 +118,14 @@ void main() {
ProcessManager: () => FakeProcessManager.any(), 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 FileSystem fileSystem = MemoryFileSystem.test();
final Config config = Config.test(); final Config config = Config.test();
expect(getDefaultCachedKernelPath( expect(getDefaultCachedKernelPath(
trackWidgetCreation: true, trackWidgetCreation: true,
dartDefines: <String>[], dartDefines: <String>[],
extraFrontEndOptions: <String>['--enable-experiment=foo', '--flutter-widget-cache'], extraFrontEndOptions: <String>['--enable-experiment=foo'],
fileSystem: fileSystem, fileSystem: fileSystem,
config: config, config: config,
), 'build/cache.dill.track.dill'); ), 'build/cache.dill.track.dill');
...@@ -133,7 +133,7 @@ void main() { ...@@ -133,7 +133,7 @@ void main() {
expect(getDefaultCachedKernelPath( expect(getDefaultCachedKernelPath(
trackWidgetCreation: true, trackWidgetCreation: true,
dartDefines: <String>['foo=bar'], dartDefines: <String>['foo=bar'],
extraFrontEndOptions: <String>['--enable-experiment=foo', '--flutter-widget-cache'], extraFrontEndOptions: <String>['--enable-experiment=foo'],
fileSystem: fileSystem, fileSystem: fileSystem,
config: config, config: config,
), 'build/06ad47d8e64bd28de537b62ff85357c4.cache.dill.track.dill'); ), 'build/06ad47d8e64bd28de537b62ff85357c4.cache.dill.track.dill');
...@@ -141,7 +141,7 @@ void main() { ...@@ -141,7 +141,7 @@ void main() {
expect(getDefaultCachedKernelPath( expect(getDefaultCachedKernelPath(
trackWidgetCreation: false, trackWidgetCreation: false,
dartDefines: <String>[], dartDefines: <String>[],
extraFrontEndOptions: <String>['--enable-experiment=foo', '--flutter-widget-cache'], extraFrontEndOptions: <String>['--enable-experiment=foo'],
fileSystem: fileSystem, fileSystem: fileSystem,
config: config, config: config,
), 'build/cache.dill'); ), 'build/cache.dill');
...@@ -149,7 +149,7 @@ void main() { ...@@ -149,7 +149,7 @@ void main() {
expect(getDefaultCachedKernelPath( expect(getDefaultCachedKernelPath(
trackWidgetCreation: true, trackWidgetCreation: true,
dartDefines: <String>[], dartDefines: <String>[],
extraFrontEndOptions: <String>['--enable-experiment=foo', '--flutter-widget-cache', '--foo=bar'], extraFrontEndOptions: <String>['--enable-experiment=foo', '--foo=bar'],
fileSystem: fileSystem, fileSystem: fileSystem,
config: config, config: config,
), 'build/95b595cca01caa5f0ca0a690339dd7f6.cache.dill.track.dill'); ), 'build/95b595cca01caa5f0ca0a690339dd7f6.cache.dill.track.dill');
......
...@@ -178,7 +178,6 @@ void main() { ...@@ -178,7 +178,6 @@ void main() {
Map<FlutterDevice?, List<FlutterView>> viewCache, Map<FlutterDevice?, List<FlutterView>> viewCache,
void Function(String message)? onSlow, void Function(String message)? onSlow,
String reloadMessage, String reloadMessage,
String? fastReassembleClassName,
) async => ReassembleResult( ) async => ReassembleResult(
<FlutterView?, FlutterVmService?>{null: null}, <FlutterView?, FlutterVmService?>{null: null},
false, false,
...@@ -296,7 +295,6 @@ void main() { ...@@ -296,7 +295,6 @@ void main() {
hotEventSdkName: 'Tester', hotEventSdkName: 'Tester',
hotEventEmulator: false, hotEventEmulator: false,
hotEventFullRestart: true, hotEventFullRestart: true,
fastReassemble: false,
hotEventOverallTimeInMs: 64000, hotEventOverallTimeInMs: 64000,
hotEventSyncedBytes: 4, hotEventSyncedBytes: 4,
hotEventInvalidatedSourcesCount: 2, hotEventInvalidatedSourcesCount: 2,
...@@ -379,7 +377,6 @@ void main() { ...@@ -379,7 +377,6 @@ void main() {
Map<FlutterDevice?, List<FlutterView>> viewCache, Map<FlutterDevice?, List<FlutterView>> viewCache,
void Function(String message)? onSlow, void Function(String message)? onSlow,
String reloadMessage, String reloadMessage,
String? fastReassembleClassName,
) async => ReassembleResult( ) async => ReassembleResult(
<FlutterView?, FlutterVmService?>{null: null}, <FlutterView?, FlutterVmService?>{null: null},
false, false,
...@@ -402,7 +399,6 @@ void main() { ...@@ -402,7 +399,6 @@ void main() {
hotEventSdkName: 'Tester', hotEventSdkName: 'Tester',
hotEventEmulator: false, hotEventEmulator: false,
hotEventFullRestart: false, hotEventFullRestart: false,
fastReassemble: false,
hotEventCompileTimeInMs: 16000, hotEventCompileTimeInMs: 16000,
hotEventFindInvalidatedTimeInMs: 64000, hotEventFindInvalidatedTimeInMs: 64000,
hotEventScannedSourcesCount: 16, hotEventScannedSourcesCount: 16,
......
...@@ -25,7 +25,6 @@ import 'package:flutter_tools/src/convert.dart'; ...@@ -25,7 +25,6 @@ import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/device_port_forwarder.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/globals.dart' as globals;
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
...@@ -424,7 +423,6 @@ void main() { ...@@ -424,7 +423,6 @@ void main() {
hotEventSdkName: 'Android', hotEventSdkName: 'Android',
hotEventEmulator: false, hotEventEmulator: false,
hotEventFullRestart: false, hotEventFullRestart: false,
fastReassemble: false,
)), )),
)); ));
expect(fakeVmServiceHost?.hasRemainingExpectations, false); expect(fakeVmServiceHost?.hasRemainingExpectations, false);
...@@ -480,7 +478,6 @@ void main() { ...@@ -480,7 +478,6 @@ void main() {
hotEventSdkName: 'Android', hotEventSdkName: 'Android',
hotEventEmulator: false, hotEventEmulator: false,
hotEventFullRestart: false, hotEventFullRestart: false,
fastReassemble: false,
)), )),
)); ));
expect(fakeVmServiceHost?.hasRemainingExpectations, false); expect(fakeVmServiceHost?.hasRemainingExpectations, false);
...@@ -527,7 +524,6 @@ void main() { ...@@ -527,7 +524,6 @@ void main() {
hotEventSdkName: 'Android', hotEventSdkName: 'Android',
hotEventEmulator: false, hotEventEmulator: false,
hotEventFullRestart: false, hotEventFullRestart: false,
fastReassemble: false,
)), )),
)); ));
expect(fakeVmServiceHost?.hasRemainingExpectations, false); expect(fakeVmServiceHost?.hasRemainingExpectations, false);
...@@ -766,96 +762,6 @@ void main() { ...@@ -766,96 +762,6 @@ void main() {
Usage: () => TestUsage(), Usage: () => TestUsage(),
})); }));
testUsingContext('ResidentRunner can perform fast reassemble', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
listViews,
FakeVmServiceRequest(
method: 'getVM',
jsonResponse: fakeVM.toJson(),
),
listViews,
listViews,
FakeVmServiceRequest(
method: 'getVM',
jsonResponse: fakeVM.toJson(),
),
const FakeVmServiceRequest(
method: kReloadSourcesServiceName,
args: <String, Object>{
'isolateId': '1',
'pause': false,
'rootLibUri': 'main.dart.incremental.dill',
},
jsonResponse: <String, Object>{
'type': 'ReloadReport',
'success': true,
'details': <String, Object>{
'loadedLibraryCount': 1,
},
},
),
FakeVmServiceRequest(
method: 'getIsolatePauseEvent',
args: <String, Object>{
'isolateId': '1',
},
jsonResponse: fakeUnpausedEvent.toJson(),
),
FakeVmServiceRequest(
method: 'ext.flutter.fastReassemble',
args: <String, Object?>{
'isolateId': fakeUnpausedIsolate.id,
'className': 'FOO',
},
),
]);
final FakeDelegateFlutterDevice flutterDevice = FakeDelegateFlutterDevice(
device,
BuildInfo.debug,
FakeResidentCompiler(),
devFS,
)..vmService = fakeVmServiceHost!.vmService;
residentRunner = HotRunner(
<FlutterDevice>[
flutterDevice,
],
stayResident: false,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
target: 'main.dart',
devtoolsHandler: createNoOpHandler,
);
devFS.nextUpdateReport = UpdateFSReport(
success: true,
fastReassembleClassName: 'FOO',
invalidatedSourcesCount: 1,
);
final Completer<DebugConnectionInfo> futureConnectionInfo = Completer<DebugConnectionInfo>.sync();
final Completer<void> futureAppStart = Completer<void>.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: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
Platform: () => FakePlatform(),
ProjectFileInvalidator: () => FakeProjectFileInvalidator(),
Usage: () => TestUsage(),
FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true),
}));
testUsingContext('ResidentRunner reports hot reload time details', () => testbed.run(() async { testUsingContext('ResidentRunner reports hot reload time details', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
listViews, listViews,
...@@ -893,10 +799,9 @@ void main() { ...@@ -893,10 +799,9 @@ void main() {
jsonResponse: fakeUnpausedEvent.toJson(), jsonResponse: fakeUnpausedEvent.toJson(),
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
method: 'ext.flutter.fastReassemble', method: 'ext.flutter.reassemble',
args: <String, Object?>{ args: <String, Object?>{
'isolateId': fakeUnpausedIsolate.id, 'isolateId': fakeUnpausedIsolate.id,
'className': 'FOO',
}, },
), ),
]); ]);
...@@ -917,7 +822,6 @@ void main() { ...@@ -917,7 +822,6 @@ void main() {
); );
devFS.nextUpdateReport = UpdateFSReport( devFS.nextUpdateReport = UpdateFSReport(
success: true, success: true,
fastReassembleClassName: 'FOO',
invalidatedSourcesCount: 1, invalidatedSourcesCount: 1,
); );
...@@ -942,7 +846,6 @@ void main() { ...@@ -942,7 +846,6 @@ void main() {
Platform: () => FakePlatform(), Platform: () => FakePlatform(),
ProjectFileInvalidator: () => FakeProjectFileInvalidator(), ProjectFileInvalidator: () => FakeProjectFileInvalidator(),
Usage: () => TestUsage(), Usage: () => TestUsage(),
FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true),
})); }));
testUsingContext('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async { testUsingContext('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async {
...@@ -1225,7 +1128,6 @@ void main() { ...@@ -1225,7 +1128,6 @@ void main() {
hotEventSdkName: 'Android', hotEventSdkName: 'Android',
hotEventEmulator: false, hotEventEmulator: false,
hotEventFullRestart: true, hotEventFullRestart: true,
fastReassemble: false,
)), )),
)); ));
expect(fakeVmServiceHost?.hasRemainingExpectations, false); expect(fakeVmServiceHost?.hasRemainingExpectations, false);
...@@ -1984,31 +1886,7 @@ flutter: ...@@ -1984,31 +1886,7 @@ flutter:
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('FlutterDevice passes flutter-widget-cache flag when feature is enabled', () async { testUsingContext('FlutterDevice passes alternative-invalidation-strategy flag', () async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice();
final DefaultResidentCompiler? residentCompiler = (await FlutterDevice.create(
device,
buildInfo: const BuildInfo(
BuildMode.debug,
'',
treeShakeIcons: false,
extraFrontEndOptions: <String>[],
),
target: null, platform: FakePlatform(),
)).generator as DefaultResidentCompiler?;
expect(residentCompiler!.extraFrontEndOptions,
contains('--flutter-widget-cache'));
}, overrides: <Type, Generator>{
Artifacts: () => Artifacts.test(),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => TestFeatureFlags(isSingleWidgetReloadEnabled: true),
});
testUsingContext('FlutterDevice passes alternative-invalidation-strategy flag', () async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]); fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice(); final FakeDevice device = FakeDevice();
...@@ -2032,7 +1910,7 @@ flutter: ...@@ -2032,7 +1910,7 @@ flutter:
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('FlutterDevice passes initializeFromDill parameter if specified', () async { testUsingContext('FlutterDevice passes initializeFromDill parameter if specified', () async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]); fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final FakeDevice device = FakeDevice(); final FakeDevice device = FakeDevice();
......
// 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<String> 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<String> 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();
}
});
}
// 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,
);
}
}
...@@ -90,7 +90,6 @@ abstract class FlutterTestDriver { ...@@ -90,7 +90,6 @@ abstract class FlutterTestDriver {
List<String> arguments, { List<String> arguments, {
String? script, String? script,
bool withDebugger = false, bool withDebugger = false,
bool singleWidgetReloads = false,
}) async { }) async {
final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter'); final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
if (withDebugger) { if (withDebugger) {
...@@ -114,8 +113,6 @@ abstract class FlutterTestDriver { ...@@ -114,8 +113,6 @@ abstract class FlutterTestDriver {
environment: <String, String>{ environment: <String, String>{
'FLUTTER_TEST': 'true', 'FLUTTER_TEST': 'true',
'FLUTTER_WEB': 'true', 'FLUTTER_WEB': 'true',
if (singleWidgetReloads)
'FLUTTER_SINGLE_WIDGET_RELOAD': 'true',
}, },
); );
...@@ -511,7 +508,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -511,7 +508,6 @@ class FlutterRunTestDriver extends FlutterTestDriver {
bool chrome = false, bool chrome = false,
bool expressionEvaluation = true, bool expressionEvaluation = true,
bool structuredErrors = false, bool structuredErrors = false,
bool singleWidgetReloads = false,
bool serveObservatory = false, bool serveObservatory = false,
String? script, String? script,
List<String>? additionalCommandArgs, List<String>? additionalCommandArgs,
...@@ -542,7 +538,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -542,7 +538,6 @@ class FlutterRunTestDriver extends FlutterTestDriver {
startPaused: startPaused, startPaused: startPaused,
pauseOnExceptions: pauseOnExceptions, pauseOnExceptions: pauseOnExceptions,
script: script, script: script,
singleWidgetReloads: singleWidgetReloads,
); );
} }
...@@ -551,7 +546,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -551,7 +546,6 @@ class FlutterRunTestDriver extends FlutterTestDriver {
bool withDebugger = false, bool withDebugger = false,
bool startPaused = false, bool startPaused = false,
bool pauseOnExceptions = false, bool pauseOnExceptions = false,
bool singleWidgetReloads = false,
bool serveObservatory = false, bool serveObservatory = false,
List<String>? additionalCommandArgs, List<String>? additionalCommandArgs,
}) async { }) async {
...@@ -573,7 +567,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -573,7 +567,6 @@ class FlutterRunTestDriver extends FlutterTestDriver {
withDebugger: withDebugger, withDebugger: withDebugger,
startPaused: startPaused, startPaused: startPaused,
pauseOnExceptions: pauseOnExceptions, pauseOnExceptions: pauseOnExceptions,
singleWidgetReloads: singleWidgetReloads,
attachPort: port, attachPort: port,
); );
} }
...@@ -585,7 +578,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -585,7 +578,6 @@ class FlutterRunTestDriver extends FlutterTestDriver {
bool withDebugger = false, bool withDebugger = false,
bool startPaused = false, bool startPaused = false,
bool pauseOnExceptions = false, bool pauseOnExceptions = false,
bool singleWidgetReloads = false,
int? attachPort, int? attachPort,
}) async { }) async {
assert(!startPaused || withDebugger); assert(!startPaused || withDebugger);
...@@ -593,7 +585,6 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -593,7 +585,6 @@ class FlutterRunTestDriver extends FlutterTestDriver {
args, args,
script: script, script: script,
withDebugger: withDebugger, withDebugger: withDebugger,
singleWidgetReloads: singleWidgetReloads,
); );
final Completer<void> prematureExitGuard = Completer<void>(); final Completer<void> prematureExitGuard = Completer<void>();
...@@ -806,13 +797,11 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -806,13 +797,11 @@ class FlutterTestTestDriver extends FlutterTestDriver {
bool withDebugger = false, bool withDebugger = false,
bool pauseOnExceptions = false, bool pauseOnExceptions = false,
Future<void> Function()? beforeStart, Future<void> Function()? beforeStart,
bool singleWidgetReloads = false,
}) async { }) async {
await super._setupProcess( await super._setupProcess(
args, args,
script: script, script: script,
withDebugger: withDebugger, withDebugger: withDebugger,
singleWidgetReloads: singleWidgetReloads,
); );
// Stash the PID so that we can terminate the VM more reliably than using // Stash the PID so that we can terminate the VM more reliably than using
......
...@@ -443,7 +443,6 @@ class TestFeatureFlags implements FeatureFlags { ...@@ -443,7 +443,6 @@ class TestFeatureFlags implements FeatureFlags {
this.isMacOSEnabled = false, this.isMacOSEnabled = false,
this.isWebEnabled = false, this.isWebEnabled = false,
this.isWindowsEnabled = false, this.isWindowsEnabled = false,
this.isSingleWidgetReloadEnabled = false,
this.isAndroidEnabled = true, this.isAndroidEnabled = true,
this.isIOSEnabled = true, this.isIOSEnabled = true,
this.isFuchsiaEnabled = false, this.isFuchsiaEnabled = false,
...@@ -463,9 +462,6 @@ class TestFeatureFlags implements FeatureFlags { ...@@ -463,9 +462,6 @@ class TestFeatureFlags implements FeatureFlags {
@override @override
final bool isWindowsEnabled; final bool isWindowsEnabled;
@override
final bool isSingleWidgetReloadEnabled;
@override @override
final bool isAndroidEnabled; final bool isAndroidEnabled;
...@@ -492,8 +488,6 @@ class TestFeatureFlags implements FeatureFlags { ...@@ -492,8 +488,6 @@ class TestFeatureFlags implements FeatureFlags {
return isMacOSEnabled; return isMacOSEnabled;
case flutterWindowsDesktopFeature: case flutterWindowsDesktopFeature:
return isWindowsEnabled; return isWindowsEnabled;
case singleWidgetReload:
return isSingleWidgetReloadEnabled;
case flutterAndroidFeature: case flutterAndroidFeature:
return isAndroidEnabled; return isAndroidEnabled;
case flutterIOSFeature: case flutterIOSFeature:
......
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