Don't crash when pubspec isn't a map (#59632)
This commit is contained in:
@@ -40,16 +40,16 @@ class FlutterManifest {
|
||||
/// Returns null on missing or invalid manifest
|
||||
@visibleForTesting
|
||||
static FlutterManifest createFromString(String manifest, { @required Logger logger }) {
|
||||
return _createFromYaml(loadYaml(manifest) as YamlMap, logger);
|
||||
return _createFromYaml(manifest != null ? loadYaml(manifest) : null, logger);
|
||||
}
|
||||
|
||||
static FlutterManifest _createFromYaml(YamlMap yamlDocument, Logger logger) {
|
||||
final FlutterManifest pubspec = FlutterManifest._(logger);
|
||||
static FlutterManifest _createFromYaml(dynamic yamlDocument, Logger logger) {
|
||||
if (yamlDocument != null && !_validate(yamlDocument, logger)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Map<dynamic, dynamic> yamlMap = yamlDocument;
|
||||
final FlutterManifest pubspec = FlutterManifest._(logger);
|
||||
final Map<dynamic, dynamic> yamlMap = yamlDocument as YamlMap;
|
||||
if (yamlMap != null) {
|
||||
pubspec._descriptor = yamlMap.cast<String, dynamic>();
|
||||
} else {
|
||||
@@ -332,32 +332,36 @@ String buildSchemaPath(FileSystem fileSystem) {
|
||||
/// This method should be kept in sync with the schema in
|
||||
/// `$FLUTTER_ROOT/packages/flutter_tools/schema/pubspec_yaml.json`,
|
||||
/// but avoid introducing dependencies on packages for simple validation.
|
||||
bool _validate(YamlMap manifest, Logger logger) {
|
||||
bool _validate(dynamic manifest, Logger logger) {
|
||||
final List<String> errors = <String>[];
|
||||
for (final MapEntry<dynamic, dynamic> kvp in manifest.entries) {
|
||||
if (kvp.key is! String) {
|
||||
errors.add('Expected YAML key to be a string, but got ${kvp.key}.');
|
||||
continue;
|
||||
}
|
||||
switch (kvp.key as String) {
|
||||
case 'name':
|
||||
if (kvp.value is! String) {
|
||||
errors.add('Expected "${kvp.key}" to be a string, but got ${kvp.value}.');
|
||||
}
|
||||
break;
|
||||
case 'flutter':
|
||||
if (kvp.value == null) {
|
||||
continue;
|
||||
}
|
||||
if (kvp.value is! YamlMap) {
|
||||
errors.add('Expected "${kvp.key}" section to be an object or null, but got ${kvp.value}.');
|
||||
} else {
|
||||
_validateFlutter(kvp.value as YamlMap, errors);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (manifest is! YamlMap) {
|
||||
errors.add('Expected YAML map');
|
||||
} else {
|
||||
for (final MapEntry<dynamic, dynamic> kvp in (manifest as YamlMap).entries) {
|
||||
if (kvp.key is! String) {
|
||||
errors.add('Expected YAML key to be a string, but got ${kvp.key}.');
|
||||
continue;
|
||||
}
|
||||
switch (kvp.key as String) {
|
||||
case 'name':
|
||||
if (kvp.value is! String) {
|
||||
errors.add('Expected "${kvp.key}" to be a string, but got ${kvp.value}.');
|
||||
}
|
||||
break;
|
||||
case 'flutter':
|
||||
if (kvp.value == null) {
|
||||
continue;
|
||||
}
|
||||
if (kvp.value is! YamlMap) {
|
||||
errors.add('Expected "${kvp.key}" section to be an object or null, but got ${kvp.value}.');
|
||||
} else {
|
||||
_validateFlutter(kvp.value as YamlMap, errors);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// additionalProperties are allowed.
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,16 @@ void main() {
|
||||
expect(flutterManifest.assets, isEmpty);
|
||||
});
|
||||
|
||||
testWithoutContext('FlutterManifest is null when the pubspec.yaml file is not a map', () async {
|
||||
final BufferLogger logger = BufferLogger.test();
|
||||
expect(FlutterManifest.createFromString(
|
||||
'Not a map',
|
||||
logger: logger,
|
||||
), isNull);
|
||||
|
||||
expect(logger.errorText, contains('Expected YAML map'));
|
||||
});
|
||||
|
||||
testWithoutContext('FlutterManifest has no fonts or assets when the "flutter" section is empty', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
|
||||
Reference in New Issue
Block a user