Version 1.5.0-dev.4.9

svn merge -c 37254 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 37256 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@37272 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart
index 7e04dc5..cd9ae9f 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/map_tracer.dart
@@ -79,6 +79,7 @@
             // the map.
             TypeInformation map = info.arguments.positional[0];
             if (map is MapTypeInformation) {
+              inferrer.analyzeMapAndEnqueue(map);
               mapAssignments.add(map);
             } else {
               // If we could select a component from a [TypeInformation],
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index ead1c4a..20c4dc3 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -1065,7 +1065,9 @@
   bool analyzed = false;
 
   // Set to false if a statically unknown key flows into this map.
-  bool isDictionary = true;
+  bool _allKeysAreStrings = true;
+
+  bool get inDictionaryMode => !bailedOut && _allKeysAreStrings;
 
   MapTypeInformation(this.initialType, this.keyType, this.valueType) {
     keyType.addUser(this);
@@ -1077,13 +1079,13 @@
                                      TypeInformation value,
                                      [bool nonNull = false]) {
     TypeInformation newInfo = null;
-    if (isDictionary && key is StringLiteralTypeInformation) {
+    if (_allKeysAreStrings && key is StringLiteralTypeInformation) {
       String keyString = key.asString();
       typeInfoMap.putIfAbsent(keyString,
           () => newInfo = new ValueInMapTypeInformation(null, nonNull));
       typeInfoMap[keyString].addAssignment(value);
     } else {
-      isDictionary = false;
+      _allKeysAreStrings = false;
       typeInfoMap.clear();
     }
     keyType.addAssignment(key);
@@ -1093,10 +1095,10 @@
     return newInfo;
   }
 
-  List<TypeInformation> addMapAssignment(MapTypeInformation map) {
+  List<TypeInformation> addMapAssignment(MapTypeInformation other) {
     List<TypeInformation> newInfos = <TypeInformation>[];
-    if (map.isDictionary) {
-      map.typeInfoMap.forEach((keyString, value) {
+    if (_allKeysAreStrings && other.inDictionaryMode) {
+      other.typeInfoMap.forEach((keyString, value) {
         typeInfoMap.putIfAbsent(keyString, () {
           TypeInformation newInfo = new ValueInMapTypeInformation(null, false);
           newInfos.add(newInfo);
@@ -1104,9 +1106,12 @@
         });
         typeInfoMap[keyString].addAssignment(value);
       });
+    } else {
+      _allKeysAreStrings = false;
+      typeInfoMap.clear();
     }
-    keyType.addAssignment(map.keyType);
-    valueType.addAssignment(map.valueType);
+    keyType.addAssignment(other.keyType);
+    valueType.addAssignment(other.valueType);
 
     return newInfos;
   }
@@ -1125,7 +1130,7 @@
   }
 
   TypeMask toTypeMask(TypeGraphInferrerEngine inferrer) {
-    if (isDictionary) {
+    if (inDictionaryMode) {
       Map<String, TypeMask> mappings = new Map<String, TypeMask>();
       for (var key in typeInfoMap.keys) {
         mappings[key] = typeInfoMap[key].type;
@@ -1146,9 +1151,10 @@
   }
 
   TypeMask refine(TypeGraphInferrerEngine inferrer) {
-    if (!bailedOut && type.isDictionary != isDictionary) {
+    if (type.isDictionary != inDictionaryMode) {
       return toTypeMask(inferrer);
-    } else if (!bailedOut && type.isDictionary) {
+    } else if (type.isDictionary) {
+      assert(inDictionaryMode);
       DictionaryTypeMask mask = type;
       for (var key in typeInfoMap.keys) {
         TypeInformation value = typeInfoMap[key];
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
index 06e05c8..021c7b3 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
@@ -239,6 +239,7 @@
     var descriptor = data[4];
     var isRoot = !!data[5];
     var fields = descriptor && descriptor["${namer.classDescriptorProperty}"];
+    if (fields instanceof Array) fields = fields[0];
     var classes = [];
     var functions = [];
     processStatics(descriptor);
diff --git a/tests/compiler/dart2js/dictionary_types_test.dart b/tests/compiler/dart2js/dictionary_types_test.dart
index 78a59aa..b95942a 100644
--- a/tests/compiler/dart2js/dictionary_types_test.dart
+++ b/tests/compiler/dart2js/dictionary_types_test.dart
@@ -8,7 +8,7 @@
 import 'compiler_helper.dart' show findElement;
 
 var SOURCES = const {
-'testAddAll.dart': """
+'AddAll.dart': """
   var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
                      'list': []};
   var dictionaryB = {'string': "aString", 'int': 42, 'double': 21.5,
@@ -28,7 +28,7 @@
     nullOrInt = dictionaryB['intTwo'];
   }
 """,
-'testUnion.dart': """
+'Union.dart': """
   var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
                      'list': []};
   var dictionaryB = {'string': "aString", 'intTwo': 42, 'list': []};
@@ -44,7 +44,7 @@
     doubleOrNull = union['double'];
   }
 """,
-'testValueType.dart': """
+'ValueType.dart': """
   var dictionary = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
   var keyD = 'double';
   var keyI = 'int';
@@ -58,7 +58,7 @@
     var x = [intOrNull, justNull];
   }
 """,
-'testPropagation.dart': """
+'Propagation.dart': """
   class A {
     A();
     foo(value) {
@@ -83,28 +83,52 @@
     }
     print(it.foo(dictionary) + 2);
   }
+""",
+'Bailout.dart': """
+  var dict = makeMap([1,2]);
+  var notInt = 0;
+  var alsoNotInt = 0;
+
+  makeMap(values) {
+    return {'moo': values[0], 'boo': values[1]};
+  }
+
+  main () {
+    dict['goo'] = 42;
+    var closure = dictfun() => dict;
+    notInt = closure()['boo'];
+    alsoNotInt = dict['goo'];
+    print("\$notInt and \$alsoNotInt.");
+  }
 """};
 
 void main() {
   asyncTest(() =>
-    compileAndTest("testAddAll.dart", (types, getType, compiler) {
+    compileAndTest("AddAll.dart", (types, getType, compiler) {
       Expect.equals(getType('int'), types.uint31Type);
       Expect.equals(getType('anotherInt'), types.uint31Type);
       Expect.equals(getType('dynamic'), types.dynamicType);
       Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-    }).then((_) => compileAndTest("testUnion.dart", (types, getType, compiler) {
-      Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-      Expect.isTrue(getType('aString').containsOnlyString(compiler));
-      Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
-    })).then((_) => compileAndTest("testValueType.dart",
-        (types, getType, compiler) {
+    }));
+  asyncTest(() => compileAndTest("Union.dart", (types, getType, compiler) {
+    Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
+    Expect.isTrue(getType('aString').containsOnlyString(compiler));
+    Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
+  }));
+  asyncTest(() => 
+    compileAndTest("ValueType.dart", (types, getType, compiler) {
       Expect.equals(getType('knownDouble'), types.doubleType);
       Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
       Expect.equals(getType('justNull'), types.nullType);
-    })).then((_) => compileAndTest("testPropagation.dart", (code) {
-      Expect.isFalse(code.contains("J.\$add\$ns"));
-    }, createCode: true))
-  );
+    }));
+  asyncTest(() => compileAndTest("Propagation.dart", (code) {
+    Expect.isFalse(code.contains("J.\$add\$ns"));
+  }, createCode: true));
+  asyncTest(() => compileAndTest("Bailout.dart", (types, getType, compiler) {
+    Expect.equals(getType('notInt'), types.dynamicType);
+    Expect.equals(getType('alsoNotInt'), types.dynamicType);
+    Expect.isFalse(getType('dict').isDictionary);
+  }));
 }
 
 compileAndTest(source, checker, {createCode: false}) {
diff --git a/tests/lib/mirrors/metadata_class_mirror_test.dart b/tests/lib/mirrors/metadata_class_mirror_test.dart
new file mode 100644
index 0000000..82aeee7
--- /dev/null
+++ b/tests/lib/mirrors/metadata_class_mirror_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for http://dartbug.com/19173
+
+import 'dart:mirrors';
+
+class A {
+    const A();
+}
+
+@deprecated
+const A anA = const A();
+
+main() {
+  ClassMirror typeMirror = reflectType(A);
+  var decs = typeMirror.declarations;
+  print(decs.length);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 18c0c2c..6ae6d22 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 5
 PATCH 0
 PRERELEASE 4
-PRERELEASE_PATCH 8
+PRERELEASE_PATCH 9