[flutter_releases] Flutter 1.24.0-10.1.pre framework cherrypicks (#70495)
* Update engine hash to 1.24.0-10.1.pre
* [null-safety] implement null-safe autodetection for the web (#70126)
Fixes #69416
Fixes #70121
* [flutter_tools] dont use autodetect enum for web (#70189)
* Update engine hash for build fix and pub DEP bump
Co-authored-by: Jonah Williams <jonahwilliams@google.com>
diff --git a/bin/internal/engine.version b/bin/internal/engine.version
index d759ac1..501a81f 100644
--- a/bin/internal/engine.version
+++ b/bin/internal/engine.version
@@ -1 +1 @@
-40b8f8227b9a8f4ab78fa9d115cf135aaa885948
+bd390c0310ed240f5781b55b6eb6d5b9f0e2955f
diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart
index 47c13d6..aff6c7c 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/web.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart
@@ -95,10 +95,10 @@
logger: environment.logger,
);
final FlutterProject flutterProject = FlutterProject.current();
- final String languageVersion = determineLanguageVersion(
+ final LanguageVersion languageVersion = determineLanguageVersion(
environment.fileSystem.file(targetFile),
packageConfig[flutterProject.manifest.appName],
- ) ?? '';
+ );
// Use the PackageConfig to find the correct package-scheme import path
// for the user application. If the application has a mix of package-scheme
@@ -122,7 +122,7 @@
final String generatedImport = packageConfig.toPackageUri(generatedUri)?.toString()
?? generatedUri.toString();
contents = '''
-$languageVersion
+// @dart=${languageVersion.major}.${languageVersion.minor}
import 'dart:ui' as ui;
@@ -139,7 +139,7 @@
''';
} else {
contents = '''
-$languageVersion
+// @dart=${languageVersion.major}.${languageVersion.minor}
import 'dart:ui' as ui;
diff --git a/packages/flutter_tools/lib/src/dart/language_version.dart b/packages/flutter_tools/lib/src/dart/language_version.dart
index b3f57a6..c4ef436 100644
--- a/packages/flutter_tools/lib/src/dart/language_version.dart
+++ b/packages/flutter_tools/lib/src/dart/language_version.dart
@@ -5,22 +5,24 @@
import 'package:file/file.dart';
import 'package:package_config/package_config.dart';
-final RegExp _languageVersion = RegExp(r'\/\/\s*@dart');
+final RegExp _languageVersion = RegExp(r'\/\/\s*@dart\s*=\s*([0-9])\.([0-9]+)');
final RegExp _declarationEnd = RegExp('(import)|(library)|(part)');
const String _blockCommentStart = '/*';
const String _blockCommentEnd = '*/';
-/// Attempts to read the language version of a dart [file], returning
-/// the entire comment.
+/// The first language version where null safety was available by default.
+final LanguageVersion nullSafeVersion = LanguageVersion(2, 12);
+
+/// Attempts to read the language version of a dart [file].
///
/// If this is not present, falls back to the language version defined in
/// [package]. If [package] is not provided and there is no
-/// language version header, returns `null`. This does not specifically check
+/// language version header, returns 2.12. This does not specifically check
/// for language declarations other than library, part, or import.
///
/// The specification for the language version tag is defined at:
/// https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
-String determineLanguageVersion(File file, Package package) {
+LanguageVersion determineLanguageVersion(File file, Package package) {
int blockCommentDepth = 0;
for (final String line in file.readAsLinesSync()) {
final String trimmedLine = line.trim();
@@ -50,7 +52,17 @@
// Check for a match with the language version.
final Match match = _languageVersion.matchAsPrefix(trimmedLine);
if (match != null) {
- return trimmedLine;
+ final String rawMajor = match.group(1);
+ final String rawMinor = match.group(2);
+ try {
+ final int major = int.parse(rawMajor);
+ final int minor = int.parse(rawMinor);
+ return LanguageVersion(major, minor);
+ } on FormatException {
+ // Language comment was invalid in a way that the regexp did not
+ // anticipate.
+ break;
+ }
}
// Check for a declaration which ends the search for a language
@@ -62,7 +74,8 @@
// If the language version cannot be found, use the package version.
if (package != null) {
- return '// @dart = ${package.languageVersion}';
+ return package.languageVersion;
}
- return null;
+ // Default to 2.12
+ return nullSafeVersion;
}
diff --git a/packages/flutter_tools/lib/src/isolated/devfs_web.dart b/packages/flutter_tools/lib/src/isolated/devfs_web.dart
index d19d8e2..76431d3 100644
--- a/packages/flutter_tools/lib/src/isolated/devfs_web.dart
+++ b/packages/flutter_tools/lib/src/isolated/devfs_web.dart
@@ -124,7 +124,7 @@
this.internetAddress,
this._modules,
this._digests,
- this._buildInfo,
+ this._nullSafetyMode,
) : basePath = _parseBasePathFromIndexHtml(globals.fs.currentDirectory
.childDirectory('web')
.childFile('index.html'));
@@ -169,7 +169,8 @@
BuildInfo buildInfo,
bool enableDwds,
Uri entrypoint,
- ExpressionCompiler expressionCompiler, {
+ ExpressionCompiler expressionCompiler,
+ NullSafetyMode nullSafetyMode, {
bool testMode = false,
DwdsLauncher dwdsLauncher = Dwds.start,
}) async {
@@ -209,7 +210,7 @@
address,
modules,
digests,
- buildInfo,
+ nullSafetyMode,
);
if (testMode) {
return server;
@@ -293,7 +294,7 @@
return server;
}
- final BuildInfo _buildInfo;
+ final NullSafetyMode _nullSafetyMode;
final HttpServer _httpServer;
// If holding these in memory is too much overhead, this can be switched to a
// RandomAccessFile and read on demand.
@@ -670,12 +671,12 @@
File get _resolveDartSdkJsFile =>
globals.fs.file(globals.artifacts.getArtifactPath(
- _dartSdkJsArtifactMap[webRenderer][_buildInfo.nullSafetyMode]
+ _dartSdkJsArtifactMap[webRenderer][_nullSafetyMode]
));
File get _resolveDartSdkJsMapFile =>
globals.fs.file(globals.artifacts.getArtifactPath(
- _dartSdkJsMapArtifactMap[webRenderer][_buildInfo.nullSafetyMode]
+ _dartSdkJsMapArtifactMap[webRenderer][_nullSafetyMode]
));
@override
@@ -733,6 +734,7 @@
@required this.expressionCompiler,
@required this.chromiumLauncher,
@required this.nullAssertions,
+ @required this.nullSafetyMode,
this.testMode = false,
}) : _port = port;
@@ -749,6 +751,7 @@
final ChromiumLauncher chromiumLauncher;
final bool nullAssertions;
final int _port;
+ final NullSafetyMode nullSafetyMode;
WebAssetServer webAssetServer;
@@ -821,6 +824,7 @@
enableDwds,
entrypoint,
expressionCompiler,
+ nullSafetyMode,
testMode: testMode,
);
final int selectedPort = webAssetServer.selectedPort;
diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
index 32f60a4..3ec5c77 100644
--- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
@@ -508,6 +508,7 @@
expressionCompiler: expressionCompiler,
chromiumLauncher: _chromiumLauncher,
nullAssertions: debuggingOptions.nullAssertions,
+ nullSafetyMode: device.nullSafetyMode,
);
final Uri url = await device.devFS.create();
if (debuggingOptions.buildInfo.isDebug) {
@@ -669,12 +670,13 @@
path: '/' + mainUri.pathSegments.last,
);
}
+ final LanguageVersion languageVersion = determineLanguageVersion(
+ globals.fs.file(mainUri),
+ packageConfig[flutterProject.manifest.appName],
+ );
final String entrypoint = <String>[
- determineLanguageVersion(
- globals.fs.file(mainUri),
- packageConfig[flutterProject.manifest.appName],
- ),
+ '// @dart=${languageVersion.major}.${languageVersion.minor}',
'// Flutter web bootstrap script for $importedEntrypoint.',
'',
"import 'dart:ui' as ui;",
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index ab841cc..07688c6 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -27,6 +27,8 @@
import 'bundle.dart';
import 'cache.dart';
import 'compile.dart';
+import 'dart/language_version.dart';
+import 'dart/package_map.dart';
import 'devfs.dart';
import 'device.dart';
import 'features.dart';
@@ -46,6 +48,7 @@
TargetPlatform targetPlatform,
ResidentCompiler generator,
this.userIdentifier,
+ this.nullSafetyMode = NullSafetyMode.autodetect,
}) : assert(buildInfo.trackWidgetCreation != null),
generator = generator ?? ResidentCompiler(
globals.artifacts.getArtifactPath(
@@ -81,6 +84,7 @@
String userIdentifier,
}) async {
ResidentCompiler generator;
+ NullSafetyMode nullSafetyMode = buildInfo.nullSafetyMode;
final TargetPlatform targetPlatform = await device.targetPlatform;
if (device.platformType == PlatformType.fuchsia) {
targetModel = TargetModel.flutterRunner;
@@ -101,14 +105,30 @@
platformDillArtifact = Artifact.webPlatformSoundKernelDill;
extraFrontEndOptions = buildInfo.extraFrontEndOptions;
} else {
- // TODO(jonahwilliams): null-safe auto detection does not currently
- // work on the web. Always opt out of null safety if it was not
- // specifically requested.
- platformDillArtifact = Artifact.webPlatformKernelDill;
- extraFrontEndOptions = <String>[
- ...?buildInfo.extraFrontEndOptions,
- '--no-sound-null-safety',
- ];
+ final PackageConfig packageConfig = await loadPackageConfigWithLogging(
+ globals.fs.file(buildInfo.packagesPath),
+ logger: globals.logger,
+ );
+ final File entrypointFile = globals.fs.file(target);
+ final LanguageVersion languageVersion = determineLanguageVersion(
+ entrypointFile,
+ packageConfig.packageOf(entrypointFile.absolute.uri),
+ );
+ if (languageVersion.major >= nullSafeVersion.major && languageVersion.minor >= nullSafeVersion.minor) {
+ platformDillArtifact = Artifact.webPlatformSoundKernelDill;
+ extraFrontEndOptions = <String>[
+ ...?buildInfo.extraFrontEndOptions,
+ '--sound-null-safety',
+ ];
+ nullSafetyMode = NullSafetyMode.sound;
+ } else {
+ platformDillArtifact = Artifact.webPlatformKernelDill;
+ extraFrontEndOptions = <String>[
+ ...?buildInfo.extraFrontEndOptions,
+ '--no-sound-null-safety',
+ ];
+ nullSafetyMode = NullSafetyMode.unsound;
+ }
}
generator = ResidentCompiler(
@@ -182,6 +202,7 @@
generator: generator,
buildInfo: buildInfo,
userIdentifier: userIdentifier,
+ nullSafetyMode: nullSafetyMode,
);
}
@@ -189,6 +210,7 @@
final ResidentCompiler generator;
final BuildInfo buildInfo;
final String userIdentifier;
+ final NullSafetyMode nullSafetyMode;
DevFSWriter devFSWriter;
Stream<Uri> observatoryUris;
diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart
index af86f99..ff713c2 100644
--- a/packages/flutter_tools/lib/src/test/flutter_platform.dart
+++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart
@@ -713,19 +713,19 @@
}) {
assert(testUrl.scheme == 'file');
final File file = globals.fs.file(testUrl);
+ final LanguageVersion languageVersion = determineLanguageVersion(
+ file,
+ _packageConfig[flutterProject?.manifest?.appName],
+ );
return generateTestBootstrap(
testUrl: testUrl,
testConfigFile: findTestConfigFile(globals.fs.file(testUrl)),
host: host,
updateGoldens: updateGoldens,
- languageVersionHeader: determineLanguageVersion(
- file,
- _packageConfig[flutterProject?.manifest?.appName],
- ),
+ languageVersionHeader: '// @dart=${languageVersion.major}.${languageVersion.minor}'
);
}
-
File _cachedFontConfig;
@override
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
index 615d0e0..e5202ba 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
@@ -238,7 +238,7 @@
final String generated = environment.buildDir.childFile('main.dart').readAsStringSync();
// Language version
- expect(generated, contains('// @dart = 2.7'));
+ expect(generated, contains('// @dart=2.7'));
}));
test('WebEntrypointTarget generates an entrypoint without plugins and without init platform', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/dart/language_version_test.dart b/packages/flutter_tools/test/general.shard/dart/language_version_test.dart
index 2bfc87d..b9e2ed3 100644
--- a/packages/flutter_tools/test/general.shard/dart/language_version_test.dart
+++ b/packages/flutter_tools/test/general.shard/dart/language_version_test.dart
@@ -19,10 +19,34 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), '// @dart = 2.9');
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 9));
});
- testWithoutContext('detects technically invalid language version', () {
+ testWithoutContext('detects language version in comment without spacing', () {
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ final File file = fileSystem.file('example.dart')
+ ..writeAsStringSync('''
+// Some license
+
+// @dart=2.9
+''');
+
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 9));
+ });
+
+ testWithoutContext('detects language version in comment with more numbers', () {
+ final FileSystem fileSystem = MemoryFileSystem.test();
+ final File file = fileSystem.file('example.dart')
+ ..writeAsStringSync('''
+// Some license
+
+// @dart=2.12
+''');
+
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
+ });
+
+ testWithoutContext('does not detect invalid language version', () {
final FileSystem fileSystem = MemoryFileSystem.test();
final File file = fileSystem.file('example.dart')
..writeAsStringSync('''
@@ -31,7 +55,7 @@
// @dart
''');
- expect(determineLanguageVersion(file, null), '// @dart');
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('detects language version with leading whitespace', () {
@@ -43,7 +67,7 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), '// @dart = 2.9');
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 9));
});
testWithoutContext('detects language version with tabs', () {
@@ -55,7 +79,7 @@
//\t@dart = 2.9
''');
- expect(determineLanguageVersion(file, null), '//\t@dart = 2.9');
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 9));
});
testWithoutContext('detects language version with tons of whitespace', () {
@@ -64,10 +88,10 @@
..writeAsStringSync('''
// Some license
-// @dart = 23
+// @dart = 2.23
''');
- expect(determineLanguageVersion(file, null), '// @dart = 23');
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 23));
});
testWithoutContext('does not detect language version in dartdoc', () {
@@ -79,7 +103,7 @@
/// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('does not detect language version in block comment', () {
@@ -93,7 +117,7 @@
*/
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('does not detect language version in nested block comment', () {
@@ -109,7 +133,7 @@
*/
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('detects language version after nested block comment', () {
@@ -124,7 +148,7 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), '// @dart = 2.9');
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 9));
});
testWithoutContext('does not crash with unbalanced opening block comments', () {
@@ -139,7 +163,7 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('does not crash with unbalanced closing block comments', () {
@@ -154,7 +178,7 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('does not detect language version in single line block comment', () {
@@ -166,7 +190,7 @@
/* // @dart = 2.9 */
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('does not detect language version after import declaration', () {
@@ -180,7 +204,7 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('does not detect language version after part declaration', () {
@@ -194,7 +218,7 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('does not detect language version after library declaration', () {
@@ -208,7 +232,7 @@
// @dart = 2.9
''');
- expect(determineLanguageVersion(file, null), null);
+ expect(determineLanguageVersion(file, null), LanguageVersion(2, 12));
});
testWithoutContext('looks up language version from package if not found in file', () {
@@ -223,6 +247,6 @@
languageVersion: LanguageVersion(2, 7),
);
- expect(determineLanguageVersion(file, package), '// @dart = 2.7');
+ expect(determineLanguageVersion(file, package), LanguageVersion(2, 7));
});
}
diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
index ed77f83..c90af3d 100644
--- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
@@ -629,6 +629,7 @@
testMode: true,
expressionCompiler: null,
chromiumLauncher: null,
+ nullSafetyMode: NullSafetyMode.unsound,
);
webDevFS.requireJS.createSync(recursive: true);
webDevFS.stackTraceMapper.createSync(recursive: true);
@@ -745,6 +746,7 @@
testMode: true,
expressionCompiler: null,
chromiumLauncher: null,
+ nullSafetyMode: NullSafetyMode.autodetect,
);
webDevFS.requireJS.createSync(recursive: true);
webDevFS.stackTraceMapper.createSync(recursive: true);
@@ -853,6 +855,7 @@
expressionCompiler: null,
chromiumLauncher: null,
nullAssertions: true,
+ nullSafetyMode: NullSafetyMode.sound,
);
webDevFS.requireJS.createSync(recursive: true);
webDevFS.stackTraceMapper.createSync(recursive: true);
@@ -903,6 +906,7 @@
testMode: true,
expressionCompiler: null,
chromiumLauncher: null,
+ nullSafetyMode: NullSafetyMode.sound,
);
webDevFS.requireJS.createSync(recursive: true);
webDevFS.stackTraceMapper.createSync(recursive: true);
@@ -954,6 +958,7 @@
testMode: true,
expressionCompiler: null,
chromiumLauncher: null,
+ nullSafetyMode: NullSafetyMode.sound,
);
webDevFS.requireJS.createSync(recursive: true);
webDevFS.stackTraceMapper.createSync(recursive: true);
@@ -981,6 +986,7 @@
false,
Uri.base,
null,
+ null,
testMode: true);
expect(webAssetServer.defaultResponseHeaders['x-frame-options'], null);