Allow empty pubspec file when building asset bundle (#12269)

diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index b5a1ef8..92bc656 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -75,13 +75,19 @@
     FlutterManifest flutterManifest;
     try {
       flutterManifest = await FlutterManifest.createFromPath(manifestPath);
-      if (flutterManifest == null)
-        return 1;
     } catch (e) {
       printStatus('Error detected in pubspec.yaml:', emphasis: true);
       printError('$e');
       return 1;
     }
+    if (flutterManifest == null)
+      return 1;
+
+    if (flutterManifest.isEmpty) {
+      entries[_kAssetManifestJson] = new DevFSStringContent('{}');
+      return 0;
+    }
+
     final String assetBasePath = fs.path.dirname(fs.path.absolute(manifestPath));
 
     _lastBuildTimestamp = new DateTime.now();
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index 3c84800..b1bff4b 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -26,10 +26,10 @@
 
   static Future<FlutterManifest> _createFromYaml(Object yamlDocument) async {
     final FlutterManifest pubspec = new FlutterManifest._();
-    if (yamlDocument == null || !await _validate(yamlDocument))
+    if (yamlDocument != null && !await _validate(yamlDocument))
       return null;
 
-    pubspec._descriptor = yamlDocument;
+    pubspec._descriptor = yamlDocument ?? <String, dynamic>{};
     pubspec._flutterDescriptor = pubspec._descriptor['flutter'] ?? <String, dynamic>{};
     return pubspec;
   }
@@ -40,7 +40,9 @@
   /// A map representation of the `flutter` section in the `pubspec.yaml` file.
   Map<String, dynamic> _flutterDescriptor;
 
-  String get appName => _descriptor['name'];
+  bool get isEmpty => _descriptor.isEmpty;
+
+  String get appName => _descriptor['name'] ?? '';
 
   bool get usesMaterialDesign {
     return _flutterDescriptor['uses-material-design'] ?? false;
diff --git a/packages/flutter_tools/test/asset_bundle_test.dart b/packages/flutter_tools/test/asset_bundle_test.dart
index 0da197e..6f5fe04 100644
--- a/packages/flutter_tools/test/asset_bundle_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_test.dart
@@ -5,6 +5,7 @@
 import 'dart:convert';
 
 import 'package:file/file.dart';
+import 'package:file/memory.dart';
 
 import 'package:flutter_tools/src/asset.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -80,6 +81,21 @@
       expect(await ab.build(), 0);
       expect(ab.entries.length, greaterThan(0));
     });
+
+    testUsingContext('empty pubspec', () async {
+      fs.file('pubspec.yaml')
+        ..createSync()
+        ..writeAsStringSync('');
+
+      final AssetBundle bundle = new AssetBundle();
+      await bundle.build(manifestPath: 'pubspec.yaml');
+      expect(bundle.entries.length, 1);
+      final String expectedAssetManifest = '{}';
+      expect(
+        UTF8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
+        expectedAssetManifest,
+      );
+    }, overrides: <Type, Generator>{FileSystem: () => new MemoryFileSystem(),});
   });
 
 }
diff --git a/packages/flutter_tools/test/flutter_manifest_test.dart b/packages/flutter_tools/test/flutter_manifest_test.dart
index 2395172..3644ad6 100644
--- a/packages/flutter_tools/test/flutter_manifest_test.dart
+++ b/packages/flutter_tools/test/flutter_manifest_test.dart
@@ -16,6 +16,16 @@
   });
 
   group('FlutterManifest', () {
+    testUsingContext('is empty when the pubspec.yaml file is empty', () async {
+      final FlutterManifest flutterManifest = await FlutterManifest.createFromString('');
+      expect(flutterManifest.isEmpty, true);
+      expect(flutterManifest.appName, '');
+      expect(flutterManifest.usesMaterialDesign, false);
+      expect(flutterManifest.fontsDescriptor, isEmpty);
+      expect(flutterManifest.fonts, isEmpty);
+      expect(flutterManifest.assets, isEmpty);
+    });
+
     test('has no fonts or assets when the "flutter" section is empty', () async {
       final String manifest = '''
 name: test
@@ -25,6 +35,7 @@
 ''';
       final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
       expect(flutterManifest, isNotNull);
+      expect(flutterManifest.isEmpty, false);
       expect(flutterManifest.appName, 'test');
       expect(flutterManifest.usesMaterialDesign, false);
       expect(flutterManifest.fontsDescriptor, isEmpty);