Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 594c4f9

Browse files
Only synchronize used Dart sources to DevFS. (flutter#6668)
- [x] Remove the second full-sync on startup. - [x] Always invoke the snapshotter to determine the minimal set of Dart sources used. - [x] Only synchronize the *used* Dart sources to DevFS. - [x] Detect syntax / file missing errors on the host and gate reloads / restarts.
1 parent 2d9d4c2 commit 594c4f9

File tree

2 files changed

+68
-34
lines changed

2 files changed

+68
-34
lines changed

packages/flutter_tools/lib/src/base/process.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,16 @@ String runCheckedSync(List<String> cmd, {
164164
);
165165
}
166166

167+
/// Run cmd and return stdout on success.
168+
///
169+
/// Throws the standard error output if cmd exits with a non-zero value.
170+
String runSyncAndThrowStdErrOnError(List<String> cmd) {
171+
return _runWithLoggingSync(cmd,
172+
checked: true,
173+
throwStandardErrorOnError: true,
174+
hideStdout: true);
175+
}
176+
167177
/// Run cmd and return stdout.
168178
String runSync(List<String> cmd, {
169179
String workingDirectory,
@@ -187,6 +197,7 @@ void _traceCommand(List<String> args, { String workingDirectory }) {
187197
String _runWithLoggingSync(List<String> cmd, {
188198
bool checked: false,
189199
bool noisyErrors: false,
200+
bool throwStandardErrorOnError: false,
190201
String workingDirectory,
191202
bool allowReentrantFlutter: false,
192203
bool hideStdout: false,
@@ -216,6 +227,9 @@ String _runWithLoggingSync(List<String> cmd, {
216227
printTrace(results.stderr.trim());
217228
}
218229

230+
if (throwStandardErrorOnError)
231+
throw results.stderr.trim();
232+
219233
if (checked)
220234
throw 'Exit code ${results.exitCode} from: ${cmd.join(' ')}';
221235
}

packages/flutter_tools/lib/src/hot.dart

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ String getDevFSLoaderScript() {
3838
'loader_app.dart'));
3939
}
4040

41-
class StartupDependencySetBuilder {
42-
StartupDependencySetBuilder(this.mainScriptPath,
43-
this.projectRootPath);
41+
class DartDependencySetBuilder {
42+
DartDependencySetBuilder(this.mainScriptPath,
43+
this.projectRootPath);
4444

4545
final String mainScriptPath;
4646
final String projectRootPath;
@@ -56,12 +56,7 @@ class StartupDependencySetBuilder {
5656
mainScriptPath
5757
];
5858

59-
String output;
60-
try {
61-
output = runCheckedSync(args, hideStdout: true);
62-
} catch (e) {
63-
return null;
64-
}
59+
String output = runSyncAndThrowStdErrOnError(args);
6560

6661
final List<String> lines = LineSplitter.split(output).toList();
6762
final Set<String> minimalDependencies = new Set<String>();
@@ -135,7 +130,7 @@ class HotRunner extends ResidentRunner {
135130
ApplicationPackage _package;
136131
String _mainPath;
137132
String _projectRootPath;
138-
Set<String> _startupDependencies;
133+
Set<String> _dartDependencies;
139134
int _observatoryPort;
140135
final AssetBundle bundle = new AssetBundle();
141136
final bool benchmarkMode;
@@ -159,6 +154,23 @@ class HotRunner extends ResidentRunner {
159154
});
160155
}
161156

157+
bool _refreshDartDependencies() {
158+
if (_dartDependencies != null) {
159+
// Already computed.
160+
return true;
161+
}
162+
DartDependencySetBuilder dartDependencySetBuilder =
163+
new DartDependencySetBuilder(_mainPath, _projectRootPath);
164+
try {
165+
_dartDependencies = dartDependencySetBuilder.build();
166+
} catch (error) {
167+
printStatus('Error detected in application source code:', emphasis: true);
168+
printError(error);
169+
return false;
170+
}
171+
return true;
172+
}
173+
162174
Future<int> _run({
163175
Completer<DebugConnectionInfo> connectionInfoCompleter,
164176
String route,
@@ -184,6 +196,12 @@ class HotRunner extends ResidentRunner {
184196
return 1;
185197
}
186198

199+
// Determine the Dart dependencies eagerly.
200+
if (!_refreshDartDependencies()) {
201+
// Some kind of source level error or missing file in the Dart code.
202+
return 1;
203+
}
204+
187205
// TODO(devoncarew): We shouldn't have to do type checks here.
188206
if (shouldBuild && device is AndroidDevice) {
189207
printTrace('Running build command.');
@@ -231,15 +249,6 @@ class HotRunner extends ResidentRunner {
231249
route: route
232250
);
233251

234-
// In parallel, compute the minimal dependency set.
235-
StartupDependencySetBuilder startupDependencySetBuilder =
236-
new StartupDependencySetBuilder(_mainPath, _projectRootPath);
237-
_startupDependencies = startupDependencySetBuilder.build();
238-
if (_startupDependencies == null) {
239-
printError('Error determining the set of Dart sources necessary to start '
240-
'the application. Initial file upload may take a long time.');
241-
}
242-
243252
LaunchResult result = await futureResult;
244253

245254
if (!result.started) {
@@ -295,10 +304,6 @@ class HotRunner extends ResidentRunner {
295304

296305
registerSignalHandlers();
297306

298-
printTrace('Finishing file synchronization');
299-
// Finish the file sync now.
300-
await _updateDevFS();
301-
302307
if (benchmarkMode) {
303308
// We are running in benchmark mode.
304309
printStatus('Running in benchmark mode.');
@@ -325,13 +330,19 @@ class HotRunner extends ResidentRunner {
325330
Future<Null> handleTerminalCommand(String code) async {
326331
final String lower = code.toLowerCase();
327332
if ((lower == 'r') || (code == AnsiTerminal.KEY_F5)) {
333+
OperationResult result = OperationResult.ok;
328334
// F5, restart
329335
if ((code == 'r') || (code == AnsiTerminal.KEY_F5)) {
330336
// lower-case 'r'
331-
await _reloadSources();
337+
result = await _reloadSources();
332338
} else {
333339
// upper-case 'R'.
334-
await _restartFromSources();
340+
result = await _restartFromSources();
341+
}
342+
if (!result.isOk) {
343+
// TODO(johnmccutchan): Attempt to determine the number of errors that
344+
// occurred and tighten this message.
345+
printStatus('Try again after fixing the above error(s).', emphasis: true);
335346
}
336347
}
337348
}
@@ -362,6 +373,10 @@ class HotRunner extends ResidentRunner {
362373
}
363374

364375
Future<bool> _updateDevFS({ DevFSProgressReporter progressReporter }) async {
376+
if (!_refreshDartDependencies()) {
377+
// Did not update DevFS because of a Dart source error.
378+
return false;
379+
}
365380
Status devFSStatus = logger.startProgress('Syncing files to device...');
366381
final bool rebuildBundle = bundle.needsBuild();
367382
if (rebuildBundle) {
@@ -371,10 +386,10 @@ class HotRunner extends ResidentRunner {
371386
await _devFS.update(progressReporter: progressReporter,
372387
bundle: bundle,
373388
bundleDirty: rebuildBundle,
374-
fileFilter: _startupDependencies);
389+
fileFilter: _dartDependencies);
375390
devFSStatus.stop(showElapsedTime: true);
376-
// Clear the minimal set after the first sync.
377-
_startupDependencies = null;
391+
// Clear the set after the sync.
392+
_dartDependencies = null;
378393
printTrace('Synced ${getSizeAsMB(_devFS.bytes)}.');
379394
return true;
380395
}
@@ -422,10 +437,12 @@ class HotRunner extends ResidentRunner {
422437
deviceAssetsDirectoryPath);
423438
}
424439

425-
Future<Null> _restartFromSources() async {
440+
Future<OperationResult> _restartFromSources() async {
426441
FirstFrameTimer firstFrameTimer = new FirstFrameTimer(vmService);
427442
firstFrameTimer.start();
428-
await _updateDevFS();
443+
bool updatedDevFS = await _updateDevFS();
444+
if (!updatedDevFS)
445+
return new OperationResult(1, 'Dart Source Error');
429446
await _launchFromDevFS(_package, _mainPath);
430447
bool waitForFrame =
431448
await currentView.uiIsolate.flutterFrameworkPresent();
@@ -446,6 +463,7 @@ class HotRunner extends ResidentRunner {
446463
flutterUsage.sendTiming('hot', 'restart', firstFrameTimer.elapsed);
447464
}
448465
flutterUsage.sendEvent('hot', 'restart');
466+
return OperationResult.ok;
449467
}
450468

451469
/// Returns [true] if the reload was successful.
@@ -465,8 +483,7 @@ class HotRunner extends ResidentRunner {
465483
@override
466484
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false }) async {
467485
if (fullRestart) {
468-
await _restartFromSources();
469-
return OperationResult.ok;
486+
return _restartFromSources();
470487
} else {
471488
return _reloadSources(pause: pauseAfterRestart);
472489
}
@@ -477,8 +494,11 @@ class HotRunner extends ResidentRunner {
477494
throw 'Application isolate not found';
478495
FirstFrameTimer firstFrameTimer = new FirstFrameTimer(vmService);
479496
firstFrameTimer.start();
480-
if (_devFS != null)
481-
await _updateDevFS();
497+
if (_devFS != null) {
498+
bool updatedDevFS = await _updateDevFS();
499+
if (!updatedDevFS)
500+
return new OperationResult(1, 'Dart Source Error');
501+
}
482502
Status reloadStatus = logger.startProgress('Performing hot reload...');
483503
try {
484504
Map<String, dynamic> reloadReport =

0 commit comments

Comments
 (0)