Unverified Commit 3f68b25b authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_tools] fix cast error when dart-defines-json file includes null (#128909)

Fixes https://github.com/flutter/flutter/issues/128787
parent dc4541fa
......@@ -38,7 +38,7 @@ class BuildInfo {
this.webRenderer = WebRendererMode.auto,
required this.treeShakeIcons,
this.performanceMeasurementFile,
this.dartDefineConfigJsonMap,
this.dartDefineConfigJsonMap = const <String, Object?>{},
this.packagesPath = '.dart_tool/package_config.json', // TODO(zanderso): make this required and remove the default.
this.nullSafetyMode = NullSafetyMode.sound,
this.codeSizeDirectory,
......@@ -144,7 +144,7 @@ class BuildInfo {
///
/// An additional field `dartDefineConfigJsonMap` is provided to represent the native JSON value of the configuration file
///
final Map<String, Object>? dartDefineConfigJsonMap;
final Map<String, Object?> dartDefineConfigJsonMap;
/// If provided, an output directory where one or more v8-style heap snapshots
/// will be written for code size profiling.
......@@ -267,7 +267,7 @@ class BuildInfo {
/// Fields that are `null` are excluded from this configuration.
Map<String, String> toEnvironmentConfig() {
final Map<String, String> map = <String, String>{};
dartDefineConfigJsonMap?.forEach((String key, Object value) {
dartDefineConfigJsonMap.forEach((String key, Object? value) {
map[key] = '$value';
});
final Map<String, String> environmentMap = <String, String>{
......@@ -327,17 +327,15 @@ class BuildInfo {
for (final String projectArg in androidProjectArgs)
'-P$projectArg',
];
if (dartDefineConfigJsonMap != null) {
final Iterable<String> gradleConfKeys = result.map((final String gradleConf) => gradleConf.split('=')[0].substring(2));
dartDefineConfigJsonMap!.forEach((String key, Object value) {
if (gradleConfKeys.contains(key)) {
globals.printWarning(
'The key: [$key] already exists, you cannot use gradle variables that have been used by the system!');
} else {
result.add('-P$key=$value');
}
});
}
final Iterable<String> gradleConfKeys = result.map((final String gradleConf) => gradleConf.split('=')[0].substring(2));
dartDefineConfigJsonMap.forEach((String key, Object? value) {
if (gradleConfKeys.contains(key)) {
globals.printWarning(
'The key: [$key] already exists, you cannot use gradle variables that have been used by the system!');
} else {
result.add('-P$key=$value');
}
});
return result;
}
}
......
......@@ -21,7 +21,6 @@ import 'devfs.dart';
import 'globals.dart' as globals;
import 'project.dart';
/// Provides a `build` method that builds the bundle.
class BundleBuilder {
/// Builds the bundle for the given target platform.
......
......@@ -258,7 +258,7 @@ class AssembleCommand extends FlutterCommand {
results[kExtraGenSnapshotOptions] = (argumentResults[FlutterOptions.kExtraGenSnapshotOptions] as List<String>).join(',');
}
final Map<String, Object>? defineConfigJsonMap = extractDartDefineConfigJsonMap();
final Map<String, Object?> defineConfigJsonMap = extractDartDefineConfigJsonMap();
final List<String> dartDefines = extractDartDefines(defineConfigJsonMap: defineConfigJsonMap);
if (dartDefines.isNotEmpty){
results[kDartDefines] = dartDefines.join(',');
......
......@@ -2,8 +2,6 @@
// 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:meta/meta.dart';
......
......@@ -1190,7 +1190,7 @@ abstract class FlutterCommand extends Command<void> {
? stringArg(FlutterOptions.kPerformanceMeasurementFile)
: null;
final Map<String, Object>? defineConfigJsonMap = extractDartDefineConfigJsonMap();
final Map<String, Object?> defineConfigJsonMap = extractDartDefineConfigJsonMap();
List<String> dartDefines = extractDartDefines(defineConfigJsonMap: defineConfigJsonMap);
WebRendererMode webRenderer = WebRendererMode.auto;
......@@ -1323,29 +1323,26 @@ abstract class FlutterCommand extends Command<void> {
}
}
List<String> extractDartDefines({Map<String, Object>? defineConfigJsonMap}) {
List<String> extractDartDefines({required Map<String, Object?> defineConfigJsonMap}) {
final List<String> dartDefines = <String>[];
if (argParser.options.containsKey(FlutterOptions.kDartDefinesOption)) {
dartDefines.addAll(stringsArg(FlutterOptions.kDartDefinesOption));
}
if (defineConfigJsonMap == null) {
return dartDefines;
}
defineConfigJsonMap.forEach((String key, Object value) {
defineConfigJsonMap.forEach((String key, Object? value) {
dartDefines.add('$key=$value');
});
return dartDefines;
}
Map<String, Object>? extractDartDefineConfigJsonMap() {
final Map<String, Object> dartDefineConfigJsonMap = <String, Object>{};
Map<String, Object?> extractDartDefineConfigJsonMap() {
final Map<String, Object?> dartDefineConfigJsonMap = <String, Object?>{};
if (argParser.options.containsKey(FlutterOptions.kDartDefineFromFileOption)) {
final List<String> configJsonPaths = stringsArg(
FlutterOptions.kDartDefineFromFileOption,
FlutterOptions.kDartDefineFromFileOption,
);
for (final String path in configJsonPaths) {
......@@ -1359,8 +1356,8 @@ abstract class FlutterCommand extends Command<void> {
try {
// Fix json convert Object value :type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<String, Object>' in type cast
(json.decode(configJsonRaw) as Map<String, dynamic>)
.forEach((String key, dynamic value) {
dartDefineConfigJsonMap[key] = value as Object;
.forEach((String key, Object? value) {
dartDefineConfigJsonMap[key] = value;
});
} on FormatException catch (err) {
throwToolExit('Json config define file "--${FlutterOptions
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:typed_data';
import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -12,6 +14,7 @@ import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build_bundle.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/project.dart';
......@@ -504,7 +507,7 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('test --dart-define-from-file option', () async {
testUsingContext('--dart-define-from-file successfully forwards values to build env', () async {
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync();
......@@ -514,7 +517,8 @@ void main() {
"kInt": 1,
"kDouble": 1.1,
"name": "denghaizhu",
"title": "this is title from config json file"
"title": "this is title from config json file",
"nullValue": null
}
'''
);
......@@ -537,7 +541,17 @@ void main() {
]);
}, overrides: <Type, Generator>{
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) {
expect(environment.defines[kDartDefines], 'a0ludD0x,a0RvdWJsZT0xLjE=,bmFtZT1kZW5naGFpemh1,dGl0bGU9dGhpcyBpcyB0aXRsZSBmcm9tIGNvbmZpZyBqc29uIGZpbGU=,Ym9keT10aGlzIGlzIGJvZHkgZnJvbSBjb25maWcganNvbiBmaWxl');
expect(
_decodeDartDefines(environment),
containsAllInOrder(const <String>[
'kInt=1',
'kDouble=1.1',
'name=denghaizhu',
'title=this is title from config json file',
'nullValue=null',
'body=this is body from config json file',
]),
);
}),
FileSystem: fsFactory,
ProcessManager: () => FakeProcessManager.any(),
......@@ -576,7 +590,10 @@ void main() {
]);
}, overrides: <Type, Generator>{
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) {
expect(environment.defines[kDartDefines], 'a0ludD0y,a0RvdWJsZT0xLjE=,bmFtZT1kZW5naGFpemh1,dGl0bGU9dGhpcyBpcyB0aXRsZSBmcm9tIGNvbmZpZyBqc29uIGZpbGU=');
expect(
_decodeDartDefines(environment),
containsAllInOrder(<String>['kInt=2', 'kDouble=1.1', 'name=denghaizhu', 'title=this is title from config json file']),
);
}),
FileSystem: fsFactory,
ProcessManager: () => FakeProcessManager.any(),
......@@ -632,6 +649,15 @@ void main() {
});
}
Iterable<String> _decodeDartDefines(Environment environment) {
final String encodedDefines = environment.defines[kDartDefines]!;
const Utf8Decoder byteDecoder = Utf8Decoder();
return encodedDefines
.split(',')
.map<Uint8List>(base64.decode)
.map<String>(byteDecoder.convert);
}
class FakeBundleBuilder extends Fake implements BundleBuilder {
@override
Future<void> build({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment