[flutter_tools] add flag for sound-null-safety, unify with experiments (#58533)
Also combines experiments into extraGenSnapshot/ExtraFrontEndOptions. Allows providing --no-sound-null-safety to allow out of order migration and running.
This commit is contained in:
parent
95edf28150
commit
b1d75fc99d
@ -340,8 +340,7 @@ Future<void> _runToolTests() async {
|
||||
/// target app.
|
||||
Future<void> _runBuildTests() async {
|
||||
final List<FileSystemEntity> exampleDirectories = Directory(path.join(flutterRoot, 'examples')).listSync()
|
||||
// TODO(jonahwilliams): re-enable once https://github.com/flutter/flutter/issues/57234 is done.
|
||||
// ..add(Directory(path.join(flutterRoot, 'dev', 'integration_tests', 'non_nullable')))
|
||||
..add(Directory(path.join(flutterRoot, 'dev', 'integration_tests', 'non_nullable')))
|
||||
..add(Directory(path.join(flutterRoot, 'dev', 'integration_tests', 'flutter_gallery')));
|
||||
|
||||
final String branch = Platform.environment['CIRRUS_BRANCH'];
|
||||
@ -377,7 +376,7 @@ Future<void> _runExampleProjectBuildTests(FileSystemEntity exampleDirectory) asy
|
||||
final String examplePath = exampleDirectory.path;
|
||||
final bool hasNullSafety = File(path.join(examplePath, 'null_safety')).existsSync();
|
||||
final List<String> additionalArgs = hasNullSafety
|
||||
? <String>['--enable-experiment', 'non-nullable']
|
||||
? <String>['--enable-experiment', 'non-nullable', '--no-sound-null-safety']
|
||||
: <String>[];
|
||||
if (Directory(path.join(examplePath, 'android')).existsSync()) {
|
||||
await _flutterBuildApk(examplePath, release: false, additionalArgs: additionalArgs, verifyCaching: verifyCaching);
|
||||
@ -603,10 +602,9 @@ Future<void> _runFrameworkTests() async {
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'fuchsia_remote_debug_protocol'), tableData: bigqueryApi?.tabledata);
|
||||
// TODO(jonahwilliams): re-enable once https://github.com/flutter/flutter/issues/57234 is done.
|
||||
// await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'non_nullable'),
|
||||
// options: <String>['--enable-experiment=non-nullable'],
|
||||
// );
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'non_nullable'),
|
||||
options: <String>['--enable-experiment=non-nullable', '--no-sound-null-safety'],
|
||||
);
|
||||
await _runFlutterTest(
|
||||
path.join(flutterRoot, 'dev', 'tracing_tests'),
|
||||
options: <String>['--enable-vmservice'],
|
||||
@ -756,8 +754,7 @@ Future<void> _runWebIntegrationTests() async {
|
||||
await _runWebDebugTest('lib/stack_trace.dart');
|
||||
await _runWebDebugTest('lib/web_directory_loading.dart');
|
||||
await _runWebDebugTest('test/test.dart');
|
||||
// TODO(jonahwilliams): re-enable once https://github.com/flutter/flutter/issues/57234 is done.
|
||||
// await _runWebDebugTest('lib/null_safe_main.dart', enableNullSafety: true);
|
||||
await _runWebDebugTest('lib/null_safe_main.dart', enableNullSafety: true);
|
||||
await _runWebDebugTest('lib/web_define_loading.dart',
|
||||
additionalArguments: <String>[
|
||||
'--dart-define=test.valueA=Example',
|
||||
@ -875,6 +872,7 @@ Future<void> _runWebDebugTest(String target, {
|
||||
...<String>[
|
||||
'--enable-experiment',
|
||||
'non-nullable',
|
||||
'--no-sound-null-safety'
|
||||
],
|
||||
'-d',
|
||||
'chrome',
|
||||
|
@ -155,7 +155,7 @@ Future<void> run(List<String> args) async {
|
||||
concurrency: math.max(1, globals.platform.numberOfProcessors - 2),
|
||||
icudtlPath: globals.fs.path.absolute(argResults[_kOptionIcudtl] as String),
|
||||
coverageDirectory: coverageDirectory,
|
||||
dartExperiments: <String>[],
|
||||
extraFrontEndOptions: <String>[],
|
||||
);
|
||||
|
||||
if (collector != null) {
|
||||
|
@ -82,7 +82,7 @@ RunCommand "${FLUTTER_ROOT}/bin/flutter" \
|
||||
-dTrackWidgetCreation="${TRACK_WIDGET_CREATION}" \
|
||||
--DartDefines="${DART_DEFINES}" \
|
||||
--ExtraGenSnapshotOptions="${EXTRA_GEN_SNAPSHOT_OPTIONS}" \
|
||||
-dExtraFrontEndOptions="${EXTRA_FRONT_END_OPTIONS}" \
|
||||
--ExtraFrontEndOptions="${EXTRA_FRONT_END_OPTIONS}" \
|
||||
--build-inputs="${build_inputs_path}" \
|
||||
--build-outputs="${build_outputs_path}" \
|
||||
--output="${ephemeral_dir}" \
|
||||
|
@ -69,7 +69,7 @@ or
|
||||
if (extraGenSnapshotOptions != null)
|
||||
'--ExtraGenSnapshotOptions=$extraGenSnapshotOptions',
|
||||
if (extraFrontEndOptions != null)
|
||||
'-dExtraFrontEndOptions=$extraFrontEndOptions',
|
||||
'--ExtraFrontEndOptions=$extraFrontEndOptions',
|
||||
target,
|
||||
],
|
||||
);
|
||||
|
@ -168,7 +168,7 @@ is set to release or run \"flutter build ios --release\", then re-run Archive fr
|
||||
-dEnableBitcode="${bitcode_flag}" \
|
||||
--ExtraGenSnapshotOptions="${EXTRA_GEN_SNAPSHOT_OPTIONS}" \
|
||||
--DartDefines="${DART_DEFINES}" \
|
||||
-dExtraFrontEndOptions="${EXTRA_FRONT_END_OPTIONS}" \
|
||||
--ExtraFrontEndOptions="${EXTRA_FRONT_END_OPTIONS}" \
|
||||
"${build_mode}_ios_bundle_flutter_assets"
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
|
@ -919,9 +919,6 @@ abstract class BaseFlutterTask extends DefaultTask {
|
||||
}
|
||||
args "-dTargetPlatform=android"
|
||||
args "-dBuildMode=${buildMode}"
|
||||
if (extraFrontEndOptions != null) {
|
||||
args "-dExtraFrontEndOptions=${extraFrontEndOptions}"
|
||||
}
|
||||
if (trackWidgetCreation != null) {
|
||||
args "-dTrackWidgetCreation=${trackWidgetCreation}"
|
||||
}
|
||||
@ -943,6 +940,9 @@ abstract class BaseFlutterTask extends DefaultTask {
|
||||
if (extraGenSnapshotOptions != null) {
|
||||
args "--ExtraGenSnapshotOptions=${extraGenSnapshotOptions}"
|
||||
}
|
||||
if (extraFrontEndOptions != null) {
|
||||
args "--ExtraFrontEndOptions=${extraFrontEndOptions}"
|
||||
}
|
||||
args ruleNames
|
||||
}
|
||||
}
|
||||
|
@ -310,10 +310,10 @@ Future<void> buildGradleApp({
|
||||
command.add('-Ptrack-widget-creation=${buildInfo.trackWidgetCreation}');
|
||||
|
||||
if (buildInfo.extraFrontEndOptions != null) {
|
||||
command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions.join(',')}');
|
||||
command.add('-Pextra-front-end-options=${encodeDartDefines(buildInfo.extraFrontEndOptions)}');
|
||||
}
|
||||
if (buildInfo.extraGenSnapshotOptions != null) {
|
||||
command.add('-Pextra-gen-snapshot-options=${buildInfo.extraGenSnapshotOptions.join(',')}');
|
||||
command.add('-Pextra-gen-snapshot-options=${encodeDartDefines(buildInfo.extraGenSnapshotOptions)}');
|
||||
}
|
||||
if (buildInfo.fileSystemRoots != null && buildInfo.fileSystemRoots.isNotEmpty) {
|
||||
command.add('-Pfilesystem-roots=${buildInfo.fileSystemRoots.join('|')}');
|
||||
|
@ -143,9 +143,9 @@ class BuildInfo {
|
||||
if (dartObfuscation != null)
|
||||
'DART_OBFUSCATION': dartObfuscation.toString(),
|
||||
if (extraFrontEndOptions?.isNotEmpty ?? false)
|
||||
'EXTRA_FRONT_END_OPTIONS': extraFrontEndOptions.join(','),
|
||||
'EXTRA_FRONT_END_OPTIONS': encodeDartDefines(extraFrontEndOptions),
|
||||
if (extraGenSnapshotOptions?.isNotEmpty ?? false)
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS': extraGenSnapshotOptions.join(','),
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS': encodeDartDefines(extraGenSnapshotOptions),
|
||||
if (splitDebugInfoPath != null)
|
||||
'SPLIT_DEBUG_INFO': splitDebugInfoPath,
|
||||
if (trackWidgetCreation != null)
|
||||
@ -667,11 +667,11 @@ String encodeDartDefines(List<String> defines) {
|
||||
}
|
||||
|
||||
/// Dart defines are encoded inside [environmentDefines] as a comma-separated list.
|
||||
List<String> decodeDartDefines(Map<String, String> environmentDefines) {
|
||||
if (!environmentDefines.containsKey(kDartDefines) || environmentDefines[kDartDefines].isEmpty) {
|
||||
List<String> decodeDartDefines(Map<String, String> environmentDefines, String key) {
|
||||
if (!environmentDefines.containsKey(key) || environmentDefines[key].isEmpty) {
|
||||
return const <String>[];
|
||||
}
|
||||
return environmentDefines[kDartDefines]
|
||||
return environmentDefines[key]
|
||||
.split(',')
|
||||
.map<Object>(Uri.decodeComponent)
|
||||
.cast<String>()
|
||||
|
@ -441,7 +441,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
debuggingOptions.buildInfo,
|
||||
debuggingOptions.initializePlatform,
|
||||
false,
|
||||
debuggingOptions.buildInfo.dartExperiments,
|
||||
);
|
||||
}
|
||||
await device.device.startApp(
|
||||
@ -504,7 +503,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
debuggingOptions.buildInfo,
|
||||
debuggingOptions.initializePlatform,
|
||||
false,
|
||||
debuggingOptions.buildInfo.dartExperiments,
|
||||
);
|
||||
} on ToolExit {
|
||||
return OperationResult(1, 'Failed to recompile application.');
|
||||
|
@ -246,8 +246,7 @@ class AndroidAot extends AotElfBase {
|
||||
if (!output.existsSync()) {
|
||||
output.createSync(recursive: true);
|
||||
}
|
||||
final List<String> extraGenSnapshotOptions = environment.defines[kExtraGenSnapshotOptions]?.split(',')
|
||||
?? const <String>[];
|
||||
final List<String> extraGenSnapshotOptions = decodeDartDefines(environment.defines, kExtraGenSnapshotOptions);
|
||||
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
||||
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
|
||||
final int snapshotExitCode = await snapshotter.build(
|
||||
|
@ -205,10 +205,7 @@ class KernelSnapshot extends Target {
|
||||
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
|
||||
|
||||
// This configuration is all optional.
|
||||
final String rawFrontEndOption = environment.defines[kExtraFrontEndOptions];
|
||||
final List<String> extraFrontEndOptions = (rawFrontEndOption?.isNotEmpty ?? false)
|
||||
? rawFrontEndOption?.split(',')
|
||||
: null;
|
||||
final List<String> extraFrontEndOptions = decodeDartDefines(environment.defines, kExtraFrontEndOptions);
|
||||
final List<String> fileSystemRoots = environment.defines[kFileSystemRoots]?.split(',');
|
||||
final String fileSystemScheme = environment.defines[kFileSystemScheme];
|
||||
|
||||
@ -254,7 +251,7 @@ class KernelSnapshot extends Target {
|
||||
extraFrontEndOptions: extraFrontEndOptions,
|
||||
fileSystemRoots: fileSystemRoots,
|
||||
fileSystemScheme: fileSystemScheme,
|
||||
dartDefines: decodeDartDefines(environment.defines),
|
||||
dartDefines: decodeDartDefines(environment.defines, kDartDefines),
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
if (output == null || output.errorCount != 0) {
|
||||
@ -287,8 +284,7 @@ abstract class AotElfBase extends Target {
|
||||
if (environment.defines[kTargetPlatform] == null) {
|
||||
throw MissingDefineException(kTargetPlatform, 'aot_elf');
|
||||
}
|
||||
final List<String> extraGenSnapshotOptions = environment.defines[kExtraGenSnapshotOptions]?.split(',')
|
||||
?? const <String>[];
|
||||
final List<String> extraGenSnapshotOptions = decodeDartDefines(environment.defines, kExtraGenSnapshotOptions);
|
||||
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
||||
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
|
||||
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
|
||||
|
@ -46,7 +46,7 @@ abstract class AotAssemblyBase extends Target {
|
||||
if (environment.defines[kTargetPlatform] == null) {
|
||||
throw MissingDefineException(kTargetPlatform, 'aot_assembly');
|
||||
}
|
||||
final List<String> extraGenSnapshotOptions = parseExtraGenSnapshotOptions(environment);
|
||||
final List<String> extraGenSnapshotOptions = decodeDartDefines(environment.defines, kExtraGenSnapshotOptions);
|
||||
final bool bitcode = environment.defines[kBitcodeFlag] == 'true';
|
||||
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
||||
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
|
||||
@ -447,13 +447,3 @@ Future<RunResult> createStubAppFramework(File outputFile, SdkType sdk, { bool in
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// iOS and macOS build scripts may pass extraGenSnapshotOptions as an empty
|
||||
/// string.
|
||||
List<String> parseExtraGenSnapshotOptions(Environment environment) {
|
||||
final String value = environment.defines[kExtraGenSnapshotOptions];
|
||||
if (value == null || value.trim().isEmpty) {
|
||||
return <String>[];
|
||||
}
|
||||
return value.split(',');
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import '../exceptions.dart';
|
||||
import 'assets.dart';
|
||||
import 'dart.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'ios.dart';
|
||||
|
||||
/// Copy the macOS framework to the correct copy dir by invoking 'cp -R'.
|
||||
///
|
||||
@ -198,7 +197,7 @@ class CompileMacOSFramework extends Target {
|
||||
}
|
||||
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
|
||||
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
|
||||
final List<String> extraGenSnapshotOptions = parseExtraGenSnapshotOptions(environment);
|
||||
final List<String> extraGenSnapshotOptions = decodeDartDefines(environment.defines, kExtraGenSnapshotOptions);
|
||||
final AOTSnapshotter snapshotter = AOTSnapshotter(
|
||||
reportTimings: false,
|
||||
fileSystem: globals.fs,
|
||||
|
@ -28,11 +28,6 @@ const String kHasWebPlugins = 'HasWebPlugins';
|
||||
/// Valid values are O1 (lowest, profile default) to O4 (highest, release default).
|
||||
const String kDart2jsOptimization = 'Dart2jsOptimization';
|
||||
|
||||
/// Allow specifying experiments for dart2js.
|
||||
///
|
||||
/// Multiple values should be encoded as a comma-separated list.
|
||||
const String kEnableExperiment = 'EnableExperiment';
|
||||
|
||||
/// Whether to disable dynamic generation code to satisfy csp policies.
|
||||
const String kCspMode = 'cspMode';
|
||||
|
||||
@ -164,8 +159,8 @@ class Dart2JSTarget extends Target {
|
||||
final String packageFile = globalPackagesPath;
|
||||
final File outputKernel = environment.buildDir.childFile('app.dill');
|
||||
final File outputFile = environment.buildDir.childFile('main.dart.js');
|
||||
final List<String> dartDefines = decodeDartDefines(environment.defines);
|
||||
final String enabledExperiments = environment.defines[kEnableExperiment];
|
||||
final List<String> dartDefines = decodeDartDefines(environment.defines, kDartDefines);
|
||||
final List<String> extraFrontEndOptions = decodeDartDefines(environment.defines, kExtraFrontEndOptions);
|
||||
|
||||
// Run the dart2js compilation in two stages, so that icon tree shaking can
|
||||
// parse the kernel file for web builds.
|
||||
@ -173,8 +168,7 @@ class Dart2JSTarget extends Target {
|
||||
globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
|
||||
globals.artifacts.getArtifactPath(Artifact.dart2jsSnapshot),
|
||||
'--libraries-spec=$specPath',
|
||||
if (enabledExperiments != null)
|
||||
'--enable-experiment=$enabledExperiments',
|
||||
...?extraFrontEndOptions,
|
||||
'-o',
|
||||
outputKernel.path,
|
||||
'--packages=$packageFile',
|
||||
@ -194,8 +188,7 @@ class Dart2JSTarget extends Target {
|
||||
globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
|
||||
globals.artifacts.getArtifactPath(Artifact.dart2jsSnapshot),
|
||||
'--libraries-spec=$specPath',
|
||||
if (enabledExperiments != null)
|
||||
'--enable-experiment=$enabledExperiments',
|
||||
...?extraFrontEndOptions,
|
||||
if (dart2jsOptimization != null)
|
||||
'-$dart2jsOptimization'
|
||||
else
|
||||
|
@ -105,6 +105,7 @@ class AssembleCommand extends FlutterCommand {
|
||||
'root of the current Flutter project.',
|
||||
);
|
||||
argParser.addOption(kExtraGenSnapshotOptions);
|
||||
argParser.addOption(kExtraFrontEndOptions);
|
||||
argParser.addOption(kDartDefines);
|
||||
argParser.addOption(
|
||||
'resource-pool-size',
|
||||
@ -204,10 +205,12 @@ class AssembleCommand extends FlutterCommand {
|
||||
if (argResults.wasParsed(kExtraGenSnapshotOptions)) {
|
||||
results[kExtraGenSnapshotOptions] = argResults[kExtraGenSnapshotOptions] as String;
|
||||
}
|
||||
// Workaround for dart-define formatting
|
||||
if (argResults.wasParsed(kDartDefines)) {
|
||||
results[kDartDefines] = argResults[kDartDefines] as String;
|
||||
}
|
||||
if (argResults.wasParsed(kExtraFrontEndOptions)) {
|
||||
results[kExtraFrontEndOptions] = argResults[kExtraFrontEndOptions] as String;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ class BuildAarCommand extends BuildSubCommand {
|
||||
addSplitDebugInfoOption();
|
||||
addDartObfuscationOption();
|
||||
usesTrackWidgetCreation(verboseHelp: false);
|
||||
addNullSafetyModeOptions();
|
||||
argParser
|
||||
..addMultiOption(
|
||||
'target-platform',
|
||||
|
@ -33,6 +33,7 @@ class BuildApkCommand extends BuildSubCommand {
|
||||
addBundleSkSLPathOption(hide: !verboseHelp);
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
addBuildPerformanceFile(hide: !verboseHelp);
|
||||
addNullSafetyModeOptions();
|
||||
argParser
|
||||
..addFlag('split-per-abi',
|
||||
negatable: false,
|
||||
|
@ -21,6 +21,7 @@ class BuildFuchsiaCommand extends BuildSubCommand {
|
||||
usesTargetOption();
|
||||
usesDartDefineOption();
|
||||
addBuildModeFlags(verboseHelp: verboseHelp);
|
||||
addNullSafetyModeOptions();
|
||||
argParser.addOption(
|
||||
'runner-source',
|
||||
help: 'The package source to use for the flutter_runner. '
|
||||
|
@ -33,6 +33,7 @@ class BuildIOSCommand extends BuildSubCommand {
|
||||
usesExtraFrontendOptions();
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
addBuildPerformanceFile(hide: !verboseHelp);
|
||||
addNullSafetyModeOptions();
|
||||
argParser
|
||||
..addFlag('simulator',
|
||||
help: 'Build for the iOS simulator instead of the device. This changes '
|
||||
|
@ -28,6 +28,7 @@ class BuildLinuxCommand extends BuildSubCommand {
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
addBuildPerformanceFile(hide: !verboseHelp);
|
||||
addNullSafetyModeOptions();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -29,6 +29,7 @@ class BuildMacosCommand extends BuildSubCommand {
|
||||
usesBuildNameOption();
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
addBuildPerformanceFile(hide: !verboseHelp);
|
||||
addNullSafetyModeOptions();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -11,7 +11,7 @@ import '../build_info.dart';
|
||||
import '../features.dart';
|
||||
import '../project.dart';
|
||||
import '../runner/flutter_command.dart'
|
||||
show DevelopmentArtifact, FlutterCommandResult, FlutterOptions;
|
||||
show DevelopmentArtifact, FlutterCommandResult;
|
||||
import '../web/compile.dart';
|
||||
import 'build.dart';
|
||||
|
||||
@ -25,6 +25,7 @@ class BuildWebCommand extends BuildSubCommand {
|
||||
addBuildModeFlags(excludeDebug: true);
|
||||
usesDartDefineOption();
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
addNullSafetyModeOptions();
|
||||
argParser.addFlag('web-initialize-platform',
|
||||
defaultsTo: true,
|
||||
negatable: true,
|
||||
@ -71,7 +72,6 @@ class BuildWebCommand extends BuildSubCommand {
|
||||
buildInfo,
|
||||
boolArg('web-initialize-platform'),
|
||||
boolArg('csp'),
|
||||
stringsArg(FlutterOptions.kEnableExperiment),
|
||||
);
|
||||
return FlutterCommandResult.success();
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
usesPubOption();
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
usesIsolateFilterOption(hide: !verboseHelp);
|
||||
addNullSafetyModeOptions();
|
||||
}
|
||||
|
||||
bool get traceStartup => boolArg('trace-startup');
|
||||
|
@ -31,6 +31,9 @@ class TestCommand extends FlutterCommand {
|
||||
}) : assert(testWrapper != null) {
|
||||
requiresPubspecYaml();
|
||||
usesPubOption();
|
||||
addNullSafetyModeOptions();
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
argParser
|
||||
..addMultiOption('name',
|
||||
help: 'A regular expression matching substrings of the names of tests to run.',
|
||||
@ -128,8 +131,6 @@ class TestCommand extends FlutterCommand {
|
||||
'This flag is ignored if --start-paused or coverage are requested. '
|
||||
'The vmservice will be enabled no matter what in those cases.'
|
||||
);
|
||||
usesTrackWidgetCreation(verboseHelp: verboseHelp);
|
||||
addEnableExperimentation(hide: !verboseHelp);
|
||||
}
|
||||
|
||||
/// The interface for starting and configuring the tester.
|
||||
@ -172,7 +173,6 @@ class TestCommand extends FlutterCommand {
|
||||
final String tags = stringArg('tags');
|
||||
final String excludeTags = stringArg('exclude-tags');
|
||||
final FlutterProject flutterProject = FlutterProject.current();
|
||||
final List<String> dartExperiments = stringsArg(FlutterOptions.kEnableExperiment);
|
||||
|
||||
if (buildTestAssets && flutterProject.manifest.assets.isNotEmpty) {
|
||||
await _buildTestAsset();
|
||||
@ -278,7 +278,7 @@ class TestCommand extends FlutterCommand {
|
||||
flutterProject: flutterProject,
|
||||
web: stringArg('platform') == 'chrome',
|
||||
randomSeed: stringArg('test-randomize-ordering-seed'),
|
||||
dartExperiments: dartExperiments,
|
||||
extraFrontEndOptions: getBuildInfo(forcedBuildMode: BuildMode.debug).extraFrontEndOptions,
|
||||
);
|
||||
|
||||
if (collector != null) {
|
||||
|
@ -269,7 +269,14 @@ class KernelCompiler {
|
||||
'--platform',
|
||||
platformDill,
|
||||
],
|
||||
...?extraFrontEndOptions,
|
||||
if (extraFrontEndOptions != null)
|
||||
for (String arg in extraFrontEndOptions)
|
||||
if (arg == '--sound-null-safety')
|
||||
'--null-safety'
|
||||
else if (arg == '--no-sound-null-safety')
|
||||
'--no-null-safety'
|
||||
else
|
||||
arg,
|
||||
mainUri?.toString() ?? mainPath,
|
||||
];
|
||||
|
||||
@ -398,7 +405,7 @@ abstract class ResidentCompiler {
|
||||
String initializeFromDill,
|
||||
TargetModel targetModel,
|
||||
bool unsafePackageSerialization,
|
||||
List<String> experimentalFlags,
|
||||
List<String> extraFrontEndOptions,
|
||||
String platformDill,
|
||||
List<String> dartDefines,
|
||||
String librariesSpec,
|
||||
@ -494,7 +501,7 @@ class DefaultResidentCompiler implements ResidentCompiler {
|
||||
this.initializeFromDill,
|
||||
this.targetModel = TargetModel.flutter,
|
||||
this.unsafePackageSerialization,
|
||||
this.experimentalFlags,
|
||||
this.extraFrontEndOptions,
|
||||
this.platformDill,
|
||||
List<String> dartDefines,
|
||||
this.librariesSpec,
|
||||
@ -512,7 +519,7 @@ class DefaultResidentCompiler implements ResidentCompiler {
|
||||
final String fileSystemScheme;
|
||||
final String initializeFromDill;
|
||||
final bool unsafePackageSerialization;
|
||||
final List<String> experimentalFlags;
|
||||
final List<String> extraFrontEndOptions;
|
||||
final List<String> dartDefines;
|
||||
final String librariesSpec;
|
||||
|
||||
@ -660,8 +667,14 @@ class DefaultResidentCompiler implements ResidentCompiler {
|
||||
platformDill,
|
||||
],
|
||||
if (unsafePackageSerialization == true) '--unsafe-package-serialization',
|
||||
if ((experimentalFlags != null) && experimentalFlags.isNotEmpty)
|
||||
'--enable-experiment=${experimentalFlags.join(',')}',
|
||||
if (extraFrontEndOptions != null)
|
||||
for (String arg in extraFrontEndOptions)
|
||||
if (arg == '--sound-null-safety')
|
||||
'--null-safety'
|
||||
else if (arg == '--no-sound-null-safety')
|
||||
'--no-null-safety'
|
||||
else
|
||||
arg,
|
||||
];
|
||||
globals.printTrace(command.join(' '));
|
||||
_server = await globals.processManager.start(command);
|
||||
|
@ -47,7 +47,6 @@ class FlutterDevice {
|
||||
this.viewFilter,
|
||||
TargetModel targetModel = TargetModel.flutter,
|
||||
TargetPlatform targetPlatform,
|
||||
List<String> experimentalFlags,
|
||||
ResidentCompiler generator,
|
||||
}) : assert(buildInfo.trackWidgetCreation != null),
|
||||
generator = generator ?? ResidentCompiler(
|
||||
@ -61,9 +60,9 @@ class FlutterDevice {
|
||||
fileSystemRoots: fileSystemRoots ?? <String>[],
|
||||
fileSystemScheme: fileSystemScheme,
|
||||
targetModel: targetModel,
|
||||
experimentalFlags: experimentalFlags,
|
||||
dartDefines: buildInfo.dartDefines,
|
||||
packagesPath: globalPackagesPath,
|
||||
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
|
||||
);
|
||||
|
||||
/// Create a [FlutterDevice] with optional code generation enabled.
|
||||
@ -106,7 +105,7 @@ class FlutterDevice {
|
||||
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
||||
),
|
||||
targetModel: TargetModel.dartdevc,
|
||||
experimentalFlags: experimentalFlags,
|
||||
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
|
||||
platformDill: globals.fs.file(globals.artifacts
|
||||
.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildInfo.mode))
|
||||
.absolute.uri.toString(),
|
||||
@ -127,8 +126,8 @@ class FlutterDevice {
|
||||
fileSystemRoots: fileSystemRoots,
|
||||
fileSystemScheme: fileSystemScheme,
|
||||
targetModel: targetModel,
|
||||
experimentalFlags: experimentalFlags,
|
||||
dartDefines: buildInfo.dartDefines,
|
||||
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
|
||||
initializeFromDill: getDefaultCachedKernelPath(
|
||||
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
||||
),
|
||||
@ -148,7 +147,6 @@ class FlutterDevice {
|
||||
fileSystemRoots: fileSystemRoots,
|
||||
fileSystemScheme:fileSystemScheme,
|
||||
viewFilter: viewFilter,
|
||||
experimentalFlags: experimentalFlags,
|
||||
targetModel: targetModel,
|
||||
targetPlatform: targetPlatform,
|
||||
generator: generator,
|
||||
|
@ -109,6 +109,7 @@ class FlutterOptions {
|
||||
static const String kDartDefinesOption = 'dart-define';
|
||||
static const String kBundleSkSLPathOption = 'bundle-sksl-path';
|
||||
static const String kPerformanceMeasurementFile = 'performance-measurement-file';
|
||||
static const String kNullSafety = 'sound-null-safety';
|
||||
}
|
||||
|
||||
abstract class FlutterCommand extends Command<void> {
|
||||
@ -460,6 +461,14 @@ abstract class FlutterCommand extends Command<void> {
|
||||
);
|
||||
}
|
||||
|
||||
void addNullSafetyModeOptions() {
|
||||
argParser.addFlag(FlutterOptions.kNullSafety,
|
||||
help: 'Whether to override the default null safety setting.',
|
||||
defaultsTo: null,
|
||||
hide: true,
|
||||
);
|
||||
}
|
||||
|
||||
void usesExtraFrontendOptions() {
|
||||
argParser.addMultiOption(FlutterOptions.kExtraFrontEndOptions,
|
||||
splitCommas: true,
|
||||
@ -572,15 +581,15 @@ abstract class FlutterCommand extends Command<void> {
|
||||
|
||||
final List<String> experiments =
|
||||
argParser.options.containsKey(FlutterOptions.kEnableExperiment)
|
||||
? stringsArg(FlutterOptions.kEnableExperiment)
|
||||
? stringsArg(FlutterOptions.kEnableExperiment).toList()
|
||||
: <String>[];
|
||||
final List<String> extraGenSnapshotOptions =
|
||||
argParser.options.containsKey(FlutterOptions.kExtraGenSnapshotOptions)
|
||||
? stringsArg(FlutterOptions.kExtraGenSnapshotOptions)
|
||||
? stringsArg(FlutterOptions.kExtraGenSnapshotOptions).toList()
|
||||
: <String>[];
|
||||
final List<String> extraFrontEndOptions =
|
||||
argParser.options.containsKey(FlutterOptions.kExtraFrontEndOptions)
|
||||
? stringsArg(FlutterOptions.kExtraFrontEndOptions)
|
||||
? stringsArg(FlutterOptions.kExtraFrontEndOptions).toList()
|
||||
: <String>[];
|
||||
|
||||
if (experiments.isNotEmpty) {
|
||||
@ -591,6 +600,18 @@ abstract class FlutterCommand extends Command<void> {
|
||||
}
|
||||
}
|
||||
|
||||
if (argParser.options.containsKey(FlutterOptions.kNullSafety)) {
|
||||
final bool nullSafety = boolArg(FlutterOptions.kNullSafety);
|
||||
// Explicitly check for `true` and `false` so that `null` results in not
|
||||
// passing a flag. This will use the automatically detected null-safety
|
||||
// value based on the entrypoint
|
||||
if (nullSafety == true) {
|
||||
extraFrontEndOptions.add('--sound-null-safety');
|
||||
} else if (nullSafety == false) {
|
||||
extraFrontEndOptions.add('--no-sound-null-safety');
|
||||
}
|
||||
}
|
||||
|
||||
final bool dartObfuscation = argParser.options.containsKey(FlutterOptions.kDartObfuscationOption)
|
||||
&& boolArg(FlutterOptions.kDartObfuscationOption);
|
||||
|
||||
|
@ -88,7 +88,7 @@ FlutterPlatform installHook({
|
||||
FlutterProject flutterProject,
|
||||
String icudtlPath,
|
||||
PlatformPluginRegistration platformPluginRegistration,
|
||||
@required List<String> dartExperiments,
|
||||
@required List<String> extraFrontEndOptions,
|
||||
}) {
|
||||
assert(testWrapper != null);
|
||||
assert(enableObservatory || (!startPaused && observatoryPort == null));
|
||||
@ -121,7 +121,7 @@ FlutterPlatform installHook({
|
||||
projectRootDirectory: projectRootDirectory,
|
||||
flutterProject: flutterProject,
|
||||
icudtlPath: icudtlPath,
|
||||
dartExperiments: dartExperiments,
|
||||
extraFrontEndOptions: extraFrontEndOptions,
|
||||
);
|
||||
platformPluginRegistration(platform);
|
||||
return platform;
|
||||
@ -269,7 +269,7 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
this.projectRootDirectory,
|
||||
this.flutterProject,
|
||||
this.icudtlPath,
|
||||
@required this.dartExperiments,
|
||||
@required this.extraFrontEndOptions,
|
||||
}) : assert(shellPath != null);
|
||||
|
||||
final String shellPath;
|
||||
@ -290,7 +290,7 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
final Uri projectRootDirectory;
|
||||
final FlutterProject flutterProject;
|
||||
final String icudtlPath;
|
||||
final List<String> dartExperiments;
|
||||
final List<String> extraFrontEndOptions;
|
||||
|
||||
Directory fontsDirectory;
|
||||
|
||||
@ -459,7 +459,7 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
|
||||
if (precompiledDillPath == null && precompiledDillFiles == null) {
|
||||
// Lazily instantiate compiler so it is built only if it is actually used.
|
||||
compiler ??= TestCompiler(buildMode, trackWidgetCreation, flutterProject, dartExperiments);
|
||||
compiler ??= TestCompiler(buildMode, trackWidgetCreation, flutterProject, extraFrontEndOptions);
|
||||
mainDart = await compiler.compile(globals.fs.file(mainDart).uri);
|
||||
|
||||
if (mainDart == null) {
|
||||
@ -751,7 +751,7 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
testConfigFile: findTestConfigFile(globals.fs.file(testUrl)),
|
||||
host: host,
|
||||
updateGoldens: updateGoldens,
|
||||
nullSafety: dartExperiments.contains('non-nullable'),
|
||||
nullSafety: extraFrontEndOptions?.contains('--enable-experiment=non-nullable') ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ abstract class FlutterTestRunner {
|
||||
Directory coverageDirectory,
|
||||
bool web = false,
|
||||
String randomSeed,
|
||||
@required List<String> dartExperiments,
|
||||
@required List<String> extraFrontEndOptions,
|
||||
});
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
||||
Directory coverageDirectory,
|
||||
bool web = false,
|
||||
String randomSeed,
|
||||
@required List<String> dartExperiments,
|
||||
@required List<String> extraFrontEndOptions,
|
||||
}) async {
|
||||
// Configure package:test to use the Flutter engine for child processes.
|
||||
final String shellPath = globals.artifacts.getArtifactPath(Artifact.flutterTester);
|
||||
@ -177,7 +177,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
||||
projectRootDirectory: globals.fs.currentDirectory.uri,
|
||||
flutterProject: flutterProject,
|
||||
icudtlPath: icudtlPath,
|
||||
dartExperiments: dartExperiments,
|
||||
extraFrontEndOptions: extraFrontEndOptions,
|
||||
);
|
||||
|
||||
// Make the global packages path absolute.
|
||||
|
@ -42,7 +42,7 @@ class TestCompiler {
|
||||
this.buildMode,
|
||||
this.trackWidgetCreation,
|
||||
this.flutterProject,
|
||||
this.dartExperiments,
|
||||
this.extraFrontEndOptions,
|
||||
) : testFilePath = getKernelPathForTransformerOptions(
|
||||
globals.fs.path.join(flutterProject.directory.path, getBuildDirectory(), 'testfile.dill'),
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
@ -66,7 +66,7 @@ class TestCompiler {
|
||||
final BuildMode buildMode;
|
||||
final bool trackWidgetCreation;
|
||||
final String testFilePath;
|
||||
final List<String> dartExperiments;
|
||||
final List<String> extraFrontEndOptions;
|
||||
|
||||
|
||||
ResidentCompiler compiler;
|
||||
@ -106,7 +106,7 @@ class TestCompiler {
|
||||
unsafePackageSerialization: false,
|
||||
dartDefines: const <String>[],
|
||||
packagesPath: globalPackagesPath,
|
||||
experimentalFlags: dartExperiments,
|
||||
extraFrontEndOptions: extraFrontEndOptions,
|
||||
);
|
||||
if (flutterProject.hasBuilders) {
|
||||
return CodeGeneratingResidentCompiler.create(
|
||||
|
@ -28,7 +28,6 @@ Future<void> buildWeb(
|
||||
BuildInfo buildInfo,
|
||||
bool initializePlatform,
|
||||
bool csp,
|
||||
List<String> experiments,
|
||||
) async {
|
||||
if (!flutterProject.web.existsSync()) {
|
||||
throwToolExit('Missing index.html.');
|
||||
@ -53,8 +52,8 @@ Future<void> buildWeb(
|
||||
kDartDefines: encodeDartDefines(buildInfo.dartDefines),
|
||||
kCspMode: csp.toString(),
|
||||
kIconTreeShakerFlag: buildInfo.treeShakeIcons.toString(),
|
||||
if (experiments.isNotEmpty)
|
||||
kEnableExperiment: experiments?.join(','),
|
||||
if (buildInfo.extraFrontEndOptions?.isNotEmpty ?? false)
|
||||
kExtraFrontEndOptions: buildInfo.extraFrontEndOptions.join(',')
|
||||
},
|
||||
artifacts: globals.artifacts,
|
||||
fileSystem: globals.fs,
|
||||
|
@ -356,8 +356,8 @@ void main() {
|
||||
'set(PROJECT_DIR "${fileSystem.currentDirectory.path}")',
|
||||
' "DART_DEFINES=\\"foo.bar%3D2,fizz.far%3D3\\""',
|
||||
' "DART_OBFUSCATION=\\"true\\""',
|
||||
' "EXTRA_FRONT_END_OPTIONS=\\"--enable-experiment=non-nullable\\""',
|
||||
' "EXTRA_GEN_SNAPSHOT_OPTIONS=\\"--enable-experiment=non-nullable\\""',
|
||||
' "EXTRA_FRONT_END_OPTIONS=\\"--enable-experiment%3Dnon-nullable\\""',
|
||||
' "EXTRA_GEN_SNAPSHOT_OPTIONS=\\"--enable-experiment%3Dnon-nullable\\""',
|
||||
' "SPLIT_DEBUG_INFO=\\"foo/\\""',
|
||||
' "TRACK_WIDGET_CREATION=\\"true\\""',
|
||||
' "TREE_SHAKE_ICONS=\\"true\\""',
|
||||
|
@ -56,7 +56,6 @@ void main() {
|
||||
BuildInfo.debug,
|
||||
false,
|
||||
false,
|
||||
<String>[],
|
||||
), throwsToolExit());
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => fakePlatform,
|
||||
|
@ -291,8 +291,8 @@ void main() {
|
||||
expect(props.findAllElements('FLUTTER_ROOT').first.text, flutterRoot);
|
||||
expect(props.findAllElements('TRACK_WIDGET_CREATION').first.text, 'true');
|
||||
expect(props.findAllElements('TREE_SHAKE_ICONS').first.text, 'true');
|
||||
expect(props.findAllElements('EXTRA_GEN_SNAPSHOT_OPTIONS').first.text, '--enable-experiment=non-nullable');
|
||||
expect(props.findAllElements('EXTRA_FRONT_END_OPTIONS').first.text, '--enable-experiment=non-nullable');
|
||||
expect(props.findAllElements('EXTRA_GEN_SNAPSHOT_OPTIONS').first.text, '--enable-experiment%3Dnon-nullable');
|
||||
expect(props.findAllElements('EXTRA_FRONT_END_OPTIONS').first.text, '--enable-experiment%3Dnon-nullable');
|
||||
expect(props.findAllElements('DART_DEFINES').first.text, 'foo%3Da,bar%3Db');
|
||||
expect(props.findAllElements('DART_OBFUSCATION').first.text, 'true');
|
||||
expect(props.findAllElements('SPLIT_DEBUG_INFO').first.text, r'C:\foo\');
|
||||
|
@ -184,7 +184,7 @@ class FakeFlutterTestRunner implements FlutterTestRunner {
|
||||
Directory coverageDirectory,
|
||||
bool web = false,
|
||||
String randomSeed,
|
||||
@override List<String> dartExperiments,
|
||||
@override List<String> extraFrontEndOptions,
|
||||
}) async {
|
||||
lastEnableObservatoryValue = enableObservatory;
|
||||
return exitCode;
|
||||
|
@ -113,8 +113,8 @@ void main() {
|
||||
'DART_DEFINES': 'foo%3D2,bar%3D2',
|
||||
'DART_OBFUSCATION': 'true',
|
||||
'SPLIT_DEBUG_INFO': 'foo/',
|
||||
'EXTRA_FRONT_END_OPTIONS': '--enable-experiment=non-nullable,bar',
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS': '--enable-experiment=non-nullable,fizz',
|
||||
'EXTRA_FRONT_END_OPTIONS': '--enable-experiment%3Dnon-nullable,bar',
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS': '--enable-experiment%3Dnon-nullable,fizz',
|
||||
});
|
||||
});
|
||||
|
||||
@ -129,18 +129,18 @@ void main() {
|
||||
testWithoutContext('decodeDartDefines decodes URI encoded dart defines', () {
|
||||
expect(decodeDartDefines(<String, String>{
|
||||
kDartDefines: '%22hello%22'
|
||||
}), <String>['"hello"']);
|
||||
}, kDartDefines), <String>['"hello"']);
|
||||
expect(decodeDartDefines(<String, String>{
|
||||
kDartDefines: 'https%3A%2F%2Fwww.google.com'
|
||||
}), <String>['https://www.google.com']);
|
||||
}, kDartDefines), <String>['https://www.google.com']);
|
||||
expect(decodeDartDefines(<String, String>{
|
||||
kDartDefines: '2%2C3%2C4,5'
|
||||
}), <String>['2,3,4', '5']);
|
||||
}, kDartDefines), <String>['2,3,4', '5']);
|
||||
expect(decodeDartDefines(<String, String>{
|
||||
kDartDefines: 'true,false,flase'
|
||||
}), <String>['true', 'false', 'flase']);
|
||||
}, kDartDefines), <String>['true', 'false', 'flase']);
|
||||
expect(decodeDartDefines(<String, String>{
|
||||
kDartDefines: '1232%2C456,2'
|
||||
}), <String>['1232,456', '2']);
|
||||
}, kDartDefines), <String>['1232,456', '2']);
|
||||
});
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ void main() {
|
||||
|
||||
test('Dart2JSTarget calls dart2js with expected args with enabled experiment', () => testbed.run(() async {
|
||||
environment.defines[kBuildMode] = 'profile';
|
||||
environment.defines[kEnableExperiment] = 'non-nullable';
|
||||
environment.defines[kExtraFrontEndOptions] = '--enable-experiment=non-nullable';
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: <String>[
|
||||
...kDart2jsLinuxArgs,
|
||||
|
@ -22,7 +22,7 @@ void main() {
|
||||
buildMode: BuildMode.debug,
|
||||
shellPath: '/',
|
||||
explicitObservatoryPort: 1234,
|
||||
dartExperiments: <String>[],
|
||||
extraFrontEndOptions: <String>[],
|
||||
);
|
||||
flutterPlatform.loadChannel('test1.dart', MockSuitePlatform());
|
||||
|
||||
@ -35,7 +35,7 @@ void main() {
|
||||
buildMode: BuildMode.debug,
|
||||
shellPath: '/',
|
||||
precompiledDillPath: 'example.dill',
|
||||
dartExperiments: <String>[],
|
||||
extraFrontEndOptions: <String>[],
|
||||
);
|
||||
flutterPlatform.loadChannel('test1.dart', MockSuitePlatform());
|
||||
|
||||
@ -113,7 +113,7 @@ void main() {
|
||||
shellPath: 'abc',
|
||||
enableObservatory: false,
|
||||
startPaused: true,
|
||||
dartExperiments: <String>[],
|
||||
extraFrontEndOptions: <String>[],
|
||||
), throwsAssertionError);
|
||||
|
||||
expect(() => installHook(
|
||||
@ -122,7 +122,7 @@ void main() {
|
||||
enableObservatory: false,
|
||||
startPaused: false,
|
||||
observatoryPort: 123,
|
||||
dartExperiments: <String>[],
|
||||
extraFrontEndOptions: <String>[],
|
||||
), throwsAssertionError);
|
||||
|
||||
FlutterPlatform capturedPlatform;
|
||||
@ -143,7 +143,7 @@ void main() {
|
||||
observatoryPort: 200,
|
||||
serverType: InternetAddressType.IPv6,
|
||||
icudtlPath: 'ghi',
|
||||
dartExperiments: <String>[],
|
||||
extraFrontEndOptions: <String>[],
|
||||
platformPluginRegistration: (FlutterPlatform platform) {
|
||||
capturedPlatform = platform;
|
||||
});
|
||||
@ -192,7 +192,7 @@ class TestFlutterPlatform extends FlutterPlatform {
|
||||
startPaused: false,
|
||||
enableObservatory: false,
|
||||
buildTestAssets: false,
|
||||
dartExperiments: <String>[],
|
||||
extraFrontEndOptions: <String>[],
|
||||
);
|
||||
|
||||
@override
|
||||
|
Loading…
x
Reference in New Issue
Block a user