[flutter_tools] only copy cached dill after startup (#58188)
Remove copying from the shutdown stage since that seems risky. If the tool copies the first compilation there will still be a decent dill for initialization.
diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
index 0ecb2d6..b4cd7a4 100644
--- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -434,6 +434,7 @@
return 1;
}
device.generator.accept();
+ cacheInitialDillCompilation();
} else {
await buildWeb(
flutterProject,
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index b7ced11..00b9f7f 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -1099,6 +1099,19 @@
);
}
+ @protected
+ void cacheInitialDillCompilation() {
+ globals.logger.printTrace('Caching compiled dill');
+ final File outputDill = globals.fs.file(dillOutputPath);
+ if (outputDill.existsSync()) {
+ final String copyPath = getDefaultCachedKernelPath(
+ trackWidgetCreation: trackWidgetCreation,
+ );
+ globals.fs.file(copyPath).parent.createSync(recursive: true);
+ outputDill.copySync(copyPath);
+ }
+ }
+
/// If the [reloadSources] parameter is not null the 'reloadSources' service
/// will be registered.
//
@@ -1208,14 +1221,9 @@
@mustCallSuper
Future<void> preExit() async {
- // If _dillOutputPath is null, we created a temporary directory for the dill.
+ // If _dillOutputPath is null, the tool created a temporary directory for
+ // the dill.
if (_dillOutputPath == null && artifactDirectory.existsSync()) {
- final File outputDill = globals.fs.file(dillOutputPath);
- if (outputDill.existsSync()) {
- outputDill.copySync(getDefaultCachedKernelPath(
- trackWidgetCreation: trackWidgetCreation,
- ));
- }
artifactDirectory.deleteSync(recursive: true);
}
}
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index 76fc6e2..1c7793c 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -63,7 +63,6 @@
List<vm_service.ReloadReport> reports; // List has one report per Flutter view.
}
-// TODO(mklim): Test this, flutter/flutter#23031.
class HotRunner extends ResidentRunner {
HotRunner(
List<FlutterDevice> devices, {
@@ -388,6 +387,7 @@
if (!results.every((bool passed) => passed)) {
return 1;
}
+ cacheInitialDillCompilation();
} on Exception catch (err) {
globals.printError(err.toString());
return 1;
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 319df1a..9ab5636 100644
--- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
@@ -521,22 +521,12 @@
expect(otherRunner.artifactDirectory.path, contains('foobar'));
}));
- test('ResidentRunner copies output dill to cache location during preExit', () => testbed.run(() async {
+ test('ResidentRunner deletes artifact directory on preExit', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
- residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('hello');
+ residentRunner.artifactDirectory.childFile('app.dill').createSync();
await residentRunner.preExit();
- final File cacheDill = globals.fs.file(globals.fs.path.join(getBuildDirectory(), 'cache.dill'));
- expect(cacheDill, exists);
- expect(cacheDill.readAsStringSync(), 'hello');
- }));
-
- test('ResidentRunner handles output dill missing during preExit', () => testbed.run(() async {
- fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
- await residentRunner.preExit();
- final File cacheDill = globals.fs.file(globals.fs.path.join(getBuildDirectory(), 'cache.dill'));
-
- expect(cacheDill, isNot(exists));
+ expect(residentRunner.artifactDirectory, isNot(exists));
}));
test('ResidentRunner can run source generation', () => testbed.run(() async {
@@ -1060,6 +1050,64 @@
expect(await globals.fs.file('foo').readAsString(), testUri.toString());
}));
+ test('HotRunner copies compiled app.dill to cache during startup', () => testbed.run(() async {
+ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
+ listViews,
+ listViews,
+ ]);
+ setWsAddress(testUri, fakeVmServiceHost.vmService);
+ globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
+ residentRunner = HotRunner(
+ <FlutterDevice>[
+ mockFlutterDevice,
+ ],
+ stayResident: false,
+ debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
+ );
+ residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
+ when(mockFlutterDevice.runHot(
+ hotRunner: anyNamed('hotRunner'),
+ route: anyNamed('route'),
+ )).thenAnswer((Invocation invocation) async {
+ return 0;
+ });
+ await residentRunner.run();
+
+ expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill')).readAsString(), 'ABC');
+ }));
+
+ test('HotRunner copies compiled app.dill to cache during startup with --track-widget-creation', () => testbed.run(() async {
+ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
+ listViews,
+ listViews,
+ ]);
+ setWsAddress(testUri, fakeVmServiceHost.vmService);
+ globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
+ residentRunner = HotRunner(
+ <FlutterDevice>[
+ mockFlutterDevice,
+ ],
+ stayResident: false,
+ debuggingOptions: DebuggingOptions.enabled(const BuildInfo(
+ BuildMode.debug,
+ '',
+ treeShakeIcons: false,
+ trackWidgetCreation: true,
+ )),
+ );
+ residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
+ when(mockFlutterDevice.runHot(
+ hotRunner: anyNamed('hotRunner'),
+ route: anyNamed('route'),
+ )).thenAnswer((Invocation invocation) async {
+ return 0;
+ });
+ await residentRunner.run();
+
+ expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill.track.dill')).readAsString(), 'ABC');
+ }));
+
+
test('HotRunner unforwards device ports', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
listViews,
diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
index 7a30f97..aca6cec 100644
--- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
@@ -257,13 +257,21 @@
expect(bufferLogger.statusText, contains('Debug service listening on ws://127.0.0.1/abcd/'));
expect(debugConnectionInfo.wsUri.toString(), 'ws://127.0.0.1/abcd/');
}, overrides: <Type, Generator>{
- Logger: () => DelegateLogger(BufferLogger(
- terminal: AnsiTerminal(
- stdio: null,
- platform: const LocalPlatform(),
- ),
- outputPreferences: OutputPreferences.test(),
- )),
+ Logger: () => DelegateLogger(BufferLogger.test()),
+ }));
+
+ test('WebRunner copies compiled app.dill to cache during startup', () => testbed.run(() async {
+ fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations.toList());
+ _setupMocks();
+
+ residentWebRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('ABC');
+ final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
+ unawaited(residentWebRunner.run(
+ connectionInfoCompleter: connectionInfoCompleter,
+ ));
+ await connectionInfoCompleter.future;
+
+ expect(await globals.fs.file(globals.fs.path.join('build', 'cache.dill')).readAsString(), 'ABC');
}));
test('Can successfully run without an index.html including status warning', () => testbed.run(() async {