mirror of
https://github.com/flutter/flutter
synced 2024-09-19 16:21:58 +00:00
Several benchmarks started failing during kernel compile:
1. Timeouts:
* commands_test
* hot_mode_dev_cycle__benchmark
* run_machine_concurrent_hot_reload
* service_extensions_test
2. Kernel compiler crash:
* hot_mode_dev_cycle_linux__benchmark
* routing_test
3. Unexpected termination:
* hot_mode_dev_cycle_win__benchmark
This reverts commit ed63e7082a
.
This commit is contained in:
parent
ed63e7082a
commit
9495df4bc3
|
@ -68,8 +68,12 @@ Future<Null> _generateDocs() async {
|
|||
}
|
||||
|
||||
Future<Null> _verifyInternationalizations() async {
|
||||
final EvalResult genResult = await _evalCommand(dart,
|
||||
<String>[ '--preview-dart-2', path.join('dev', 'tools', 'gen_localizations.dart'), ],
|
||||
final EvalResult genResult = await _evalCommand(
|
||||
dart,
|
||||
<String>[
|
||||
'--preview-dart-2',
|
||||
path.join('dev', 'tools', 'gen_localizations.dart'),
|
||||
],
|
||||
workingDirectory: flutterRoot,
|
||||
);
|
||||
|
||||
|
|
|
@ -32,6 +32,14 @@ void main() async {
|
|||
return new TaskResult.failure(errorMessage);
|
||||
}
|
||||
|
||||
section('gradlew assembleDebug no-preview-dart-2');
|
||||
await project.runGradleTask('assembleDebug', options: <String>['-Ppreview-dart-2=false']);
|
||||
errorMessage = _validateSnapshotDependency(project,
|
||||
'${project.rootPath}/build/app/intermediates/flutter/debug/snapshot_blob.bin');
|
||||
if (errorMessage != null) {
|
||||
return new TaskResult.failure(errorMessage);
|
||||
}
|
||||
|
||||
section('gradlew assembleProfile');
|
||||
await project.runGradleTask('assembleProfile');
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) 2017 The Chromium 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_devicelab/tasks/hot_mode_tests.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
|
||||
Future<Null> main() async {
|
||||
await task(createHotModeTest(isPreviewDart2: false));
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2018 The Chromium 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_devicelab/tasks/hot_mode_tests.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/framework/adb.dart';
|
||||
|
||||
Future<Null> main() async {
|
||||
deviceOperatingSystem = DeviceOperatingSystem.ios;
|
||||
await task(createHotModeTest(isPreviewDart2: false));
|
||||
}
|
|
@ -16,7 +16,7 @@ import '../framework/utils.dart';
|
|||
final Directory _editedFlutterGalleryDir = dir(path.join(Directory.systemTemp.path, 'edited_flutter_gallery'));
|
||||
final Directory flutterGalleryDir = dir(path.join(flutterDirectory.path, 'examples/flutter_gallery'));
|
||||
|
||||
TaskFunction createHotModeTest() {
|
||||
TaskFunction createHotModeTest({ bool isPreviewDart2 = true }) {
|
||||
return () async {
|
||||
final Device device = await devices.workingDevice;
|
||||
await device.unlock();
|
||||
|
@ -25,6 +25,10 @@ TaskFunction createHotModeTest() {
|
|||
final List<String> options = <String>[
|
||||
'--hot', '-d', device.deviceId, '--benchmark', '--verbose', '--resident'
|
||||
];
|
||||
if (isPreviewDart2)
|
||||
options.add('--preview-dart-2');
|
||||
else
|
||||
options.add('--no-preview-dart-2');
|
||||
setLocalEngineOptionIfNecessary(options);
|
||||
int hotReloadCount = 0;
|
||||
Map<String, dynamic> twoReloadsData;
|
||||
|
@ -88,8 +92,8 @@ TaskFunction createHotModeTest() {
|
|||
}
|
||||
benchmarkFile.deleteSync();
|
||||
|
||||
// start `flutter run` again to make sure it loads from the previous
|
||||
// state; frontend loads up from previously generated kernel files.
|
||||
// start `flutter run` again to make sure it loads from the previous state
|
||||
// (in case of --preview-dart-2 frontend loads up from previously generated kernel files).
|
||||
{
|
||||
final Process process = await startProcess(
|
||||
path.join(flutterDirectory.path, 'bin', 'flutter'),
|
||||
|
|
|
@ -23,7 +23,7 @@ TaskFunction createMicrobenchmarkTask() {
|
|||
final Device device = await devices.workingDevice;
|
||||
await device.unlock();
|
||||
|
||||
Future<Map<String, double>> _runMicrobench(String benchmarkPath) async {
|
||||
Future<Map<String, double>> _runMicrobench(String benchmarkPath, {bool previewDart2 = true}) async {
|
||||
Future<Map<String, double>> _run() async {
|
||||
print('Running $benchmarkPath');
|
||||
final Directory appDir = dir(
|
||||
|
@ -38,6 +38,10 @@ TaskFunction createMicrobenchmarkTask() {
|
|||
'-d',
|
||||
device.deviceId,
|
||||
];
|
||||
if (previewDart2)
|
||||
options.add('--preview-dart-2');
|
||||
else
|
||||
options.add('--no-preview-dart-2');
|
||||
setLocalEngineOptionIfNecessary(options);
|
||||
options.add(benchmarkPath);
|
||||
return await _startFlutter(
|
||||
|
@ -57,6 +61,26 @@ TaskFunction createMicrobenchmarkTask() {
|
|||
allResults.addAll(await _runMicrobench('lib/gestures/velocity_tracker_bench.dart'));
|
||||
allResults.addAll(await _runMicrobench('lib/stocks/animation_bench.dart'));
|
||||
|
||||
// Run micro-benchmarks once again in --no-preview-dart-2 mode.
|
||||
// Append "_dart1" suffix to the result keys to distinguish them from
|
||||
// the original results.
|
||||
|
||||
void addDart1Results(Map<String, double> benchmarkResults) {
|
||||
benchmarkResults.forEach((String key, double result) {
|
||||
allResults[key + '_dart1'] = result;
|
||||
});
|
||||
}
|
||||
|
||||
addDart1Results(await _runMicrobench(
|
||||
'lib/stocks/layout_bench.dart', previewDart2: false));
|
||||
addDart1Results(await _runMicrobench(
|
||||
'lib/stocks/layout_bench.dart', previewDart2: false));
|
||||
addDart1Results(await _runMicrobench(
|
||||
'lib/stocks/build_bench.dart', previewDart2: false));
|
||||
addDart1Results(await _runMicrobench(
|
||||
'lib/gestures/velocity_tracker_bench.dart', previewDart2: false));
|
||||
addDart1Results(await _runMicrobench(
|
||||
'lib/stocks/animation_bench.dart', previewDart2: false));
|
||||
return new TaskResult.success(allResults, benchmarkScoreKeys: allResults.keys.toList());
|
||||
};
|
||||
}
|
||||
|
|
|
@ -205,13 +205,23 @@ class CompileTest {
|
|||
final Map<String, dynamic> metrics = <String, dynamic>{}
|
||||
..addAll(await _compileAot())
|
||||
..addAll(await _compileApp())
|
||||
..addAll(await _compileDebug());
|
||||
..addAll(await _compileDebug())
|
||||
..addAll(_suffix(await _compileAot(previewDart2: false), '__dart1'))
|
||||
..addAll(_suffix(await _compileApp(previewDart2: false), '__dart1'))
|
||||
..addAll(_suffix(await _compileDebug(previewDart2: false), '__dart1'));
|
||||
|
||||
return new TaskResult.success(metrics, benchmarkScoreKeys: metrics.keys.toList());
|
||||
});
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> _compileAot() async {
|
||||
static Map<String, dynamic> _suffix(Map<String, dynamic> map, String suffix) {
|
||||
return new Map<String, dynamic>.fromIterables(
|
||||
map.keys.map<String>((String key) => '$key$suffix'),
|
||||
map.values,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> _compileAot({ bool previewDart2 = true }) async {
|
||||
// Generate blobs instead of assembly.
|
||||
await flutter('clean');
|
||||
final Stopwatch watch = new Stopwatch()..start();
|
||||
|
@ -230,6 +240,10 @@ class CompileTest {
|
|||
options.add('android-arm');
|
||||
break;
|
||||
}
|
||||
if (previewDart2)
|
||||
options.add('--preview-dart-2');
|
||||
else
|
||||
options.add('--no-preview-dart-2');
|
||||
setLocalEngineOptionIfNecessary(options);
|
||||
final String compileLog = await evalFlutter('build', options: options);
|
||||
watch.stop();
|
||||
|
@ -244,11 +258,15 @@ class CompileTest {
|
|||
return metrics;
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> _compileApp() async {
|
||||
static Future<Map<String, dynamic>> _compileApp({ bool previewDart2 = true }) async {
|
||||
await flutter('clean');
|
||||
final Stopwatch watch = new Stopwatch();
|
||||
int releaseSizeInBytes;
|
||||
final List<String> options = <String>['--release'];
|
||||
if (previewDart2)
|
||||
options.add('--preview-dart-2');
|
||||
else
|
||||
options.add('--no-preview-dart-2');
|
||||
setLocalEngineOptionIfNecessary(options);
|
||||
switch (deviceOperatingSystem) {
|
||||
case DeviceOperatingSystem.ios:
|
||||
|
@ -281,10 +299,14 @@ class CompileTest {
|
|||
};
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> _compileDebug() async {
|
||||
static Future<Map<String, dynamic>> _compileDebug({ bool previewDart2 = true }) async {
|
||||
await flutter('clean');
|
||||
final Stopwatch watch = new Stopwatch();
|
||||
final List<String> options = <String>['--debug'];
|
||||
if (previewDart2)
|
||||
options.add('--preview-dart-2');
|
||||
else
|
||||
options.add('--no-preview-dart-2');
|
||||
setLocalEngineOptionIfNecessary(options);
|
||||
switch (deviceOperatingSystem) {
|
||||
case DeviceOperatingSystem.ios:
|
||||
|
|
|
@ -154,6 +154,21 @@ tasks:
|
|||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/android"]
|
||||
|
||||
hot_mode_dev_cycle__benchmark_dart1:
|
||||
description: >
|
||||
Measures the performance of Dart VM hot patching feature under
|
||||
--no-preview-dart-2 option, that disables Dart 2.0 frontend.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/android"]
|
||||
|
||||
hot_mode_dev_cycle_ios__benchmark_dart1:
|
||||
description: >
|
||||
Measures the performance of Dart VM hot patching feature under
|
||||
--no-preview-dart-2 option, that disables Dart 2.0 frontend.
|
||||
stage: devicelab_ios
|
||||
required_agent_capabilities: ["mac/ios"]
|
||||
flaky: true
|
||||
|
||||
complex_layout_scroll_perf__memory:
|
||||
description: >
|
||||
Measures memory usage of the scroll performance test.
|
||||
|
|
|
@ -102,6 +102,13 @@ BuildApp() {
|
|||
local_engine_flag="--local-engine=$LOCAL_ENGINE"
|
||||
fi
|
||||
|
||||
local preview_dart_2_flag=""
|
||||
if [[ -n "$PREVIEW_DART_2" ]]; then
|
||||
preview_dart_2_flag="--preview-dart-2"
|
||||
else
|
||||
preview_dart_2_flag="--no-preview-dart-2"
|
||||
fi
|
||||
|
||||
local track_widget_creation_flag=""
|
||||
if [[ -n "$TRACK_WIDGET_CREATION" ]]; then
|
||||
track_widget_creation_flag="--track-widget-creation"
|
||||
|
@ -120,6 +127,7 @@ BuildApp() {
|
|||
--${build_mode} \
|
||||
--ios-arch="${archs}" \
|
||||
${local_engine_flag} \
|
||||
${preview_dart_2_flag} \
|
||||
${track_widget_creation_flag}
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
|
@ -159,10 +167,12 @@ BuildApp() {
|
|||
${verbose_flag} \
|
||||
build bundle \
|
||||
--target="${target_path}" \
|
||||
--snapshot="${build_dir}/snapshot_blob.bin" \
|
||||
--depfile="${build_dir}/snapshot_blob.bin.d" \
|
||||
--asset-dir="${derived_dir}/flutter_assets" \
|
||||
${precompilation_flag} \
|
||||
${local_engine_flag} \
|
||||
${preview_dart_2_flag} \
|
||||
${track_widget_creation_flag}
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
|
|
|
@ -260,6 +260,10 @@ class FlutterPlugin implements Plugin<Project> {
|
|||
if (project.hasProperty('verbose')) {
|
||||
verboseValue = project.property('verbose').toBoolean()
|
||||
}
|
||||
Boolean previewDart2Value = true
|
||||
if (project.hasProperty('preview-dart-2')) {
|
||||
previewDart2Value = project.property('preview-dart-2').toBoolean()
|
||||
}
|
||||
String[] fileSystemRootsValue = null
|
||||
if (project.hasProperty('filesystem-roots')) {
|
||||
fileSystemRootsValue = project.property('filesystem-roots').split('\\|')
|
||||
|
@ -311,6 +315,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||
localEngineSrcPath this.localEngineSrcPath
|
||||
targetPath target
|
||||
verbose verboseValue
|
||||
previewDart2 previewDart2Value
|
||||
fileSystemRoots fileSystemRootsValue
|
||||
fileSystemScheme fileSystemSchemeValue
|
||||
trackWidgetCreation trackWidgetCreationValue
|
||||
|
@ -355,6 +360,8 @@ abstract class BaseFlutterTask extends DefaultTask {
|
|||
@Optional @Input
|
||||
Boolean verbose
|
||||
@Optional @Input
|
||||
Boolean previewDart2
|
||||
@Optional @Input
|
||||
String[] fileSystemRoots
|
||||
@Optional @Input
|
||||
String fileSystemScheme
|
||||
|
@ -376,10 +383,12 @@ abstract class BaseFlutterTask extends DefaultTask {
|
|||
if (buildMode != 'debug') {
|
||||
// For AOT builds, include the gen_snapshot depfile.
|
||||
FileCollection depfiles = project.files("${intermediateDir}/snapshot.d")
|
||||
// Include the kernel compiler depfile, since kernel compile is the
|
||||
// first stage of AOT build in this mode, and it includes all the
|
||||
// Dart sources.
|
||||
depfiles += project.files("${intermediateDir}/kernel_compile.d")
|
||||
if (previewDart2) {
|
||||
// For Dart 2, also include the kernel compiler depfile, since
|
||||
// kernel compile is the first stage of AOT build in this mode,
|
||||
// and it includes all the Dart sources.
|
||||
depfiles += project.files("${intermediateDir}/kernel_compile.d")
|
||||
}
|
||||
return depfiles
|
||||
}
|
||||
return project.files("${intermediateDir}/snapshot_blob.bin.d")
|
||||
|
@ -406,6 +415,11 @@ abstract class BaseFlutterTask extends DefaultTask {
|
|||
args "--target", targetPath
|
||||
args "--target-platform", "android-arm"
|
||||
args "--output-dir", "${intermediateDir}"
|
||||
if (previewDart2) {
|
||||
args "--preview-dart-2"
|
||||
} else {
|
||||
args "--no-preview-dart-2"
|
||||
}
|
||||
if (trackWidgetCreation) {
|
||||
args "--track-widget-creation"
|
||||
}
|
||||
|
@ -438,6 +452,11 @@ abstract class BaseFlutterTask extends DefaultTask {
|
|||
if (verbose) {
|
||||
args "--verbose"
|
||||
}
|
||||
if (previewDart2) {
|
||||
args "--preview-dart-2"
|
||||
} else {
|
||||
args "--no-preview-dart-2"
|
||||
}
|
||||
if (fileSystemRoots != null) {
|
||||
for (root in fileSystemRoots) {
|
||||
args "--filesystem-root", root
|
||||
|
@ -456,6 +475,9 @@ abstract class BaseFlutterTask extends DefaultTask {
|
|||
args "--precompiled"
|
||||
} else {
|
||||
args "--depfile", "${intermediateDir}/snapshot_blob.bin.d"
|
||||
if (!previewDart2) {
|
||||
args "--snapshot", "${intermediateDir}/snapshot_blob.bin"
|
||||
}
|
||||
}
|
||||
args "--asset-dir", "${intermediateDir}/flutter_assets"
|
||||
}
|
||||
|
@ -511,7 +533,9 @@ class FlutterTask extends BaseFlutterTask {
|
|||
// We have a dependencies file. Add a dependency on gen_snapshot as well, since the
|
||||
// snapshots have to be rebuilt if it changes.
|
||||
sources += readDependencies(project.file("${intermediateDir}/gen_snapshot.d"))
|
||||
sources += readDependencies(project.file("${intermediateDir}/frontend_server.d"))
|
||||
if (previewDart2) {
|
||||
sources += readDependencies(project.file("${intermediateDir}/frontend_server.d"))
|
||||
}
|
||||
if (localEngineSrcPath != null) {
|
||||
sources += project.files("$localEngineSrcPath/$localEngine")
|
||||
}
|
||||
|
|
|
@ -327,16 +327,21 @@ Future<Null> _buildGradleProjectV2(String gradle, BuildInfo buildInfo, String ta
|
|||
if (target != null) {
|
||||
command.add('-Ptarget=$target');
|
||||
}
|
||||
if (buildInfo.trackWidgetCreation)
|
||||
command.add('-Ptrack-widget-creation=true');
|
||||
if (buildInfo.extraFrontEndOptions != null)
|
||||
command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}');
|
||||
if (buildInfo.extraGenSnapshotOptions != null)
|
||||
command.add('-Pextra-gen-snapshot-options=${buildInfo.extraGenSnapshotOptions}');
|
||||
if (buildInfo.fileSystemRoots != null && buildInfo.fileSystemRoots.isNotEmpty)
|
||||
command.add('-Pfilesystem-roots=${buildInfo.fileSystemRoots.join('|')}');
|
||||
if (buildInfo.fileSystemScheme != null)
|
||||
command.add('-Pfilesystem-scheme=${buildInfo.fileSystemScheme}');
|
||||
if (buildInfo.previewDart2) {
|
||||
command.add('-Ppreview-dart-2=true');
|
||||
if (buildInfo.trackWidgetCreation)
|
||||
command.add('-Ptrack-widget-creation=true');
|
||||
if (buildInfo.extraFrontEndOptions != null)
|
||||
command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}');
|
||||
if (buildInfo.extraGenSnapshotOptions != null)
|
||||
command.add('-Pextra-gen-snapshot-options=${buildInfo.extraGenSnapshotOptions}');
|
||||
if (buildInfo.fileSystemRoots != null && buildInfo.fileSystemRoots.isNotEmpty)
|
||||
command.add('-Pfilesystem-roots=${buildInfo.fileSystemRoots.join('|')}');
|
||||
if (buildInfo.fileSystemScheme != null)
|
||||
command.add('-Pfilesystem-scheme=${buildInfo.fileSystemScheme}');
|
||||
} else {
|
||||
command.add('-Ppreview-dart-2=false');
|
||||
}
|
||||
if (buildInfo.buildSharedLibrary && androidSdk.ndk != null) {
|
||||
command.add('-Pbuild-shared-library=true');
|
||||
}
|
||||
|
|
|
@ -64,6 +64,70 @@ class GenSnapshot {
|
|||
}
|
||||
}
|
||||
|
||||
/// Dart snapshot builder.
|
||||
///
|
||||
/// Builds Dart snapshots in one of three modes:
|
||||
/// * Script snapshot: architecture-independent snapshot of a Dart script
|
||||
/// and core libraries.
|
||||
/// * AOT snapshot: architecture-specific ahead-of-time compiled snapshot
|
||||
/// suitable for loading with `mmap`.
|
||||
/// * Assembly AOT snapshot: architecture-specific ahead-of-time compile to
|
||||
/// assembly suitable for compilation as a static or dynamic library.
|
||||
class ScriptSnapshotter {
|
||||
/// Builds an architecture-independent snapshot of the specified script.
|
||||
Future<int> build({
|
||||
@required String mainPath,
|
||||
@required String snapshotPath,
|
||||
@required String depfilePath,
|
||||
@required String packagesPath
|
||||
}) async {
|
||||
final SnapshotType snapshotType = new SnapshotType(null, BuildMode.debug);
|
||||
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
|
||||
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
|
||||
final List<String> args = <String>[
|
||||
'--snapshot_kind=script',
|
||||
'--script_snapshot=$snapshotPath',
|
||||
'--vm_snapshot_data=$vmSnapshotData',
|
||||
'--isolate_snapshot_data=$isolateSnapshotData',
|
||||
'--enable-mirrors=false',
|
||||
mainPath,
|
||||
];
|
||||
|
||||
final Fingerprinter fingerprinter = new Fingerprinter(
|
||||
fingerprintPath: '$depfilePath.fingerprint',
|
||||
paths: <String>[
|
||||
mainPath,
|
||||
snapshotPath,
|
||||
vmSnapshotData,
|
||||
isolateSnapshotData,
|
||||
],
|
||||
properties: <String, String>{
|
||||
'buildMode': snapshotType.mode.toString(),
|
||||
'targetPlatform': snapshotType.platform?.toString() ?? '',
|
||||
'entryPoint': mainPath,
|
||||
},
|
||||
depfilePaths: <String>[depfilePath],
|
||||
);
|
||||
if (await fingerprinter.doesFingerprintMatch()) {
|
||||
printTrace('Skipping script snapshot build. Fingerprints match.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Build the snapshot.
|
||||
final int exitCode = await genSnapshot.run(
|
||||
snapshotType: snapshotType,
|
||||
packagesPath: packagesPath,
|
||||
depfilePath: depfilePath,
|
||||
additionalArgs: args,
|
||||
);
|
||||
|
||||
if (exitCode != 0)
|
||||
return exitCode;
|
||||
await fingerprinter.writeFingerprint();
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
|
||||
class AOTSnapshotter {
|
||||
/// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script.
|
||||
Future<int> build({
|
||||
|
@ -72,6 +136,7 @@ class AOTSnapshotter {
|
|||
@required String mainPath,
|
||||
@required String packagesPath,
|
||||
@required String outputPath,
|
||||
@required bool previewDart2,
|
||||
@required bool buildSharedLibrary,
|
||||
IOSArch iosArch,
|
||||
List<String> extraGenSnapshotOptions = const <String>[],
|
||||
|
@ -127,10 +192,12 @@ class AOTSnapshotter {
|
|||
'--embedder_entry_points_manifest=$ioEntryPoints',
|
||||
'--dependencies=$depfilePath',
|
||||
];
|
||||
genSnapshotArgs.addAll(<String>[
|
||||
'--reify-generic-functions',
|
||||
'--strong',
|
||||
]);
|
||||
if (previewDart2) {
|
||||
genSnapshotArgs.addAll(<String>[
|
||||
'--reify-generic-functions',
|
||||
'--strong',
|
||||
]);
|
||||
}
|
||||
if (extraGenSnapshotOptions != null && extraGenSnapshotOptions.isNotEmpty) {
|
||||
printTrace('Extra gen_snapshot options: $extraGenSnapshotOptions');
|
||||
genSnapshotArgs.addAll(extraGenSnapshotOptions);
|
||||
|
@ -185,6 +252,7 @@ class AOTSnapshotter {
|
|||
'buildMode': buildMode.toString(),
|
||||
'targetPlatform': platform.toString(),
|
||||
'entryPoint': mainPath,
|
||||
'dart2': previewDart2.toString(),
|
||||
'sharedLib': buildSharedLibrary.toString(),
|
||||
'extraGenSnapshotOptions': extraGenSnapshotOptions.join(' '),
|
||||
},
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'globals.dart';
|
|||
/// Information about a build to be performed or used.
|
||||
class BuildInfo {
|
||||
const BuildInfo(this.mode, this.flavor, {
|
||||
this.previewDart2 = false,
|
||||
this.trackWidgetCreation = false,
|
||||
this.extraFrontEndOptions,
|
||||
this.extraGenSnapshotOptions,
|
||||
|
@ -32,6 +33,9 @@ class BuildInfo {
|
|||
/// Mode-Flavor (e.g. Release-Paid).
|
||||
final String flavor;
|
||||
|
||||
/// Whether build should be done using Dart2 Frontend parser.
|
||||
final bool previewDart2;
|
||||
|
||||
final List<String> fileSystemRoots;
|
||||
final String fileSystemScheme;
|
||||
|
||||
|
@ -89,6 +93,7 @@ class BuildInfo {
|
|||
|
||||
BuildInfo withTargetPlatform(TargetPlatform targetPlatform) =>
|
||||
new BuildInfo(mode, flavor,
|
||||
previewDart2: previewDart2,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
extraFrontEndOptions: extraFrontEndOptions,
|
||||
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:async';
|
|||
|
||||
import 'artifacts.dart';
|
||||
import 'asset.dart';
|
||||
import 'base/build.dart';
|
||||
import 'base/common.dart';
|
||||
import 'base/file_system.dart';
|
||||
import 'build_info.dart';
|
||||
|
@ -23,6 +24,7 @@ String get defaultApplicationKernelPath => fs.path.join(getBuildDirectory(), 'ap
|
|||
const String defaultPrivateKeyPath = 'privatekey.der';
|
||||
|
||||
const String _kKernelKey = 'kernel_blob.bin';
|
||||
const String _kSnapshotKey = 'snapshot_blob.bin';
|
||||
const String _kVMSnapshotData = 'vm_snapshot_data';
|
||||
const String _kIsolateSnapshotData = 'isolate_snapshot_data';
|
||||
const String _kDylibKey = 'libapp.so';
|
||||
|
@ -31,11 +33,13 @@ const String _kPlatformKernelKey = 'platform.dill';
|
|||
Future<void> build({
|
||||
String mainPath = defaultMainPath,
|
||||
String manifestPath = defaultManifestPath,
|
||||
String snapshotPath,
|
||||
String applicationKernelFilePath,
|
||||
String depfilePath,
|
||||
String privateKeyPath = defaultPrivateKeyPath,
|
||||
String assetDirPath,
|
||||
String packagesPath,
|
||||
bool previewDart2 = false,
|
||||
bool precompiledSnapshot = false,
|
||||
bool reportLicensedPackages = false,
|
||||
bool trackWidgetCreation = false,
|
||||
|
@ -43,13 +47,32 @@ Future<void> build({
|
|||
List<String> fileSystemRoots,
|
||||
String fileSystemScheme,
|
||||
}) async {
|
||||
snapshotPath ??= defaultSnapshotPath;
|
||||
depfilePath ??= defaultDepfilePath;
|
||||
assetDirPath ??= getAssetBuildDirectory();
|
||||
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
|
||||
applicationKernelFilePath ??= defaultApplicationKernelPath;
|
||||
File snapshotFile;
|
||||
|
||||
if (!precompiledSnapshot && !previewDart2) {
|
||||
ensureDirectoryExists(snapshotPath);
|
||||
|
||||
// In a precompiled snapshot, the instruction buffer contains script
|
||||
// content equivalents
|
||||
final int result = await new ScriptSnapshotter().build(
|
||||
mainPath: mainPath,
|
||||
snapshotPath: snapshotPath,
|
||||
depfilePath: depfilePath,
|
||||
packagesPath: packagesPath,
|
||||
);
|
||||
if (result != 0)
|
||||
throwToolExit('Failed to run the Flutter compiler. Exit code: $result', exitCode: result);
|
||||
|
||||
snapshotFile = fs.file(snapshotPath);
|
||||
}
|
||||
|
||||
DevFSContent kernelContent;
|
||||
if (!precompiledSnapshot) {
|
||||
if (!precompiledSnapshot && previewDart2) {
|
||||
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
|
||||
printTrace('Extra front-end options: $extraFrontEndOptions');
|
||||
ensureDirectoryExists(applicationKernelFilePath);
|
||||
|
@ -86,6 +109,7 @@ Future<void> build({
|
|||
await assemble(
|
||||
assetBundle: assets,
|
||||
kernelContent: kernelContent,
|
||||
snapshotFile: snapshotFile,
|
||||
privateKeyPath: privateKeyPath,
|
||||
assetDirPath: assetDirPath,
|
||||
);
|
||||
|
@ -119,6 +143,7 @@ Future<AssetBundle> buildAssets({
|
|||
Future<void> assemble({
|
||||
AssetBundle assetBundle,
|
||||
DevFSContent kernelContent,
|
||||
File snapshotFile,
|
||||
File dylibFile,
|
||||
String privateKeyPath = defaultPrivateKeyPath,
|
||||
String assetDirPath,
|
||||
|
@ -127,16 +152,21 @@ Future<void> assemble({
|
|||
printTrace('Building bundle');
|
||||
|
||||
final Map<String, DevFSContent> assetEntries = new Map<String, DevFSContent>.from(assetBundle.entries);
|
||||
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
|
||||
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
|
||||
|
||||
if (kernelContent != null) {
|
||||
final String platformKernelDill = artifacts.getArtifactPath(Artifact.platformKernelDill);
|
||||
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
|
||||
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
|
||||
assetEntries[_kKernelKey] = kernelContent;
|
||||
assetEntries[_kPlatformKernelKey] = new DevFSFileContent(fs.file(platformKernelDill));
|
||||
assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData));
|
||||
assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData));
|
||||
}
|
||||
if (snapshotFile != null) {
|
||||
assetEntries[_kSnapshotKey] = new DevFSFileContent(snapshotFile);
|
||||
assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData));
|
||||
assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData));
|
||||
}
|
||||
if (dylibFile != null)
|
||||
assetEntries[_kDylibKey] = new DevFSFileContent(dylibFile);
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ class AnalyzeCommand extends FlutterCommand {
|
|||
argParser.addFlag('watch',
|
||||
help: 'Run analysis continuously, watching the filesystem for changes.',
|
||||
negatable: false);
|
||||
argParser.addFlag('preview-dart-2',
|
||||
defaultsTo: true, help: 'Preview Dart 2.0 functionality.');
|
||||
argParser.addOption('write',
|
||||
valueHelp: 'file',
|
||||
help: 'Also output the results to a file. This is useful with --watch '
|
||||
|
@ -85,6 +87,7 @@ class AnalyzeCommand extends FlutterCommand {
|
|||
argResults,
|
||||
runner.getRepoRoots(),
|
||||
runner.getRepoPackages(),
|
||||
previewDart2: argResults['preview-dart-2'],
|
||||
).analyze();
|
||||
} else {
|
||||
return new AnalyzeOnce(
|
||||
|
@ -92,6 +95,7 @@ class AnalyzeCommand extends FlutterCommand {
|
|||
runner.getRepoRoots(),
|
||||
runner.getRepoPackages(),
|
||||
workingDirectory: workingDirectory,
|
||||
previewDart2: argResults['preview-dart-2'],
|
||||
).analyze();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,13 @@ import '../globals.dart';
|
|||
import 'analyze_base.dart';
|
||||
|
||||
class AnalyzeContinuously extends AnalyzeBase {
|
||||
AnalyzeContinuously(ArgResults argResults, this.repoRoots, this.repoPackages) : super(argResults);
|
||||
AnalyzeContinuously(ArgResults argResults, this.repoRoots, this.repoPackages, {
|
||||
this.previewDart2 = false,
|
||||
}) : super(argResults);
|
||||
|
||||
final List<String> repoRoots;
|
||||
final List<Directory> repoPackages;
|
||||
final bool previewDart2;
|
||||
|
||||
String analysisTarget;
|
||||
bool firstAnalysis = true;
|
||||
|
@ -57,7 +60,7 @@ class AnalyzeContinuously extends AnalyzeBase {
|
|||
|
||||
final String sdkPath = argResults['dart-sdk'] ?? sdk.dartSdkPath;
|
||||
|
||||
final AnalysisServer server = new AnalysisServer(sdkPath, directories);
|
||||
final AnalysisServer server = new AnalysisServer(sdkPath, directories, previewDart2: previewDart2);
|
||||
server.onAnalyzing.listen((bool isAnalyzing) => _handleAnalysisStatus(server, isAnalyzing));
|
||||
server.onErrors.listen(_handleAnalysisErrors);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ class AnalyzeOnce extends AnalyzeBase {
|
|||
this.repoRoots,
|
||||
this.repoPackages, {
|
||||
this.workingDirectory,
|
||||
this.previewDart2 = false,
|
||||
}) : super(argResults);
|
||||
|
||||
final List<String> repoRoots;
|
||||
|
@ -32,6 +33,8 @@ class AnalyzeOnce extends AnalyzeBase {
|
|||
/// The working directory for testing analysis using dartanalyzer.
|
||||
final Directory workingDirectory;
|
||||
|
||||
final bool previewDart2;
|
||||
|
||||
@override
|
||||
Future<Null> analyze() async {
|
||||
final String currentDirectory =
|
||||
|
@ -88,6 +91,7 @@ class AnalyzeOnce extends AnalyzeBase {
|
|||
final AnalysisServer server = new AnalysisServer(
|
||||
sdkPath,
|
||||
directories.toList(),
|
||||
previewDart2: previewDart2,
|
||||
);
|
||||
|
||||
StreamSubscription<bool> subscription;
|
||||
|
|
|
@ -28,6 +28,11 @@ class BuildAotCommand extends BuildSubCommand {
|
|||
allowed: <String>['android-arm', 'android-arm64', 'ios']
|
||||
)
|
||||
..addFlag('quiet', defaultsTo: false)
|
||||
..addFlag('preview-dart-2',
|
||||
defaultsTo: true,
|
||||
hide: !verboseHelp,
|
||||
help: 'Preview Dart 2.0 functionality.',
|
||||
)
|
||||
..addFlag('build-shared-library',
|
||||
negatable: false,
|
||||
defaultsTo: false,
|
||||
|
@ -74,20 +79,23 @@ class BuildAotCommand extends BuildSubCommand {
|
|||
}
|
||||
final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory();
|
||||
try {
|
||||
final bool previewDart2 = argResults['preview-dart-2'];
|
||||
String mainPath = findMainDartFile(targetFile);
|
||||
final AOTSnapshotter snapshotter = new AOTSnapshotter();
|
||||
|
||||
// Compile to kernel.
|
||||
mainPath = await snapshotter.compileKernel(
|
||||
platform: platform,
|
||||
buildMode: buildMode,
|
||||
mainPath: mainPath,
|
||||
outputPath: outputPath,
|
||||
extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
|
||||
);
|
||||
if (mainPath == null) {
|
||||
printError('Compiler terminated unexpectedly.');
|
||||
return;
|
||||
// Compile to kernel, if Dart 2.
|
||||
if (previewDart2) {
|
||||
mainPath = await snapshotter.compileKernel(
|
||||
platform: platform,
|
||||
buildMode: buildMode,
|
||||
mainPath: mainPath,
|
||||
outputPath: outputPath,
|
||||
extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
|
||||
);
|
||||
if (mainPath == null) {
|
||||
printError('Compiler terminated unexpectedly.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Build AOT snapshot.
|
||||
|
@ -108,6 +116,7 @@ class BuildAotCommand extends BuildSubCommand {
|
|||
mainPath: mainPath,
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
outputPath: outputPath,
|
||||
previewDart2: previewDart2,
|
||||
buildSharedLibrary: false,
|
||||
extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions],
|
||||
).then((int buildExitCode) {
|
||||
|
@ -134,6 +143,7 @@ class BuildAotCommand extends BuildSubCommand {
|
|||
mainPath: mainPath,
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
outputPath: outputPath,
|
||||
previewDart2: previewDart2,
|
||||
buildSharedLibrary: argResults['build-shared-library'],
|
||||
extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions],
|
||||
);
|
||||
|
|
|
@ -17,6 +17,11 @@ class BuildApkCommand extends BuildSubCommand {
|
|||
usesBuildNameOption();
|
||||
|
||||
argParser
|
||||
..addFlag('preview-dart-2',
|
||||
defaultsTo: true,
|
||||
hide: !verboseHelp,
|
||||
help: 'Preview Dart 2.0 functionality.',
|
||||
)
|
||||
..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp)
|
||||
..addFlag('build-shared-library',
|
||||
negatable: false,
|
||||
|
|
|
@ -19,8 +19,14 @@ class BuildBundleCommand extends BuildSubCommand {
|
|||
..addOption('asset-base', help: 'Ignored. Will be removed.', hide: !verboseHelp)
|
||||
..addOption('manifest', defaultsTo: defaultManifestPath)
|
||||
..addOption('private-key', defaultsTo: defaultPrivateKeyPath)
|
||||
..addOption('snapshot', defaultsTo: defaultSnapshotPath)
|
||||
..addOption('depfile', defaultsTo: defaultDepfilePath)
|
||||
..addOption('kernel-file', defaultsTo: defaultApplicationKernelPath)
|
||||
..addFlag('preview-dart-2',
|
||||
defaultsTo: true,
|
||||
hide: !verboseHelp,
|
||||
help: 'Preview Dart 2.0 functionality.',
|
||||
)
|
||||
..addFlag('track-widget-creation',
|
||||
hide: !verboseHelp,
|
||||
help: 'Track widget creation locations. Requires Dart 2.0 functionality.',
|
||||
|
@ -66,10 +72,12 @@ class BuildBundleCommand extends BuildSubCommand {
|
|||
await build(
|
||||
mainPath: targetFile,
|
||||
manifestPath: argResults['manifest'],
|
||||
snapshotPath: argResults['snapshot'],
|
||||
applicationKernelFilePath: argResults['kernel-file'],
|
||||
depfilePath: argResults['depfile'],
|
||||
privateKeyPath: argResults['private-key'],
|
||||
assetDirPath: argResults['asset-dir'],
|
||||
previewDart2: argResults['preview-dart-2'],
|
||||
precompiledSnapshot: argResults['precompiled'],
|
||||
reportLicensedPackages: argResults['report-licensed-packages'],
|
||||
trackWidgetCreation: argResults['track-widget-creation'],
|
||||
|
|
|
@ -38,7 +38,11 @@ class BuildIOSCommand extends BuildSubCommand {
|
|||
..addFlag('codesign',
|
||||
defaultsTo: true,
|
||||
help: 'Codesign the application bundle (only available on device builds).',
|
||||
);
|
||||
)
|
||||
..addFlag('preview-dart-2',
|
||||
defaultsTo: true,
|
||||
hide: !verboseHelp,
|
||||
help: 'Preview Dart 2.0 functionality.');
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -334,6 +334,7 @@ class AppDomain extends Domain {
|
|||
final BuildInfo buildInfo = new BuildInfo(
|
||||
getBuildModeForName(mode) ?? BuildMode.debug,
|
||||
flavor,
|
||||
previewDart2: _getBoolArg(args, 'preview-dart-2'),
|
||||
);
|
||||
DebuggingOptions options;
|
||||
if (buildInfo.isRelease) {
|
||||
|
@ -384,6 +385,7 @@ class AppDomain extends Domain {
|
|||
|
||||
final FlutterDevice flutterDevice = new FlutterDevice(
|
||||
device,
|
||||
previewDart2: options.buildInfo.previewDart2,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
dillOutputPath: dillOutputPath,
|
||||
);
|
||||
|
|
|
@ -62,7 +62,10 @@ class DriveCommand extends RunCommandBase {
|
|||
'just before the extension, so e.g. if the target is "lib/main.dart", the\n'
|
||||
'driver will be "test_driver/main_test.dart".',
|
||||
valueHelp: 'path',
|
||||
);
|
||||
)
|
||||
..addFlag('preview-dart-2',
|
||||
defaultsTo: true,
|
||||
help: 'Preview Dart 2.0 functionality.');
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -120,7 +123,7 @@ class DriveCommand extends RunCommandBase {
|
|||
Cache.releaseLockEarly();
|
||||
|
||||
try {
|
||||
await testRunner(<String>[testFile], observatoryUri);
|
||||
await testRunner(<String>[testFile], observatoryUri, argResults['preview-dart-2']);
|
||||
} catch (error, stackTrace) {
|
||||
if (error is ToolExit)
|
||||
rethrow;
|
||||
|
@ -272,20 +275,24 @@ Future<LaunchResult> _startApp(DriveCommand command) async {
|
|||
}
|
||||
|
||||
/// Runs driver tests.
|
||||
typedef Future<Null> TestRunner(List<String> testArgs, String observatoryUri);
|
||||
typedef Future<Null> TestRunner(List<String> testArgs, String observatoryUri, bool previewDart2);
|
||||
TestRunner testRunner = _runTests;
|
||||
void restoreTestRunner() {
|
||||
testRunner = _runTests;
|
||||
}
|
||||
|
||||
Future<Null> _runTests(List<String> testArgs, String observatoryUri) async {
|
||||
Future<Null> _runTests(List<String> testArgs, String observatoryUri, bool previewDart2) async {
|
||||
printTrace('Running driver tests.');
|
||||
|
||||
PackageMap.globalPackagesPath = fs.path.normalize(fs.path.absolute(PackageMap.globalPackagesPath));
|
||||
final List<String> args = testArgs.toList()
|
||||
..add('--packages=${PackageMap.globalPackagesPath}')
|
||||
..add('-rexpanded')
|
||||
..add('--preview-dart-2');
|
||||
..add('-rexpanded');
|
||||
if (previewDart2) {
|
||||
args.add('--preview-dart-2');
|
||||
} else {
|
||||
args.add('--no-preview-dart-2');
|
||||
}
|
||||
|
||||
final String dartVmPath = fs.path.join(dartSdkPath, 'bin', 'dart');
|
||||
final int result = await runCommandAndStreamOutput(
|
||||
|
|
|
@ -53,6 +53,10 @@ class FuchsiaReloadCommand extends FlutterCommand {
|
|||
argParser.addOption('name-override',
|
||||
abbr: 'n',
|
||||
help: 'On-device name of the application binary.');
|
||||
argParser.addFlag('preview-dart-2',
|
||||
abbr: '2',
|
||||
defaultsTo: false,
|
||||
help: 'Preview Dart 2.0 functionality.');
|
||||
argParser.addOption('target',
|
||||
abbr: 't',
|
||||
defaultsTo: bundle.defaultMainPath,
|
||||
|
@ -128,8 +132,13 @@ class FuchsiaReloadCommand extends FlutterCommand {
|
|||
final List<Uri> observatoryUris = fullAddresses.map(
|
||||
(String a) => Uri.parse('http://$a')
|
||||
).toList();
|
||||
final FuchsiaDevice device = new FuchsiaDevice(fullAddresses[0], name: _address);
|
||||
final FlutterDevice flutterDevice = new FlutterDevice(device, trackWidgetCreation: false);
|
||||
final FuchsiaDevice device = new FuchsiaDevice(
|
||||
fullAddresses[0], name: _address);
|
||||
final FlutterDevice flutterDevice = new FlutterDevice(
|
||||
device,
|
||||
trackWidgetCreation: false,
|
||||
previewDart2: false,
|
||||
);
|
||||
flutterDevice.observatoryUris = observatoryUris;
|
||||
final HotRunner hotRunner = new HotRunner(
|
||||
<FlutterDevice>[flutterDevice],
|
||||
|
|
|
@ -120,6 +120,11 @@ class RunCommand extends RunCommandBase {
|
|||
hide: !verboseHelp,
|
||||
help: 'Specify a pre-built application binary to use when running.',
|
||||
)
|
||||
..addFlag('preview-dart-2',
|
||||
defaultsTo: true,
|
||||
hide: !verboseHelp,
|
||||
help: 'Preview Dart 2.0 functionality.',
|
||||
)
|
||||
..addFlag('track-widget-creation',
|
||||
hide: !verboseHelp,
|
||||
help: 'Track widget creation locations. Requires Dart 2.0 functionality.',
|
||||
|
@ -342,6 +347,7 @@ class RunCommand extends RunCommandBase {
|
|||
final List<FlutterDevice> flutterDevices = devices.map((Device device) {
|
||||
return new FlutterDevice(
|
||||
device,
|
||||
previewDart2: argResults['preview-dart-2'],
|
||||
trackWidgetCreation: argResults['track-widget-creation'],
|
||||
dillOutputPath: argResults['output-dill'],
|
||||
fileSystemRoots: argResults['filesystem-root'],
|
||||
|
|
|
@ -68,6 +68,11 @@ class TestCommand extends FlutterCommand {
|
|||
help: 'Handle machine structured JSON command input\n'
|
||||
'and provide output and progress in machine friendly format.',
|
||||
)
|
||||
..addFlag('preview-dart-2',
|
||||
defaultsTo: true,
|
||||
hide: !verboseHelp,
|
||||
help: 'Preview Dart 2.0 functionality.',
|
||||
)
|
||||
..addFlag('track-widget-creation',
|
||||
negatable: false,
|
||||
hide: !verboseHelp,
|
||||
|
@ -218,6 +223,7 @@ class TestCommand extends FlutterCommand {
|
|||
startPaused: startPaused,
|
||||
ipv6: argResults['ipv6'],
|
||||
machine: machine,
|
||||
previewDart2: argResults['preview-dart-2'],
|
||||
trackWidgetCreation: argResults['track-widget-creation'],
|
||||
updateGoldens: argResults['update-goldens'],
|
||||
);
|
||||
|
|
|
@ -13,10 +13,11 @@ import '../base/process_manager.dart';
|
|||
import '../globals.dart';
|
||||
|
||||
class AnalysisServer {
|
||||
AnalysisServer(this.sdkPath, this.directories);
|
||||
AnalysisServer(this.sdkPath, this.directories, {this.previewDart2 = false});
|
||||
|
||||
final String sdkPath;
|
||||
final List<String> directories;
|
||||
final bool previewDart2;
|
||||
|
||||
Process _process;
|
||||
final StreamController<bool> _analyzingController =
|
||||
|
@ -34,9 +35,14 @@ class AnalysisServer {
|
|||
snapshot,
|
||||
'--sdk',
|
||||
sdkPath,
|
||||
'--preview-dart-2',
|
||||
];
|
||||
|
||||
if (previewDart2) {
|
||||
command.add('--preview-dart-2');
|
||||
} else {
|
||||
command.add('--no-preview-dart-2');
|
||||
}
|
||||
|
||||
printTrace('dart ${command.skip(1).join(' ')}');
|
||||
_process = await processManager.start(command);
|
||||
// This callback hookup can't throw.
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'dart:async';
|
|||
import 'dart:convert' show base64, utf8;
|
||||
|
||||
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'asset.dart';
|
||||
import 'base/context.dart';
|
||||
|
@ -402,14 +401,14 @@ class DevFS {
|
|||
///
|
||||
/// Returns the number of bytes synced.
|
||||
Future<int> update({
|
||||
@required String mainPath,
|
||||
String mainPath,
|
||||
String target,
|
||||
AssetBundle bundle,
|
||||
DateTime firstBuildTime,
|
||||
bool bundleFirstUpload = false,
|
||||
bool bundleDirty = false,
|
||||
Set<String> fileFilter,
|
||||
@required ResidentCompiler generator,
|
||||
ResidentCompiler generator,
|
||||
String dillOutputPath,
|
||||
bool fullRestart = false,
|
||||
String projectRootPath,
|
||||
|
@ -425,9 +424,10 @@ class DevFS {
|
|||
await _scanDirectory(rootDirectory,
|
||||
recursive: true,
|
||||
fileFilter: fileFilter);
|
||||
final bool previewDart2 = generator != null;
|
||||
if (fs.isFileSync(_packagesFilePath)) {
|
||||
printTrace('Scanning package files');
|
||||
await _scanPackages(fileFilter);
|
||||
await _scanPackages(fileFilter, previewDart2);
|
||||
}
|
||||
if (bundle != null) {
|
||||
printTrace('Scanning asset files');
|
||||
|
@ -468,9 +468,10 @@ class DevFS {
|
|||
String archivePath;
|
||||
if (deviceUri.path.startsWith(assetBuildDirPrefix))
|
||||
archivePath = deviceUri.path.substring(assetBuildDirPrefix.length);
|
||||
// When doing full restart in, copy content so that isModified does not
|
||||
// reset last check timestamp because we want to report all modified
|
||||
// files to incremental compiler next time user does hot reload.
|
||||
// When doing full restart in preview-dart-2 mode, copy content so
|
||||
// that isModified does not reset last check timestamp because we
|
||||
// want to report all modified files to incremental compiler next time
|
||||
// user does hot reload.
|
||||
if (content.isModified || ((bundleDirty || bundleFirstUpload) && archivePath != null)) {
|
||||
dirtyEntries[deviceUri] = content;
|
||||
numBytes += content.size;
|
||||
|
@ -478,24 +479,24 @@ class DevFS {
|
|||
assetPathsToEvict.add(archivePath);
|
||||
}
|
||||
});
|
||||
|
||||
// We run generator even if [dirtyEntries] was empty because we want to
|
||||
// keep logic of accepting/rejecting generator's output simple: we must
|
||||
// accept/reject generator's output after every [update] call. Incremental
|
||||
// run with no changes is supposed to be fast (considering that it is
|
||||
// initiated by user key press).
|
||||
final List<String> invalidatedFiles = <String>[];
|
||||
final Set<Uri> filesUris = new Set<Uri>();
|
||||
for (Uri uri in dirtyEntries.keys.toList()) {
|
||||
if (!uri.path.startsWith(assetBuildDirPrefix)) {
|
||||
final DevFSContent content = dirtyEntries[uri];
|
||||
if (content is DevFSFileContent) {
|
||||
filesUris.add(uri);
|
||||
invalidatedFiles.add(content.file.uri.toString());
|
||||
numBytes -= content.size;
|
||||
if (previewDart2) {
|
||||
// We run generator even if [dirtyEntries] was empty because we want
|
||||
// to keep logic of accepting/rejecting generator's output simple:
|
||||
// we must accept/reject generator's output after every [update] call.
|
||||
// Incremental run with no changes is supposed to be fast (considering
|
||||
// that it is initiated by user key press).
|
||||
final List<String> invalidatedFiles = <String>[];
|
||||
final Set<Uri> filesUris = new Set<Uri>();
|
||||
for (Uri uri in dirtyEntries.keys.toList()) {
|
||||
if (!uri.path.startsWith(assetBuildDirPrefix)) {
|
||||
final DevFSContent content = dirtyEntries[uri];
|
||||
if (content is DevFSFileContent) {
|
||||
filesUris.add(uri);
|
||||
invalidatedFiles.add(content.file.uri.toString());
|
||||
numBytes -= content.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No need to send source files because all compilation is done on the
|
||||
// host and result of compilation is single kernel file.
|
||||
filesUris.forEach(dirtyEntries.remove);
|
||||
|
@ -503,12 +504,10 @@ class DevFS {
|
|||
if (fullRestart) {
|
||||
generator.reset();
|
||||
}
|
||||
final CompilerOutput compilerOutput = await generator.recompile(
|
||||
mainPath,
|
||||
invalidatedFiles,
|
||||
outputPath: dillOutputPath ?? fs.path.join(getBuildDirectory(), 'app.dill'),
|
||||
packagesFilePath : _packagesFilePath,
|
||||
);
|
||||
final CompilerOutput compilerOutput =
|
||||
await generator.recompile(mainPath, invalidatedFiles,
|
||||
outputPath: dillOutputPath ?? fs.path.join(getBuildDirectory(), 'app.dill'),
|
||||
packagesFilePath : _packagesFilePath);
|
||||
final String compiledBinary = compilerOutput?.outputFilename;
|
||||
if (compiledBinary != null && compiledBinary.isNotEmpty) {
|
||||
final String entryUri = projectRootPath != null ?
|
||||
|
@ -698,7 +697,7 @@ class DevFS {
|
|||
);
|
||||
}
|
||||
|
||||
Future<Null> _scanPackages(Set<String> fileFilter) async {
|
||||
Future<Null> _scanPackages(Set<String> fileFilter, bool previewDart2) async {
|
||||
StringBuffer sb;
|
||||
final PackageMap packageMap = new PackageMap(_packagesFilePath);
|
||||
|
||||
|
@ -731,6 +730,22 @@ class DevFS {
|
|||
sb.writeln('$packageName:$directoryUriOnDevice');
|
||||
}
|
||||
}
|
||||
if (previewDart2) {
|
||||
// When in previewDart2 mode we don't update .packages-file entry
|
||||
// so actual file will get invalidated in frontend.
|
||||
// We don't need to synthesize device-correct .packages file because
|
||||
// it is not going to be used on the device anyway - compilation
|
||||
// is done on the host.
|
||||
return;
|
||||
}
|
||||
if (sb != null) {
|
||||
final DevFSContent content = _entries[fs.path.toUri('.packages')];
|
||||
if (content is DevFSStringContent && content.string == sb.toString()) {
|
||||
content._exists = true;
|
||||
return;
|
||||
}
|
||||
_entries[fs.path.toUri('.packages')] = new DevFSStringContent(sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Converts a platform-specific file path to a platform-independent Uri path.
|
||||
|
|
|
@ -246,6 +246,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||
projectPath: fs.currentDirectory.path,
|
||||
buildInfo: buildInfo,
|
||||
targetOverride: targetOverride,
|
||||
previewDart2: buildInfo.previewDart2,
|
||||
);
|
||||
|
||||
if (hasPlugins()) {
|
||||
|
@ -427,7 +428,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||
outputDir = expectedOutputDirectory.replaceFirst('/$configuration-', '/');
|
||||
if (fs.isDirectorySync(outputDir)) {
|
||||
// Previous output directory might have incompatible artifacts
|
||||
// (for example, kernel binary files produced from previous run).
|
||||
// (for example, kernel binary files produced from previous `--preview-dart-2` run).
|
||||
fs.directory(outputDir).deleteSync(recursive: true);
|
||||
}
|
||||
copyDirectorySync(fs.directory(expectedOutputDirectory), fs.directory(outputDir));
|
||||
|
|
|
@ -362,6 +362,7 @@ class IOSSimulator extends Device {
|
|||
// The build mode for the simulator is always debug.
|
||||
|
||||
final BuildInfo debugBuildInfo = new BuildInfo(BuildMode.debug, buildInfo.flavor,
|
||||
previewDart2: buildInfo.previewDart2,
|
||||
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
||||
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
|
||||
extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions,
|
||||
|
@ -389,10 +390,12 @@ class IOSSimulator extends Device {
|
|||
}
|
||||
|
||||
Future<Null> _sideloadUpdatedAssetsForInstalledApplicationBundle(ApplicationPackage app, BuildInfo buildInfo, String mainPath) {
|
||||
// Run compiler to produce kernel file for the application.
|
||||
// When running in previewDart2 mode, we still need to run compiler to
|
||||
// produce kernel file for the application.
|
||||
return bundle.build(
|
||||
mainPath: mainPath,
|
||||
precompiledSnapshot: false,
|
||||
precompiledSnapshot: !buildInfo.previewDart2,
|
||||
previewDart2: buildInfo.previewDart2,
|
||||
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ Future<void> generateXcodeProperties(String projectPath) async {
|
|||
projectPath: projectPath,
|
||||
buildInfo: BuildInfo.debug,
|
||||
targetOverride: bundle.defaultMainPath,
|
||||
previewDart2: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +55,7 @@ Future<void> updateGeneratedXcodeProperties({
|
|||
@required String projectPath,
|
||||
@required BuildInfo buildInfo,
|
||||
String targetOverride,
|
||||
@required bool previewDart2,
|
||||
}) async {
|
||||
final StringBuffer localsBuffer = new StringBuffer();
|
||||
|
||||
|
@ -111,6 +113,10 @@ Future<void> updateGeneratedXcodeProperties({
|
|||
localsBuffer.writeln('ARCHS=$arch');
|
||||
}
|
||||
|
||||
if (previewDart2) {
|
||||
localsBuffer.writeln('PREVIEW_DART_2=true');
|
||||
}
|
||||
|
||||
if (buildInfo.trackWidgetCreation) {
|
||||
localsBuffer.writeln('TRACK_WIDGET_CREATION=true');
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class FlutterDevice {
|
|||
List<VMService> vmServices;
|
||||
DevFS devFS;
|
||||
ApplicationPackage package;
|
||||
final ResidentCompiler generator;
|
||||
ResidentCompiler generator;
|
||||
String dillOutputPath;
|
||||
List<String> fileSystemRoots;
|
||||
String fileSystemScheme;
|
||||
|
@ -42,15 +42,20 @@ class FlutterDevice {
|
|||
StreamSubscription<String> _loggingSubscription;
|
||||
|
||||
FlutterDevice(this.device, {
|
||||
@required bool previewDart2,
|
||||
@required bool trackWidgetCreation,
|
||||
this.dillOutputPath,
|
||||
this.fileSystemRoots,
|
||||
this.fileSystemScheme,
|
||||
}) : generator = new ResidentCompiler(
|
||||
artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
fileSystemRoots: fileSystemRoots,
|
||||
fileSystemScheme: fileSystemScheme);
|
||||
}) {
|
||||
if (previewDart2) {
|
||||
generator = new ResidentCompiler(
|
||||
artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
fileSystemRoots: fileSystemRoots, fileSystemScheme: fileSystemScheme
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String viewFilter;
|
||||
|
||||
|
@ -407,9 +412,9 @@ class FlutterDevice {
|
|||
|
||||
void updateReloadStatus(bool wasReloadSuccessful) {
|
||||
if (wasReloadSuccessful)
|
||||
generator.accept();
|
||||
generator?.accept();
|
||||
else
|
||||
generator.reject();
|
||||
generator?.reject();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -412,11 +412,15 @@ class HotRunner extends ResidentRunner {
|
|||
}
|
||||
// We are now running from source.
|
||||
_runningFromSnapshot = false;
|
||||
|
||||
await _launchFromDevFS('$mainPath.dill');
|
||||
final String launchPath = debuggingOptions.buildInfo.previewDart2
|
||||
? mainPath + '.dill'
|
||||
: mainPath;
|
||||
await _launchFromDevFS(launchPath);
|
||||
restartTimer.stop();
|
||||
printTrace('Restart performed in ${getElapsedAsMilliseconds(restartTimer.elapsed)}.');
|
||||
|
||||
printTrace('Restart performed in '
|
||||
'${getElapsedAsMilliseconds(restartTimer.elapsed)}.');
|
||||
// We are now running from sources.
|
||||
_runningFromSnapshot = false;
|
||||
_addBenchmarkData('hotRestartMillisecondsToFrame',
|
||||
restartTimer.elapsed.inMilliseconds);
|
||||
flutterUsage.sendEvent('hot', 'restart');
|
||||
|
@ -506,6 +510,14 @@ class HotRunner extends ResidentRunner {
|
|||
}
|
||||
}
|
||||
|
||||
String _uriToRelativePath(Uri uri) {
|
||||
final String path = uri.toString();
|
||||
final String base = new Uri.file(projectRootPath).toString();
|
||||
if (path.startsWith(base))
|
||||
return path.substring(base.length + 1);
|
||||
return path;
|
||||
}
|
||||
|
||||
Future<OperationResult> _reloadSources({ bool pause = false }) async {
|
||||
for (FlutterDevice device in flutterDevices) {
|
||||
for (FlutterView view in device.views) {
|
||||
|
@ -525,6 +537,7 @@ class HotRunner extends ResidentRunner {
|
|||
// change from host path to a device path). Subsequent reloads will
|
||||
// not be affected, so we resume reporting reload times on the second
|
||||
// reload.
|
||||
final bool reportUnused = !debuggingOptions.buildInfo.previewDart2;
|
||||
final bool shouldReportReloadTime = !_runningFromSnapshot;
|
||||
final Stopwatch reloadTimer = new Stopwatch()..start();
|
||||
|
||||
|
@ -538,7 +551,10 @@ class HotRunner extends ResidentRunner {
|
|||
String reloadMessage;
|
||||
final Stopwatch vmReloadTimer = new Stopwatch()..start();
|
||||
try {
|
||||
final String entryPath = fs.path.relative('$mainPath.dill', from: projectRootPath);
|
||||
final String entryPath = fs.path.relative(
|
||||
debuggingOptions.buildInfo.previewDart2 ? mainPath + '.dill' : mainPath,
|
||||
from: projectRootPath,
|
||||
);
|
||||
final Completer<Map<String, dynamic>> retrieveFirstReloadReport = new Completer<Map<String, dynamic>>();
|
||||
|
||||
int countExpectedReports = 0;
|
||||
|
@ -550,7 +566,10 @@ class HotRunner extends ResidentRunner {
|
|||
}
|
||||
|
||||
// List has one report per Flutter view.
|
||||
final List<Future<Map<String, dynamic>>> reports = device.reloadSources(entryPath, pause: pause);
|
||||
final List<Future<Map<String, dynamic>>> reports = device.reloadSources(
|
||||
entryPath,
|
||||
pause: pause
|
||||
);
|
||||
countExpectedReports += reports.length;
|
||||
Future.wait(reports).catchError((dynamic error) {
|
||||
return <Map<String, dynamic>>[error];
|
||||
|
@ -618,8 +637,8 @@ class HotRunner extends ResidentRunner {
|
|||
}
|
||||
// We are now running from source.
|
||||
_runningFromSnapshot = false;
|
||||
|
||||
// Check if the isolate is paused.
|
||||
|
||||
final List<FlutterView> reassembleViews = <FlutterView>[];
|
||||
for (FlutterDevice device in flutterDevices) {
|
||||
for (FlutterView view in device.views) {
|
||||
|
@ -680,9 +699,36 @@ class HotRunner extends ResidentRunner {
|
|||
shouldReportReloadTime)
|
||||
flutterUsage.sendTiming('hot', 'reload', reloadTimer.elapsed);
|
||||
|
||||
String unusedElementMessage;
|
||||
if (reportUnused && !reassembleAndScheduleErrors && !reassembleTimedOut) {
|
||||
final List<Future<List<ProgramElement>>> unusedReports =
|
||||
<Future<List<ProgramElement>>>[];
|
||||
for (FlutterDevice device in flutterDevices)
|
||||
unusedReports.add(device.unusedChangesInLastReload());
|
||||
final List<ProgramElement> unusedElements = <ProgramElement>[];
|
||||
for (Future<List<ProgramElement>> unusedReport in unusedReports)
|
||||
unusedElements.addAll(await unusedReport);
|
||||
|
||||
if (unusedElements.isNotEmpty) {
|
||||
final String restartCommand = hostIsIde ? '' : ' (by pressing "R")';
|
||||
unusedElementMessage =
|
||||
'Some program elements were changed during reload but did not run when the view was reassembled;\n'
|
||||
'you may need to restart the app$restartCommand for the changes to have an effect.';
|
||||
for (ProgramElement unusedElement in unusedElements) {
|
||||
final String name = unusedElement.qualifiedName;
|
||||
final String path = _uriToRelativePath(unusedElement.uri);
|
||||
final int line = unusedElement.line;
|
||||
final String description = line == null ? '$name ($path)' : '$name ($path:$line)';
|
||||
unusedElementMessage += '\n • $description';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new OperationResult(
|
||||
reassembleAndScheduleErrors ? 1 : OperationResult.ok.code,
|
||||
reloadMessage,
|
||||
hintMessage: unusedElementMessage,
|
||||
hintId: unusedElementMessage != null ? 'restartRecommended' : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -182,6 +182,10 @@ abstract class FlutterCommand extends Command<Null> {
|
|||
}
|
||||
|
||||
BuildInfo getBuildInfo() {
|
||||
final bool previewDart2 = argParser.options.containsKey('preview-dart-2')
|
||||
? argResults['preview-dart-2']
|
||||
: true;
|
||||
|
||||
TargetPlatform targetPlatform;
|
||||
if (argParser.options.containsKey('target-platform') &&
|
||||
argResults['target-platform'] != 'default') {
|
||||
|
@ -191,6 +195,10 @@ abstract class FlutterCommand extends Command<Null> {
|
|||
final bool trackWidgetCreation = argParser.options.containsKey('track-widget-creation')
|
||||
? argResults['track-widget-creation']
|
||||
: false;
|
||||
if (trackWidgetCreation == true && previewDart2 == false) {
|
||||
throw new UsageException(
|
||||
'--track-widget-creation is valid only when --preview-dart-2 is specified.', null);
|
||||
}
|
||||
|
||||
int buildNumber;
|
||||
try {
|
||||
|
@ -206,6 +214,7 @@ abstract class FlutterCommand extends Command<Null> {
|
|||
argParser.options.containsKey('flavor')
|
||||
? argResults['flavor']
|
||||
: null,
|
||||
previewDart2: previewDart2,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
extraFrontEndOptions: argParser.options.containsKey(FlutterOptions.kExtraFrontEndOptions)
|
||||
? argResults[FlutterOptions.kExtraFrontEndOptions]
|
||||
|
|
|
@ -67,6 +67,7 @@ void installHook({
|
|||
bool enableObservatory = false,
|
||||
bool machine = false,
|
||||
bool startPaused = false,
|
||||
bool previewDart2 = false,
|
||||
int port = 0,
|
||||
String precompiledDillPath,
|
||||
bool trackWidgetCreation = false,
|
||||
|
@ -85,6 +86,7 @@ void installHook({
|
|||
startPaused: startPaused,
|
||||
explicitObservatoryPort: observatoryPort,
|
||||
host: _kHosts[serverType],
|
||||
previewDart2: previewDart2,
|
||||
port: port,
|
||||
precompiledDillPath: precompiledDillPath,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
|
@ -304,6 +306,7 @@ class _FlutterPlatform extends PlatformPlugin {
|
|||
this.startPaused,
|
||||
this.explicitObservatoryPort,
|
||||
this.host,
|
||||
this.previewDart2,
|
||||
this.port,
|
||||
this.precompiledDillPath,
|
||||
this.trackWidgetCreation,
|
||||
|
@ -317,6 +320,7 @@ class _FlutterPlatform extends PlatformPlugin {
|
|||
final bool startPaused;
|
||||
final int explicitObservatoryPort;
|
||||
final InternetAddress host;
|
||||
final bool previewDart2;
|
||||
final int port;
|
||||
final String precompiledDillPath;
|
||||
final bool trackWidgetCreation;
|
||||
|
@ -404,15 +408,17 @@ class _FlutterPlatform extends PlatformPlugin {
|
|||
cancelOnError: true,
|
||||
);
|
||||
|
||||
printTrace('test $ourTestCount: starting shell process');
|
||||
printTrace('test $ourTestCount: starting shell process${previewDart2? " in preview-dart-2 mode":""}');
|
||||
|
||||
// [precompiledDillPath] can be set only if [previewDart2] is [true].
|
||||
assert(precompiledDillPath == null || previewDart2);
|
||||
// If a kernel file is given, then use that to launch the test.
|
||||
// Otherwise create a "listener" dart that invokes actual test.
|
||||
String mainDart = precompiledDillPath != null
|
||||
? precompiledDillPath
|
||||
: _createListenerDart(finalizers, ourTestCount, testPath, server);
|
||||
|
||||
if (precompiledDillPath == null) {
|
||||
if (previewDart2 && precompiledDillPath == null) {
|
||||
// Lazily instantiate compiler so it is built only if it is actually used.
|
||||
compiler ??= new _Compiler(trackWidgetCreation);
|
||||
mainDart = await compiler.compile(mainDart);
|
||||
|
@ -669,6 +675,10 @@ class _FlutterPlatform extends PlatformPlugin {
|
|||
}
|
||||
|
||||
String _getBundlePath(List<_Finalizer> finalizers, int ourTestCount) {
|
||||
if (!previewDart2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (precompiledDillPath != null) {
|
||||
return artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
// ignore: implementation_imports
|
||||
import 'package:test/src/executable.dart' as test;
|
||||
|
||||
|
@ -28,10 +29,18 @@ Future<int> runTests(
|
|||
bool startPaused = false,
|
||||
bool ipv6 = false,
|
||||
bool machine = false,
|
||||
bool previewDart2 = false,
|
||||
bool trackWidgetCreation = false,
|
||||
bool updateGoldens = false,
|
||||
TestWatcher watcher,
|
||||
}) async {
|
||||
if (trackWidgetCreation && !previewDart2) {
|
||||
throw new UsageException(
|
||||
'--track-widget-creation is valid only when --preview-dart-2 is specified.',
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
// Compute the command-line arguments for package:test.
|
||||
final List<String> testArgs = <String>[];
|
||||
if (!terminal.supportsColor) {
|
||||
|
@ -78,6 +87,7 @@ Future<int> runTests(
|
|||
machine: machine,
|
||||
startPaused: startPaused,
|
||||
serverType: serverType,
|
||||
previewDart2: previewDart2,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
updateGoldens: updateGoldens,
|
||||
);
|
||||
|
|
|
@ -133,11 +133,20 @@ class FlutterTesterDevice extends Device {
|
|||
mainPath: mainPath,
|
||||
assetDirPath: assetDirPath,
|
||||
applicationKernelFilePath: applicationKernelFilePath,
|
||||
precompiledSnapshot: false,
|
||||
precompiledSnapshot: !buildInfo.previewDart2,
|
||||
previewDart2: buildInfo.previewDart2,
|
||||
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
||||
);
|
||||
if (buildInfo.previewDart2) {
|
||||
mainPath = applicationKernelFilePath;
|
||||
}
|
||||
|
||||
command.add('--flutter-assets-dir=$assetDirPath');
|
||||
command.add(applicationKernelFilePath);
|
||||
|
||||
// TODO(scheglov): Either remove the check, or make it fail earlier.
|
||||
if (mainPath != null) {
|
||||
command.add(mainPath);
|
||||
}
|
||||
|
||||
try {
|
||||
printTrace(command.join(' '));
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert' show json;
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_sdk.dart';
|
||||
|
@ -84,6 +85,199 @@ void main() {
|
|||
});
|
||||
});
|
||||
|
||||
group('Snapshotter - Script Snapshots', () {
|
||||
const String kVersion = '123456abcdef';
|
||||
const String kIsolateSnapshotData = 'isolate_snapshot.bin';
|
||||
const String kVmSnapshotData = 'vm_isolate_snapshot.bin';
|
||||
|
||||
_FakeGenSnapshot genSnapshot;
|
||||
MemoryFileSystem fs;
|
||||
MockFlutterVersion mockVersion;
|
||||
ScriptSnapshotter snapshotter;
|
||||
MockArtifacts mockArtifacts;
|
||||
|
||||
setUp(() {
|
||||
fs = new MemoryFileSystem();
|
||||
fs.file(kIsolateSnapshotData).writeAsStringSync('snapshot data');
|
||||
fs.file(kVmSnapshotData).writeAsStringSync('vm data');
|
||||
genSnapshot = new _FakeGenSnapshot();
|
||||
genSnapshot.outputs = <String, String>{
|
||||
'output.snapshot': '',
|
||||
'output.snapshot.d': 'output.snapshot.d : main.dart',
|
||||
};
|
||||
mockVersion = new MockFlutterVersion();
|
||||
when(mockVersion.frameworkRevision).thenReturn(kVersion);
|
||||
snapshotter = new ScriptSnapshotter();
|
||||
mockArtifacts = new MockArtifacts();
|
||||
when(mockArtifacts.getArtifactPath(Artifact.isolateSnapshotData)).thenReturn(kIsolateSnapshotData);
|
||||
when(mockArtifacts.getArtifactPath(Artifact.vmSnapshotData)).thenReturn(kVmSnapshotData);
|
||||
});
|
||||
|
||||
final Map<Type, Generator> contextOverrides = <Type, Generator>{
|
||||
Artifacts: () => mockArtifacts,
|
||||
FileSystem: () => fs,
|
||||
FlutterVersion: () => mockVersion,
|
||||
GenSnapshot: () => genSnapshot,
|
||||
};
|
||||
|
||||
Future<void> writeFingerprint({ Map<String, String> files = const <String, String>{} }) {
|
||||
return fs.file('output.snapshot.d.fingerprint').writeAsString(json.encode(<String, dynamic>{
|
||||
'version': kVersion,
|
||||
'properties': <String, String>{
|
||||
'buildMode': BuildMode.debug.toString(),
|
||||
'targetPlatform': '',
|
||||
'entryPoint': 'main.dart',
|
||||
},
|
||||
'files': <String, dynamic>{
|
||||
kVmSnapshotData: '2ec34912477a46c03ddef07e8b909b46',
|
||||
kIsolateSnapshotData: '621b3844bb7d4d17d2cfc5edf9a91c4c',
|
||||
}..addAll(files),
|
||||
}));
|
||||
}
|
||||
|
||||
void expectFingerprintHas({
|
||||
String entryPoint = 'main.dart',
|
||||
Map<String, String> checksums = const <String, String>{},
|
||||
}) {
|
||||
final Map<String, dynamic> jsonObject = json.decode(fs.file('output.snapshot.d.fingerprint').readAsStringSync());
|
||||
expect(jsonObject['properties']['entryPoint'], entryPoint);
|
||||
expect(jsonObject['files'], hasLength(checksums.length + 2));
|
||||
checksums.forEach((String filePath, String checksum) {
|
||||
expect(jsonObject['files'][filePath], checksum);
|
||||
});
|
||||
expect(jsonObject['files'][kVmSnapshotData], '2ec34912477a46c03ddef07e8b909b46');
|
||||
expect(jsonObject['files'][kIsolateSnapshotData], '621b3844bb7d4d17d2cfc5edf9a91c4c');
|
||||
}
|
||||
|
||||
testUsingContext('builds snapshot and fingerprint when no fingerprint is present', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot').create();
|
||||
await fs.file('output.snapshot.d').writeAsString('snapshot : main.dart');
|
||||
await snapshotter.build(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
expect(genSnapshot.snapshotType.platform, isNull);
|
||||
expect(genSnapshot.snapshotType.mode, BuildMode.debug);
|
||||
expect(genSnapshot.packagesPath, '.packages');
|
||||
expect(genSnapshot.depfilePath, 'output.snapshot.d');
|
||||
expect(genSnapshot.additionalArgs, <String>[
|
||||
'--snapshot_kind=script',
|
||||
'--script_snapshot=output.snapshot',
|
||||
'--vm_snapshot_data=vm_isolate_snapshot.bin',
|
||||
'--isolate_snapshot_data=isolate_snapshot.bin',
|
||||
'--enable-mirrors=false',
|
||||
'main.dart',
|
||||
]);
|
||||
expectFingerprintHas(checksums: <String, String>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
});
|
||||
}, overrides: contextOverrides);
|
||||
|
||||
testUsingContext('builds snapshot and fingerprint when fingerprints differ', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot').create();
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await writeFingerprint(files: <String, String>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'deadbeef000b204e9800998ecaaaaa',
|
||||
});
|
||||
await snapshotter.build(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
expectFingerprintHas(checksums: <String, String>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
});
|
||||
}, overrides: contextOverrides);
|
||||
|
||||
testUsingContext('builds snapshot and fingerprint when fingerprints match but previous snapshot not present', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await writeFingerprint(files: <String, String>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
});
|
||||
await snapshotter.build(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
expectFingerprintHas(checksums: <String, String>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
});
|
||||
}, overrides: contextOverrides);
|
||||
|
||||
testUsingContext('builds snapshot and fingerprint when main entry point changes to other dependency', () async {
|
||||
await fs.file('main.dart').writeAsString('import "other.dart";\nvoid main() {}');
|
||||
await fs.file('other.dart').writeAsString('import "main.dart";\nvoid main() {}');
|
||||
await fs.file('output.snapshot').create();
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await writeFingerprint(files: <String, String>{
|
||||
'main.dart': 'bc096b33f14dde5e0ffaf93a1d03395c',
|
||||
'other.dart': 'e0c35f083f0ad76b2d87100ec678b516',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
});
|
||||
genSnapshot.outputs = <String, String>{
|
||||
'output.snapshot': '',
|
||||
'output.snapshot.d': 'output.snapshot : main.dart other.dart',
|
||||
};
|
||||
|
||||
await snapshotter.build(
|
||||
mainPath: 'other.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
expectFingerprintHas(
|
||||
entryPoint: 'other.dart',
|
||||
checksums: <String, String>{
|
||||
'main.dart': 'bc096b33f14dde5e0ffaf93a1d03395c',
|
||||
'other.dart': 'e0c35f083f0ad76b2d87100ec678b516',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
},
|
||||
);
|
||||
}, overrides: contextOverrides);
|
||||
|
||||
testUsingContext('skips snapshot when fingerprints match and previous snapshot is present', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot').create();
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await writeFingerprint(files: <String, String>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
});
|
||||
await snapshotter.build(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 0);
|
||||
expectFingerprintHas(checksums: <String, String>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
});
|
||||
}, overrides: contextOverrides);
|
||||
});
|
||||
|
||||
group('Snapshotter - iOS AOT', () {
|
||||
const String kVmEntrypoints = 'dart_vm_entry_points.txt';
|
||||
const String kIoEntries = 'dart_io_entries.txt';
|
||||
|
@ -146,6 +340,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
), isNot(equals(0)));
|
||||
}, overrides: contextOverrides);
|
||||
|
||||
|
@ -158,6 +353,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
), isNot(0));
|
||||
}, overrides: contextOverrides);
|
||||
|
||||
|
@ -170,6 +366,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
), isNot(0));
|
||||
}, overrides: contextOverrides);
|
||||
|
||||
|
@ -195,6 +392,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
iosArch: IOSArch.armv7,
|
||||
);
|
||||
|
||||
|
@ -241,6 +439,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
iosArch: IOSArch.arm64,
|
||||
);
|
||||
|
||||
|
@ -288,6 +487,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
expect(genSnapshotExitCode, 0);
|
||||
|
@ -339,6 +539,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
expect(genSnapshotExitCode, 0);
|
||||
|
@ -385,6 +586,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
iosArch: IOSArch.armv7,
|
||||
);
|
||||
|
||||
|
@ -431,6 +633,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
iosArch: IOSArch.arm64,
|
||||
);
|
||||
|
||||
|
@ -465,6 +668,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: true,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
expect(genSnapshotExitCode, isNot(0));
|
||||
|
@ -496,6 +700,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
expect(genSnapshotExitCode, 0);
|
||||
|
@ -547,6 +752,7 @@ void main() {
|
|||
packagesPath: '.packages',
|
||||
outputPath: outputPath,
|
||||
buildSharedLibrary: false,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
expect(genSnapshotExitCode, 0);
|
||||
|
|
|
@ -70,10 +70,10 @@ void main() {
|
|||
OperatingSystemUtils: () => os
|
||||
});
|
||||
|
||||
testUsingContext('Returns no errors when source is error-free', () async {
|
||||
testUsingContext('--preview-dart-2', () async {
|
||||
const String contents = "StringBuffer bar = StringBuffer('baz');";
|
||||
tempDir.childFile('main.dart').writeAsStringSync(contents);
|
||||
server = new AnalysisServer(dartSdkPath, <String>[tempDir.path]);
|
||||
server = new AnalysisServer(dartSdkPath, <String>[tempDir.path], previewDart2: true);
|
||||
|
||||
int errorCount = 0;
|
||||
final Future<bool> onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first;
|
||||
|
@ -88,6 +88,25 @@ void main() {
|
|||
}, overrides: <Type, Generator>{
|
||||
OperatingSystemUtils: () => os
|
||||
});
|
||||
|
||||
testUsingContext('no --preview-dart-2 shows errors', () async {
|
||||
const String contents = "StringBuffer bar = StringBuffer('baz');";
|
||||
tempDir.childFile('main.dart').writeAsStringSync(contents);
|
||||
server = new AnalysisServer(dartSdkPath, <String>[tempDir.path], previewDart2: false);
|
||||
|
||||
int errorCount = 0;
|
||||
final Future<bool> onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first;
|
||||
server.onErrors.listen((FileAnalysisErrors errors) {
|
||||
errorCount += errors.errors.length;
|
||||
});
|
||||
|
||||
await server.start();
|
||||
await onDone;
|
||||
|
||||
expect(errorCount, 1);
|
||||
}, overrides: <Type, Generator>{
|
||||
OperatingSystemUtils: () => os
|
||||
});
|
||||
}
|
||||
|
||||
void _createSampleProject(Directory directory, { bool brokenCode = false }) {
|
||||
|
|
|
@ -168,7 +168,7 @@ void bar() {
|
|||
}
|
||||
});
|
||||
|
||||
testUsingContext('returns no issues when source is error-free', () async {
|
||||
testUsingContext('--preview-dart-2', () async {
|
||||
const String contents = '''
|
||||
StringBuffer bar = StringBuffer('baz');
|
||||
''';
|
||||
|
@ -179,13 +179,33 @@ StringBuffer bar = StringBuffer('baz');
|
|||
try {
|
||||
await runCommand(
|
||||
command: new AnalyzeCommand(workingDirectory: fs.directory(tempDir)),
|
||||
arguments: <String>['analyze'],
|
||||
arguments: <String>['analyze', '--preview-dart-2'],
|
||||
statusTextContains: <String>['No issues found!'],
|
||||
);
|
||||
} finally {
|
||||
tempDir.deleteSync(recursive: true);
|
||||
}
|
||||
});
|
||||
|
||||
testUsingContext('no --preview-dart-2 shows errors', () async {
|
||||
const String contents = '''
|
||||
StringBuffer bar = StringBuffer('baz');
|
||||
''';
|
||||
|
||||
final Directory tempDir = fs.systemTempDirectory.createTempSync();
|
||||
tempDir.childFile('main.dart').writeAsStringSync(contents);
|
||||
|
||||
try {
|
||||
await runCommand(
|
||||
command: new AnalyzeCommand(workingDirectory: fs.directory(tempDir)),
|
||||
arguments: <String>['analyze', '--no-preview-dart-2'],
|
||||
statusTextContains: <String>['1 issue found.'],
|
||||
toolExit: true,
|
||||
);
|
||||
} finally {
|
||||
tempDir.deleteSync(recursive: true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void main() {
|
|||
appStarter = (DriveCommand command) {
|
||||
throw 'Unexpected call to appStarter';
|
||||
};
|
||||
testRunner = (List<String> testArgs, String observatoryUri) {
|
||||
testRunner = (List<String> testArgs, String observatoryUri, bool previewDart2) {
|
||||
throw 'Unexpected call to testRunner';
|
||||
};
|
||||
appStopper = (DriveCommand command) {
|
||||
|
@ -169,7 +169,7 @@ void main() {
|
|||
appStarter = expectAsync1((DriveCommand command) async {
|
||||
return new LaunchResult.succeeded();
|
||||
});
|
||||
testRunner = expectAsync2((List<String> testArgs, String observatoryUri) async {
|
||||
testRunner = expectAsync3((List<String> testArgs, String observatoryUri, bool previewDart2) async {
|
||||
expect(testArgs, <String>[testFile]);
|
||||
return null;
|
||||
});
|
||||
|
@ -200,7 +200,7 @@ void main() {
|
|||
appStarter = expectAsync1((DriveCommand command) async {
|
||||
return new LaunchResult.succeeded();
|
||||
});
|
||||
testRunner = (List<String> testArgs, String observatoryUri) async {
|
||||
testRunner = (List<String> testArgs, String observatoryUri, bool previewDart2) async {
|
||||
throwToolExit(null, exitCode: 123);
|
||||
};
|
||||
appStopper = expectAsync1((DriveCommand command) async {
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:flutter_tools/src/asset.dart';
|
|||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/devfs.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
|
||||
|
@ -68,7 +67,6 @@ void main() {
|
|||
|
||||
group('devfs local', () {
|
||||
final MockDevFSOperations devFSOperations = new MockDevFSOperations();
|
||||
final MockResidentCompiler residentCompiler = new MockResidentCompiler();
|
||||
|
||||
setUpAll(() {
|
||||
tempDir = _newTempDir(fs);
|
||||
|
@ -91,13 +89,22 @@ void main() {
|
|||
devFSOperations.expectMessages(<String>['create test']);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
final int bytes = await devFS.update();
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test .packages',
|
||||
'writeFile test lib/foo.txt',
|
||||
'writeFile test packages/somepkg/somefile.txt',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
|
||||
expect(bytes, 22);
|
||||
final List<String> packageSpecOnDevice = LineSplitter.split(utf8.decode(
|
||||
await devFSOperations.devicePathToContent[fs.path.toUri('.packages')].contentsAsBytes()
|
||||
)).toList();
|
||||
expect(packageSpecOnDevice,
|
||||
unorderedEquals(<String>['my_project:lib/', 'somepkg:packages/somepkg/'])
|
||||
);
|
||||
|
||||
expect(bytes, 48);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
@ -106,33 +113,48 @@ void main() {
|
|||
final File file = fs.file(fs.path.join(basePath, filePath2));
|
||||
await file.parent.create(recursive: true);
|
||||
file.writeAsBytesSync(<int>[1, 2, 3, 4, 5, 6, 7]);
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
final int bytes = await devFS.update();
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test foo/bar.txt',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
expect(bytes, 22);
|
||||
expect(bytes, 7);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
||||
testUsingContext('add new file to local file system and preserve unusual file name casing', () async {
|
||||
final String filePathWithUnusualCasing = fs.path.join('FooBar', 'TEST.txt');
|
||||
final File file = fs.file(fs.path.join(basePath, filePathWithUnusualCasing));
|
||||
await file.parent.create(recursive: true);
|
||||
file.writeAsBytesSync(<int>[1, 2, 3, 4, 5, 6, 7]);
|
||||
final int bytes = await devFS.update();
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test FooBar/TEST.txt',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
expect(bytes, 7);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
||||
testUsingContext('modify existing file on local file system', () async {
|
||||
await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
await devFS.update();
|
||||
final File file = fs.file(fs.path.join(basePath, filePath));
|
||||
// Set the last modified time to 5 seconds in the past.
|
||||
updateFileModificationTime(file.path, new DateTime.now(), -5);
|
||||
int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
int bytes = await devFS.update();
|
||||
devFSOperations.expectMessages(<String>[]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
expect(bytes, 0);
|
||||
|
||||
await file.writeAsBytes(<int>[1, 2, 3, 4, 5, 6]);
|
||||
bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
bytes = await devFS.update();
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test lib/foo.txt',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
expect(bytes, 22);
|
||||
expect(bytes, 6);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
@ -140,7 +162,7 @@ void main() {
|
|||
testUsingContext('delete a file from the local file system', () async {
|
||||
final File file = fs.file(fs.path.join(basePath, filePath));
|
||||
await file.delete();
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
final int bytes = await devFS.update();
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'deleteFile test lib/foo.txt',
|
||||
]);
|
||||
|
@ -152,12 +174,13 @@ void main() {
|
|||
|
||||
testUsingContext('add new package', () async {
|
||||
await _createPackage(fs, 'newpkg', 'anotherfile.txt');
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
final int bytes = await devFS.update();
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test .packages',
|
||||
'writeFile test packages/newpkg/anotherfile.txt',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
expect(bytes, 22);
|
||||
expect(bytes, 69);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
@ -178,65 +201,63 @@ void main() {
|
|||
.map((FileSystemEntity file) => canonicalizePath(file.path))
|
||||
.toList());
|
||||
}
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', fileFilter: fileFilter, generator: residentCompiler);
|
||||
final int bytes = await devFS.update(fileFilter: fileFilter);
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test .packages',
|
||||
'writeFile test packages/doubleslashpkg/somefile.txt',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
expect(bytes, 22);
|
||||
expect(bytes, 109);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
||||
testUsingContext('add an asset bundle', () async {
|
||||
assetBundle.entries['a.txt'] = new DevFSStringContent('abc');
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, bundleDirty: true, generator: residentCompiler);
|
||||
final int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true);
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test ${_inAssetBuildDirectory(fs, 'a.txt')}',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, unorderedMatches(<String>['a.txt']));
|
||||
devFS.assetPathsToEvict.clear();
|
||||
expect(bytes, 22 + 3);
|
||||
expect(bytes, 3);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
||||
testUsingContext('add a file to the asset bundle - bundleDirty', () async {
|
||||
assetBundle.entries['b.txt'] = new DevFSStringContent('abcd');
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, bundleDirty: true, generator: residentCompiler);
|
||||
final int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true);
|
||||
// Expect entire asset bundle written because bundleDirty is true
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test ${_inAssetBuildDirectory(fs, 'a.txt')}',
|
||||
'writeFile test ${_inAssetBuildDirectory(fs, 'b.txt')}',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
|
||||
'a.txt', 'b.txt']));
|
||||
devFS.assetPathsToEvict.clear();
|
||||
expect(bytes, 22 + 7);
|
||||
expect(bytes, 7);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
||||
testUsingContext('add a file to the asset bundle', () async {
|
||||
assetBundle.entries['c.txt'] = new DevFSStringContent('12');
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, generator: residentCompiler);
|
||||
final int bytes = await devFS.update(bundle: assetBundle);
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test ${_inAssetBuildDirectory(fs, 'c.txt')}',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
|
||||
'c.txt']));
|
||||
devFS.assetPathsToEvict.clear();
|
||||
expect(bytes, 22 + 2);
|
||||
expect(bytes, 2);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
||||
testUsingContext('delete a file from the asset bundle', () async {
|
||||
assetBundle.entries.remove('c.txt');
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, generator: residentCompiler);
|
||||
final int bytes = await devFS.update(bundle: assetBundle);
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'deleteFile test ${_inAssetBuildDirectory(fs, 'c.txt')}',
|
||||
]);
|
||||
|
@ -249,7 +270,7 @@ void main() {
|
|||
|
||||
testUsingContext('delete all files from the asset bundle', () async {
|
||||
assetBundle.entries.clear();
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', bundle: assetBundle, bundleDirty: true, generator: residentCompiler);
|
||||
final int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true);
|
||||
devFSOperations.expectMessages(<String>[
|
||||
'deleteFile test ${_inAssetBuildDirectory(fs, 'a.txt')}',
|
||||
'deleteFile test ${_inAssetBuildDirectory(fs, 'b.txt')}',
|
||||
|
@ -274,7 +295,6 @@ void main() {
|
|||
|
||||
group('devfs remote', () {
|
||||
MockVMService vmService;
|
||||
final MockResidentCompiler residentCompiler = new MockResidentCompiler();
|
||||
|
||||
setUpAll(() async {
|
||||
tempDir = _newTempDir(fs);
|
||||
|
@ -301,12 +321,14 @@ void main() {
|
|||
vmService.expectMessages(<String>['create test']);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
|
||||
final int bytes = await devFS.update(mainPath: 'lib/foo.txt', generator: residentCompiler);
|
||||
final int bytes = await devFS.update();
|
||||
vmService.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
'writeFile test .packages',
|
||||
'writeFile test lib/foo.txt',
|
||||
'writeFile test packages/somepkg/somefile.txt',
|
||||
]);
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
expect(bytes, 22);
|
||||
expect(bytes, 48);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
@ -349,38 +371,6 @@ void main() {
|
|||
});
|
||||
}
|
||||
|
||||
class MockResidentCompiler extends BasicMock implements ResidentCompiler {
|
||||
@override
|
||||
void accept() {}
|
||||
|
||||
@override
|
||||
void reject() {}
|
||||
|
||||
@override
|
||||
void reset() {}
|
||||
|
||||
@override
|
||||
Future<dynamic> shutdown() async {}
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> compileExpression(
|
||||
String expression,
|
||||
List<String> definitions,
|
||||
List<String> typeDefinitions,
|
||||
String libraryUri,
|
||||
String klass,
|
||||
bool isStatic
|
||||
) async {
|
||||
return null;
|
||||
}
|
||||
@override
|
||||
Future<CompilerOutput> recompile(String mainPath, List<String> invalidatedFiles, {String outputPath, String packagesFilePath}) async {
|
||||
fs.file(outputPath).createSync(recursive: true);
|
||||
fs.file(outputPath).writeAsStringSync('compiled_kernel_output');
|
||||
return new CompilerOutput(outputPath, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class MockVMService extends BasicMock implements VMService {
|
||||
Uri _httpAddress;
|
||||
HttpServer _server;
|
||||
|
|
|
@ -284,10 +284,14 @@ Information about project "Runner":
|
|||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
|
||||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine');
|
||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, targetPlatform: TargetPlatform.ios);
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||
previewDart2: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: 'path/to/project',
|
||||
buildInfo: buildInfo,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
|
||||
|
@ -301,12 +305,14 @@ Information about project "Runner":
|
|||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine');
|
||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||
previewDart2: true,
|
||||
trackWidgetCreation: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: 'path/to/project',
|
||||
buildInfo: buildInfo,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
|
||||
|
@ -319,10 +325,14 @@ Information about project "Runner":
|
|||
testUsingOsxContext('does not set TRACK_WIDGET_CREATION when trackWidgetCreation is false', () async {
|
||||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine');
|
||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, targetPlatform: TargetPlatform.ios);
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||
previewDart2: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: 'path/to/project',
|
||||
buildInfo: buildInfo,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
|
||||
|
@ -335,10 +345,14 @@ Information about project "Runner":
|
|||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
|
||||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, typed(any))).thenReturn('engine');
|
||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile'));
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null, targetPlatform: TargetPlatform.ios);
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||
previewDart2: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: 'path/to/project',
|
||||
buildInfo: buildInfo,
|
||||
previewDart2: true,
|
||||
);
|
||||
|
||||
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
|
||||
|
@ -391,6 +405,7 @@ Information about project "Runner":
|
|||
projectPath: projectPath,
|
||||
buildInfo: buildInfo,
|
||||
targetOverride: bundle.defaultMainPath,
|
||||
previewDart2: false,
|
||||
);
|
||||
|
||||
final String propertiesPath = fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig');
|
||||
|
|
|
@ -44,11 +44,14 @@ class TestRunner extends ResidentRunner {
|
|||
|
||||
void main() {
|
||||
TestRunner createTestRunner() {
|
||||
// TODO(jacobr): make these tests run with `trackWidgetCreation: true` as
|
||||
// well as the default flags.
|
||||
// TODO(jacobr): make these tests run with `previewDart2: true` and
|
||||
// `trackWidgetCreation: true` as well as the default flags.
|
||||
// Currently the TestRunner is not properly configured to be able to run
|
||||
// with `previewDart2: true` due to missing resources.
|
||||
return new TestRunner(
|
||||
<FlutterDevice>[new FlutterDevice(
|
||||
new MockDevice(),
|
||||
previewDart2: false,
|
||||
trackWidgetCreation: false,
|
||||
)],
|
||||
);
|
||||
|
|
|
@ -6,14 +6,11 @@ import 'dart:async';
|
|||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/device.dart';
|
||||
import 'package:flutter_tools/src/tester/flutter_tester.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
@ -100,8 +97,6 @@ void main() {
|
|||
String projectPath;
|
||||
String mainPath;
|
||||
|
||||
MockArtifacts mockArtifacts;
|
||||
MockKernelCompiler mockKernelCompiler;
|
||||
MockProcessManager mockProcessManager;
|
||||
MockProcess mockProcess;
|
||||
|
||||
|
@ -110,8 +105,6 @@ void main() {
|
|||
FileSystem: () => fs,
|
||||
Cache: () => new Cache(rootOverride: fs.directory(flutterRoot)),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
KernelCompiler: () => mockKernelCompiler,
|
||||
Artifacts: () => mockArtifacts,
|
||||
};
|
||||
|
||||
setUp(() {
|
||||
|
@ -129,13 +122,6 @@ void main() {
|
|||
mockProcessManager = new MockProcessManager();
|
||||
mockProcessManager.processFactory =
|
||||
(List<String> commands) => mockProcess;
|
||||
|
||||
mockArtifacts = new MockArtifacts();
|
||||
final String artifactPath = fs.path.join(flutterRoot, 'artifact');
|
||||
fs.file(artifactPath).createSync(recursive: true);
|
||||
when(mockArtifacts.getArtifactPath(any)).thenReturn(artifactPath);
|
||||
|
||||
mockKernelCompiler = new MockKernelCompiler();
|
||||
});
|
||||
|
||||
testUsingContext('not debug', () async {
|
||||
|
@ -167,22 +153,6 @@ Hello!
|
|||
.codeUnits
|
||||
]));
|
||||
|
||||
when(mockKernelCompiler.compile(
|
||||
sdkRoot: any,
|
||||
incrementalCompilerByteStorePath: any,
|
||||
mainPath: any,
|
||||
outputFilePath: any,
|
||||
depFilePath: any,
|
||||
trackWidgetCreation: any,
|
||||
extraFrontEndOptions: any,
|
||||
fileSystemRoots: any,
|
||||
fileSystemScheme: any,
|
||||
packagesPath: any,
|
||||
)).thenAnswer((_) async {
|
||||
fs.file('$mainPath.dill').createSync(recursive: true);
|
||||
return new CompilerOutput('$mainPath.dill', 0);
|
||||
});
|
||||
|
||||
final LaunchResult result = await device.startApp(null,
|
||||
mainPath: mainPath,
|
||||
debuggingOptions: new DebuggingOptions.enabled(
|
||||
|
@ -195,6 +165,3 @@ Hello!
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
class MockArtifacts extends Mock implements Artifacts {}
|
||||
class MockKernelCompiler extends Mock implements KernelCompiler {}
|
||||
|
|
Loading…
Reference in a new issue