Enabling adding and querying for source maps in a MappingBundle.

BUG=
R=sigmund@google.com

Review-Url: https://codereview.chromium.org//2736983002 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d2bed8a..95b161d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 0.10.3
+ * Add `addMapping` and `containsMapping` members to `MappingBundle`.
+
 ## 0.10.2
  * Support for extended source map format.
  * Polish `MappingBundle.spanFor` handling of URIs that have a suffix that
diff --git a/lib/parser.dart b/lib/parser.dart
index 1c23187..3b65e89 100644
--- a/lib/parser.dart
+++ b/lib/parser.dart
@@ -180,16 +180,20 @@
 class MappingBundle extends Mapping {
   Map<String, SingleMapping> _mappings = {};
 
+  MappingBundle() {}
+
   MappingBundle.fromJson(List json, {String mapUrl}) {
     for (var map in json) {
-      var mapping = parseJson(map, mapUrl: mapUrl) as SingleMapping;
-      var targetUrl = mapping.targetUrl;
-      // TODO(jacobr): verify that targetUrl is valid uri instead of a windows
-      // path.
-      _mappings[targetUrl] = mapping;
+      addMapping(parseJson(map, mapUrl: mapUrl) as SingleMapping);
     }
   }
 
+  addMapping(SingleMapping mapping) {
+    // TODO(jacobr): verify that targetUrl is valid uri instead of a windows
+    // path.
+    _mappings[mapping.targetUrl] = mapping;
+  }
+
   /// Encodes the Mapping mappings as a json map.
   List toJson() => _mappings.values.map((v) => v.toJson()).toList();
 
@@ -201,6 +205,8 @@
     return buff.toString();
   }
 
+  bool containsMapping(String url) => _mappings.containsKey(url);
+
   SourceMapSpan spanFor(int line, int column,
       {Map<String, SourceFile> files, String uri}) {
     if (uri == null) {
diff --git a/pubspec.yaml b/pubspec.yaml
index 64c0e9c..6185512 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: source_maps
-version: 0.10.2
+version: 0.10.3
 author: Dart Team <misc@dartlang.org>
 description: Library to programmatically manipulate source map files.
 homepage: http://github.com/dart-lang/source_maps
diff --git a/test/parser_test.dart b/test/parser_test.dart
index 3cccf44..2c24d1b 100644
--- a/test/parser_test.dart
+++ b/test/parser_test.dart
@@ -262,6 +262,29 @@
           Uri.parse("file:///path/to/pkg/input3.dart"));
     });
 
+    test('build bundle incrementally', () {
+      var mapping = new MappingBundle();
+
+      mapping.addMapping(parseJson(MAP_WITH_SOURCE_LOCATION_AND_NAME_1,
+          mapUrl: "file:///path/to/map"));
+      expect(mapping.spanFor(0, 0, uri: "output.dart").sourceUrl,
+          Uri.parse("file:///path/to/pkg/input1.dart"));
+
+      expect(mapping.containsMapping("output2.dart"), isFalse);
+      mapping.addMapping(parseJson(MAP_WITH_SOURCE_LOCATION_AND_NAME_2,
+          mapUrl: "file:///path/to/map"));
+      expect(mapping.containsMapping("output2.dart"), isTrue);
+      expect(mapping.spanFor(0, 0, uri: "output2.dart").sourceUrl,
+          Uri.parse("file:///path/to/pkg/input2.dart"));
+
+      expect(mapping.containsMapping("3/output.dart"), isFalse);
+      mapping.addMapping(parseJson(MAP_WITH_SOURCE_LOCATION_AND_NAME_3,
+          mapUrl: "file:///path/to/map"));
+      expect(mapping.containsMapping("3/output.dart"), isTrue);
+      expect(mapping.spanFor(0, 0, uri: "3/output.dart").sourceUrl,
+          Uri.parse("file:///path/to/pkg/input3.dart"));
+    });
+
     // Test that the source map can handle cases where the uri passed in is
     // not from the expected host but it is still unambiguous which source
     // map should be used.