Unverified Commit e934c2fc authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] reland: copy dill after startup (#58455)

* [flutter_tools] only copy cached dill after startup

* shared code

* cleanup artifact directory

* do not copy if dillOutputPath is given
parent 8b5326a9
...@@ -434,6 +434,7 @@ class _ResidentWebRunner extends ResidentWebRunner { ...@@ -434,6 +434,7 @@ class _ResidentWebRunner extends ResidentWebRunner {
return 1; return 1;
} }
device.generator.accept(); device.generator.accept();
cacheInitialDillCompilation();
} else { } else {
await buildWeb( await buildWeb(
flutterProject, flutterProject,
......
...@@ -1080,6 +1080,22 @@ abstract class ResidentRunner { ...@@ -1080,6 +1080,22 @@ abstract class ResidentRunner {
); );
} }
@protected
void cacheInitialDillCompilation() {
if (_dillOutputPath != null) {
return;
}
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 /// If the [reloadSources] parameter is not null the 'reloadSources' service
/// will be registered. /// will be registered.
// //
...@@ -1189,14 +1205,9 @@ abstract class ResidentRunner { ...@@ -1189,14 +1205,9 @@ abstract class ResidentRunner {
@mustCallSuper @mustCallSuper
Future<void> preExit() async { 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()) { if (_dillOutputPath == null && artifactDirectory.existsSync()) {
final File outputDill = globals.fs.file(dillOutputPath);
if (outputDill.existsSync()) {
outputDill.copySync(getDefaultCachedKernelPath(
trackWidgetCreation: trackWidgetCreation,
));
}
artifactDirectory.deleteSync(recursive: true); artifactDirectory.deleteSync(recursive: true);
} }
} }
......
...@@ -63,7 +63,6 @@ class DeviceReloadReport { ...@@ -63,7 +63,6 @@ class DeviceReloadReport {
List<vm_service.ReloadReport> reports; // List has one report per Flutter view. List<vm_service.ReloadReport> reports; // List has one report per Flutter view.
} }
// TODO(mklim): Test this, flutter/flutter#23031.
class HotRunner extends ResidentRunner { class HotRunner extends ResidentRunner {
HotRunner( HotRunner(
List<FlutterDevice> devices, { List<FlutterDevice> devices, {
...@@ -379,6 +378,7 @@ class HotRunner extends ResidentRunner { ...@@ -379,6 +378,7 @@ class HotRunner extends ResidentRunner {
if (!results.every((bool passed) => passed)) { if (!results.every((bool passed) => passed)) {
return 1; return 1;
} }
cacheInitialDillCompilation();
} on Exception catch (err) { } on Exception catch (err) {
globals.printError(err.toString()); globals.printError(err.toString());
return 1; return 1;
......
...@@ -608,22 +608,12 @@ void main() { ...@@ -608,22 +608,12 @@ void main() {
expect(otherRunner.artifactDirectory.path, contains('foobar')); 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>[]); fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
residentRunner.artifactDirectory.childFile('app.dill').writeAsStringSync('hello'); residentRunner.artifactDirectory.childFile('app.dill').createSync();
await residentRunner.preExit(); await residentRunner.preExit();
final File cacheDill = globals.fs.file(globals.fs.path.join(getBuildDirectory(), 'cache.dill'));
expect(cacheDill, exists); expect(residentRunner.artifactDirectory, isNot(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));
})); }));
test('ResidentRunner can run source generation', () => testbed.run(() async { test('ResidentRunner can run source generation', () => testbed.run(() async {
...@@ -1147,6 +1137,91 @@ void main() { ...@@ -1147,6 +1137,91 @@ void main() {
expect(await globals.fs.file('foo').readAsString(), testUri.toString()); 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 does not copy app.dill if a dillOutputPath is given', () => 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,
dillOutputPath: 'test',
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(globals.fs.file(globals.fs.path.join('build', 'cache.dill')), isNot(exists));
}));
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 { test('HotRunner unforwards device ports', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
listViews, listViews,
......
...@@ -257,13 +257,21 @@ void main() { ...@@ -257,13 +257,21 @@ void main() {
expect(bufferLogger.statusText, contains('Debug service listening on ws://127.0.0.1/abcd/')); expect(bufferLogger.statusText, contains('Debug service listening on ws://127.0.0.1/abcd/'));
expect(debugConnectionInfo.wsUri.toString(), 'ws://127.0.0.1/abcd/'); expect(debugConnectionInfo.wsUri.toString(), 'ws://127.0.0.1/abcd/');
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Logger: () => DelegateLogger(BufferLogger( Logger: () => DelegateLogger(BufferLogger.test()),
terminal: AnsiTerminal( }));
stdio: null,
platform: const LocalPlatform(), test('WebRunner copies compiled app.dill to cache during startup', () => testbed.run(() async {
), fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations.toList());
outputPreferences: OutputPreferences.test(), _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 { test('Can successfully run without an index.html including status warning', () => testbed.run(() async {
......
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