Revert "[flutter_tools] initialize frontend server with build (#49405)" (#51476)
This reverts commit 59cc3cdf0167740b51236f5eb5571c6bf3345d6f.
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 469f73e..606d5b2 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -469,6 +469,7 @@
// See: https://github.com/flutter/flutter/issues/50494
void addFileSystemRoot(String root);
+
/// If invoked for the first time, it compiles Dart script identified by
/// [mainPath], [invalidatedFiles] list is ignored.
/// On successive runs [invalidatedFiles] indicates which files need to be
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index b985bff..3400c82 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -488,9 +488,6 @@
if (fullRestart) {
generator.reset();
}
- // On a full restart, or on an initial compile for the attach based workflow,
- // this will produce a full dill. Subsequent invocations will produce incremental
- // dill files that depend on the invalidated files.
globals.printTrace('Compiling dart to kernel with ${invalidatedFiles.length} updated files');
final CompilerOutput compilerOutput = await generator.recompile(
mainPath,
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index d24e3c7..b58487e 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -629,6 +629,16 @@
if (!artifactDirectory.existsSync()) {
artifactDirectory.createSync(recursive: true);
}
+ // TODO(jonahwilliams): this is a temporary work around to regain some of
+ // the initialize from dill performance. Longer term, we should have a
+ // better way to determine where the appropriate dill file is, as this
+ // doesn't work for Android or macOS builds.}
+ if (dillOutputPath == null) {
+ final File existingDill = globals.fs.file(globals.fs.path.join('build', 'app.dill'));
+ if (existingDill.existsSync()) {
+ existingDill.copySync(globals.fs.path.join(artifactDirectory.path, 'app.dill'));
+ }
+ }
}
@protected
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index 32f98a6..67a93d3 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -16,7 +16,6 @@
import 'base/logger.dart';
import 'base/utils.dart';
import 'build_info.dart';
-import 'bundle.dart';
import 'compile.dart';
import 'convert.dart';
import 'devfs.dart';
@@ -330,36 +329,14 @@
firstBuildTime = DateTime.now();
- final List<Future<bool>> startupTasks = <Future<bool>>[];
for (final FlutterDevice device in flutterDevices) {
- // Here we initialize the frontend_server concurrently with the platform
- // build, reducing overall initialization time. This is safe because the first
- // invocation of the frontend server produces a full dill file that the
- // subsequent invocation in devfs will not overwrite.
- if (device.generator != null) {
- startupTasks.add(
- device.generator.recompile(
- mainPath,
- <Uri>[],
- outputPath: dillOutputPath ??
- getDefaultApplicationKernelPath(trackWidgetCreation: device.trackWidgetCreation),
- packagesFilePath : packagesFilePath,
- ).then((CompilerOutput output) => output?.errorCount == 0)
- );
- }
- startupTasks.add(device.runHot(
+ final int result = await device.runHot(
hotRunner: this,
route: route,
- ).then((int result) => result == 0));
- }
- try {
- final List<bool> results = await Future.wait(startupTasks);
- if (!results.every((bool passed) => passed)) {
- return 1;
+ );
+ if (result != 0) {
+ return result;
}
- } on Exception catch (err) {
- globals.printError(err.toString());
- return 1;
}
return attach(
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
index 9a9535e..77f60ad 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
@@ -84,6 +84,47 @@
ProcessManager: () => FakeProcessManager.any(),
});
+ testUsingContext('Forces fast start off for devices that do not support it', () async {
+ final MockDevice mockDevice = MockDevice(TargetPlatform.android_arm);
+ when(mockDevice.name).thenReturn('mockdevice');
+ when(mockDevice.supportsFastStart).thenReturn(false);
+ when(mockDevice.supportsHotReload).thenReturn(true);
+ when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async => false);
+ when(deviceManager.hasSpecifiedAllDevices).thenReturn(false);
+ when(deviceManager.findTargetDevices(any)).thenAnswer((Invocation invocation) {
+ return Future<List<Device>>.value(<Device>[mockDevice]);
+ });
+ when(deviceManager.getDevices()).thenAnswer((Invocation invocation) {
+ return Future<List<Device>>.value(<Device>[mockDevice]);
+ });
+ globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
+ globals.fs.file('pubspec.yaml').createSync();
+ globals.fs.file('.packages').createSync();
+
+ final RunCommand command = RunCommand();
+ applyMocksToCommand(command);
+ try {
+ await createTestCommandRunner(command).run(<String>[
+ 'run',
+ '--fast-start',
+ '--no-pub',
+ ]);
+ fail('Expect exception');
+ } catch (e) {
+ expect(e, isA<ToolExit>());
+ }
+
+ final BufferLogger bufferLogger = globals.logger as BufferLogger;
+ expect(bufferLogger.statusText, isNot(contains(
+ 'Using --fast-start option with device mockdevice, but this device '
+ 'does not support it. Overriding the setting to false.'
+ )));
+ }, overrides: <Type, Generator>{
+ FileSystem: () => MemoryFileSystem(),
+ ProcessManager: () => FakeProcessManager.any(),
+ DeviceManager: () => MockDeviceManager(),
+ });
+
testUsingContext('Walks upward looking for a pubspec.yaml and succeeds if found', () async {
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages')
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 d570b08..f443115 100644
--- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
@@ -234,6 +234,10 @@
Usage: () => MockUsage(),
}));
+ test('ResidentRunner copies dill file from build output into temp directory', () => testbed.run(() async {
+ expect(residentRunner.artifactDirectory.childFile('app.dill').readAsStringSync(), 'ABC');
+ }));
+
test('ResidentRunner can send target platform to analytics from hot reload', () => testbed.run(() async {
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
return 'Example';
diff --git a/packages/flutter_tools/test/integration.shard/hot_reload_test.dart b/packages/flutter_tools/test/integration.shard/hot_reload_test.dart
index 612de2f..455e756 100644
--- a/packages/flutter_tools/test/integration.shard/hot_reload_test.dart
+++ b/packages/flutter_tools/test/integration.shard/hot_reload_test.dart
@@ -36,10 +36,10 @@
});
test('newly added code executes during hot reload', () async {
- final StringBuffer stdout = StringBuffer();
- final StreamSubscription<String> subscription = _flutter.stdout.listen(stdout.writeln);
await _flutter.run();
_project.uncommentHotReloadPrint();
+ final StringBuffer stdout = StringBuffer();
+ final StreamSubscription<String> subscription = _flutter.stdout.listen(stdout.writeln);
try {
await _flutter.hotReload();
expect(stdout.toString(), contains('(((((RELOAD WORKED)))))'));
@@ -49,10 +49,10 @@
});
test('reloadMethod triggers hot reload behavior', () async {
- final StringBuffer stdout = StringBuffer();
- final StreamSubscription<String> subscription = _flutter.stdout.listen(stdout.writeln);
await _flutter.run();
_project.uncommentHotReloadPrint();
+ final StringBuffer stdout = StringBuffer();
+ final StreamSubscription<String> subscription = _flutter.stdout.listen(stdout.writeln);
try {
final String libraryId = _project.buildBreakpointUri.toString();
await _flutter.reloadMethod(libraryId: libraryId, classId: 'MyApp');
@@ -72,6 +72,7 @@
test('breakpoints are hit after hot reload', () async {
Isolate isolate;
+ await _flutter.run(withDebugger: true, startPaused: true);
final Completer<void> sawTick1 = Completer<void>();
final Completer<void> sawTick3 = Completer<void>();
final Completer<void> sawDebuggerPausedMessage = Completer<void>();
@@ -91,7 +92,6 @@
}
},
);
- await _flutter.run(withDebugger: true, startPaused: true);
await _flutter.resume(); // we start paused so we can set up our TICK 1 listener before the app starts
unawaited(sawTick1.future.timeout(
const Duration(seconds: 5),
@@ -125,15 +125,16 @@
});
test("hot reload doesn't reassemble if paused", () async {
- final Completer<void> sawTick1 = Completer<void>();
+ await _flutter.run(withDebugger: true);
+ final Completer<void> sawTick2 = Completer<void>();
final Completer<void> sawTick3 = Completer<void>();
final Completer<void> sawDebuggerPausedMessage1 = Completer<void>();
final Completer<void> sawDebuggerPausedMessage2 = Completer<void>();
final StreamSubscription<String> subscription = _flutter.stdout.listen(
(String line) {
- if (line.contains('(((TICK 1)))')) {
- expect(sawTick1.isCompleted, isFalse);
- sawTick1.complete();
+ if (line.contains('((((TICK 2))))')) {
+ expect(sawTick2.isCompleted, isFalse);
+ sawTick2.complete();
}
if (line.contains('The application is paused in the debugger on a breakpoint.')) {
expect(sawDebuggerPausedMessage1.isCompleted, isFalse);
@@ -145,14 +146,13 @@
}
},
);
- await _flutter.run(withDebugger: true);
- await sawTick1.future;
await _flutter.addBreakpoint(
_project.buildBreakpointUri,
_project.buildBreakpointLine,
);
bool reloaded = false;
final Future<void> reloadFuture = _flutter.hotReload().then((void value) { reloaded = true; });
+ await sawTick2.future; // this should happen before it pauses
final Isolate isolate = await _flutter.waitForPause();
expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
expect(reloaded, isFalse);