Version 0.8.8.0 .

svn merge -r 29340:29512 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@29513 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 518e52e..04d6d01 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -3400,7 +3400,7 @@
           statistics.putCacheItem(dartEntry, DartEntry.PARSE_ERRORS);
           statistics.putCacheItem(dartEntry, DartEntry.PARSED_UNIT);
           statistics.putCacheItem(dartEntry, DartEntry.SOURCE_KIND);
-          statistics.putCacheItem(dartEntry, DartEntry.LINE_INFO);
+          statistics.putCacheItem(dartEntry, SourceEntry.LINE_INFO);
           if (identical(kind, SourceKind.LIBRARY)) {
             statistics.putCacheItem(dartEntry, DartEntry.ELEMENT);
             statistics.putCacheItem(dartEntry, DartEntry.EXPORTED_LIBRARIES);
@@ -4054,6 +4054,10 @@
   AnalysisTask get nextTaskAnalysisTask {
     {
       bool hintsEnabled = _options.hint;
+      if (_incrementalAnalysisCache != null) {
+        AnalysisTask task = new IncrementalAnalysisTask(this, _incrementalAnalysisCache);
+        _incrementalAnalysisCache = null;
+      }
       for (Source source in _priorityOrder) {
         AnalysisTask task = getNextTaskAnalysisTask2(source, _cache.get(source), true, hintsEnabled);
         if (task != null) {
@@ -4580,6 +4584,24 @@
   }
 
   /**
+   * Record the results produced by performing a [IncrementalAnalysisTask].
+   *
+   * @param task the task that was performed
+   * @return an entry containing the computed results
+   * @throws AnalysisException if the results could not be recorded
+   */
+  DartEntry recordIncrementalAnalysisTaskResults(IncrementalAnalysisTask task) {
+    {
+      CompilationUnit unit = task.compilationUnit;
+      if (unit != null) {
+        ChangeNoticeImpl notice = getNotice(task.source);
+        notice.compilationUnit = unit;
+      }
+    }
+    return null;
+  }
+
+  /**
    * Record the results produced by performing a [ParseDartTask]. If the results were computed
    * from data that is now out-of-date, then the results will not be recorded.
    *
@@ -5033,6 +5055,7 @@
   AnalysisContextImpl_AnalysisTaskResultRecorder(this.AnalysisContextImpl_this);
   SourceEntry visitGenerateDartErrorsTask(GenerateDartErrorsTask task) => AnalysisContextImpl_this.recordGenerateDartErrorsTask(task);
   SourceEntry visitGenerateDartHintsTask(GenerateDartHintsTask task) => AnalysisContextImpl_this.recordGenerateDartHintsTask(task);
+  SourceEntry visitIncrementalAnalysisTask(IncrementalAnalysisTask task) => AnalysisContextImpl_this.recordIncrementalAnalysisTaskResults(task);
   DartEntry visitParseDartTask(ParseDartTask task) => AnalysisContextImpl_this.recordParseDartTaskResults(task);
   HtmlEntry visitParseHtmlTask(ParseHtmlTask task) => AnalysisContextImpl_this.recordParseHtmlTaskResults(task);
   DartEntry visitResolveDartLibraryTask(ResolveDartLibraryTask task) => AnalysisContextImpl_this.recordResolveDartLibraryTaskResults(task);
@@ -6619,6 +6642,15 @@
   E visitGenerateDartHintsTask(GenerateDartHintsTask task);
 
   /**
+   * Visit an [IncrementalAnalysisTask].
+   *
+   * @param task the task to be visited
+   * @return the result of visiting the task
+   * @throws AnalysisException if the visitor throws an exception for some reason
+   */
+  E visitIncrementalAnalysisTask(IncrementalAnalysisTask incrementalAnalysisTask);
+
+  /**
    * Visit a [ParseDartTask].
    *
    * @param task the task to be visited
@@ -6802,6 +6834,46 @@
   TimestampedData<CompilationUnit> getCompilationUnit(Source unitSource) => context.internalResolveCompilationUnit(unitSource, libraryElement);
 }
 /**
+ * Instances of the class `IncrementalAnalysisTask` incrementally update existing analysis.
+ */
+class IncrementalAnalysisTask extends AnalysisTask {
+
+  /**
+   * The information used to perform incremental analysis.
+   */
+  IncrementalAnalysisCache _cache;
+
+  /**
+   * The compilation unit that was produced by incrementally updating the existing unit.
+   */
+  CompilationUnit compilationUnit;
+
+  /**
+   * Initialize a newly created task to perform analysis within the given context.
+   *
+   * @param context the context in which the task is to be performed
+   * @param cache the incremental analysis cache used to perform the analysis
+   */
+  IncrementalAnalysisTask(InternalAnalysisContext context, IncrementalAnalysisCache cache) : super(context) {
+    this._cache = cache;
+  }
+  accept(AnalysisTaskVisitor visitor) => visitor.visitIncrementalAnalysisTask(this);
+
+  /**
+   * Return the source that is to be incrementally analyzed.
+   *
+   * @return the source
+   */
+  Source get source => _cache != null ? _cache.source : null;
+  String get taskDescription => "incremental analysis ${(_cache != null ? _cache.source : "null")}";
+  void internalPerform() {
+    if (_cache == null) {
+      return;
+    }
+    compilationUnit = _cache.resolvedUnit;
+  }
+}
+/**
  * Instances of the class `ParseDartTask` parse a specific source as a Dart file.
  */
 class ParseDartTask extends AnalysisTask {
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 6fc95e0..c1c580a 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -1734,31 +1734,43 @@
    * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with the const modifier but
    * <i>k'</i> is not a constant constructor.
    */
-  static final CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR = new CompileTimeErrorCode.con1('REDIRECT_TO_NON_CONST_CONSTRUCTOR', 119, "Constant factory constructor cannot delegate to a non-constant constructor");
+  static final CompileTimeErrorCode REDIRECT_TO_MISSING_CONSTRUCTOR = new CompileTimeErrorCode.con1('REDIRECT_TO_MISSING_CONSTRUCTOR', 119, "The constructor '%s' could not be found in '%s'");
+
+  /**
+   * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with the const modifier but
+   * <i>k'</i> is not a constant constructor.
+   */
+  static final CompileTimeErrorCode REDIRECT_TO_NON_CLASS = new CompileTimeErrorCode.con1('REDIRECT_TO_NON_CLASS', 120, "The name '%s' is not a type and cannot be used in a redirected constructor");
+
+  /**
+   * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with the const modifier but
+   * <i>k'</i> is not a constant constructor.
+   */
+  static final CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR = new CompileTimeErrorCode.con1('REDIRECT_TO_NON_CONST_CONSTRUCTOR', 121, "Constant factory constructor cannot delegate to a non-constant constructor");
 
   /**
    * 13.3 Local Variable Declaration: It is a compile-time error if <i>e</i> refers to the name
    * <i>v</i> or the name <i>v=</i>.
    */
-  static final CompileTimeErrorCode REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode.con1('REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER', 120, "The name '%s' cannot be referenced in the initializer of a variable with the same name");
+  static final CompileTimeErrorCode REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode.con1('REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER', 122, "The name '%s' cannot be referenced in the initializer of a variable with the same name");
 
   /**
    * 5 Variables: A local variable may only be referenced at a source code location that is after
    * its initializer, if any, is complete, or a compile-time error occurs.
    */
-  static final CompileTimeErrorCode REFERENCED_BEFORE_DECLARATION = new CompileTimeErrorCode.con1('REFERENCED_BEFORE_DECLARATION', 121, "Local variables cannot be referenced before they are declared");
+  static final CompileTimeErrorCode REFERENCED_BEFORE_DECLARATION = new CompileTimeErrorCode.con1('REFERENCED_BEFORE_DECLARATION', 123, "Local variables cannot be referenced before they are declared");
 
   /**
    * 12.8.1 Rethrow: It is a compile-time error if an expression of the form <i>rethrow;</i> is not
    * enclosed within a on-catch clause.
    */
-  static final CompileTimeErrorCode RETHROW_OUTSIDE_CATCH = new CompileTimeErrorCode.con1('RETHROW_OUTSIDE_CATCH', 122, "rethrow must be inside of a catch clause");
+  static final CompileTimeErrorCode RETHROW_OUTSIDE_CATCH = new CompileTimeErrorCode.con1('RETHROW_OUTSIDE_CATCH', 124, "rethrow must be inside of a catch clause");
 
   /**
    * 13.11 Return: It is a compile-time error if a return statement of the form <i>return e;</i>
    * appears in a generative constructor.
    */
-  static final CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode.con1('RETURN_IN_GENERATIVE_CONSTRUCTOR', 123, "Constructors cannot return a value");
+  static final CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode.con1('RETURN_IN_GENERATIVE_CONSTRUCTOR', 125, "Constructors cannot return a value");
 
   /**
    * 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -1768,19 +1780,19 @@
    * initializer list, in class Object, in a factory constructor, or in a static method or variable
    * initializer.
    */
-  static final CompileTimeErrorCode SUPER_IN_INVALID_CONTEXT = new CompileTimeErrorCode.con1('SUPER_IN_INVALID_CONTEXT', 124, "Invalid context for 'super' invocation");
+  static final CompileTimeErrorCode SUPER_IN_INVALID_CONTEXT = new CompileTimeErrorCode.con1('SUPER_IN_INVALID_CONTEXT', 126, "Invalid context for 'super' invocation");
 
   /**
    * 7.6.1 Generative Constructors: A generative constructor may be redirecting, in which case its
    * only action is to invoke another generative constructor.
    */
-  static final CompileTimeErrorCode SUPER_IN_REDIRECTING_CONSTRUCTOR = new CompileTimeErrorCode.con1('SUPER_IN_REDIRECTING_CONSTRUCTOR', 125, "The redirecting constructor cannot have a 'super' initializer");
+  static final CompileTimeErrorCode SUPER_IN_REDIRECTING_CONSTRUCTOR = new CompileTimeErrorCode.con1('SUPER_IN_REDIRECTING_CONSTRUCTOR', 127, "The redirecting constructor cannot have a 'super' initializer");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile-time
    * error if a generative constructor of class Object includes a superinitializer.
    */
-  static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode.con1('SUPER_INITIALIZER_IN_OBJECT', 126, "");
+  static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode.con1('SUPER_INITIALIZER_IN_OBJECT', 128, "");
 
   /**
    * 12.11 Instance Creation: It is a static type warning if any of the type arguments to a
@@ -1799,19 +1811,19 @@
    * @param boundingTypeName the name of the bounding type
    * @see StaticTypeWarningCode#TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
    */
-  static final CompileTimeErrorCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new CompileTimeErrorCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 127, "'%s' does not extend '%s'");
+  static final CompileTimeErrorCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new CompileTimeErrorCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 129, "'%s' does not extend '%s'");
 
   /**
    * 15.3.1 Typedef: Any self reference, either directly, or recursively via another typedef, is a
    * compile time error.
    */
-  static final CompileTimeErrorCode TYPE_ALIAS_CANNOT_REFERENCE_ITSELF = new CompileTimeErrorCode.con1('TYPE_ALIAS_CANNOT_REFERENCE_ITSELF', 128, "Type alias cannot reference itself directly or recursively via another typedef");
+  static final CompileTimeErrorCode TYPE_ALIAS_CANNOT_REFERENCE_ITSELF = new CompileTimeErrorCode.con1('TYPE_ALIAS_CANNOT_REFERENCE_ITSELF', 130, "Type alias cannot reference itself directly or recursively via another typedef");
 
   /**
    * 12.11.2 Const: It is a compile-time error if <i>T</i> is not a class accessible in the current
    * scope, optionally followed by type arguments.
    */
-  static final CompileTimeErrorCode UNDEFINED_CLASS = new CompileTimeErrorCode.con1('UNDEFINED_CLASS', 129, "Undefined class '%s'");
+  static final CompileTimeErrorCode UNDEFINED_CLASS = new CompileTimeErrorCode.con1('UNDEFINED_CLASS', 131, "Undefined class '%s'");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1819,7 +1831,7 @@
    * a compile-time error if class <i>S</i> does not declare a generative constructor named <i>S</i>
    * (respectively <i>S.id</i>)
    */
-  static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 130, "The class '%s' does not have a generative constructor '%s'");
+  static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 132, "The class '%s' does not have a generative constructor '%s'");
 
   /**
    * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1827,7 +1839,7 @@
    * a compile-time error if class <i>S</i> does not declare a generative constructor named <i>S</i>
    * (respectively <i>S.id</i>)
    */
-  static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT', 131, "The class '%s' does not have a default generative constructor");
+  static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT', 133, "The class '%s' does not have a default generative constructor");
 
   /**
    * 12.14.3 Unqualified Invocation: If there exists a lexically visible declaration named
@@ -1837,7 +1849,7 @@
    *
    * @param methodName the name of the method that is undefined
    */
-  static final CompileTimeErrorCode UNDEFINED_FUNCTION = new CompileTimeErrorCode.con1('UNDEFINED_FUNCTION', 132, "The function '%s' is not defined");
+  static final CompileTimeErrorCode UNDEFINED_FUNCTION = new CompileTimeErrorCode.con1('UNDEFINED_FUNCTION', 134, "The function '%s' is not defined");
 
   /**
    * 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>, <i>1<=i<=l</i>,
@@ -1849,7 +1861,7 @@
    *
    * @param name the name of the requested named parameter
    */
-  static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode.con1('UNDEFINED_NAMED_PARAMETER', 133, "The named parameter '%s' is not defined");
+  static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode.con1('UNDEFINED_NAMED_PARAMETER', 135, "The named parameter '%s' is not defined");
 
   /**
    * 14.2 Exports: It is a compile-time error if the compilation unit found at the specified URI is
@@ -1864,7 +1876,7 @@
    * @param uri the URI pointing to a non-existent file
    * @see #INVALID_URI
    */
-  static final CompileTimeErrorCode URI_DOES_NOT_EXIST = new CompileTimeErrorCode.con1('URI_DOES_NOT_EXIST', 134, "Target of URI does not exist: '%s'");
+  static final CompileTimeErrorCode URI_DOES_NOT_EXIST = new CompileTimeErrorCode.con1('URI_DOES_NOT_EXIST', 136, "Target of URI does not exist: '%s'");
 
   /**
    * 14.1 Imports: It is a compile-time error if <i>x</i> is not a compile-time constant, or if
@@ -1876,7 +1888,7 @@
    * 14.5 URIs: It is a compile-time error if the string literal <i>x</i> that describes a URI is
    * not a compile-time constant, or if <i>x</i> involves string interpolation.
    */
-  static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode.con1('URI_WITH_INTERPOLATION', 135, "URIs cannot use string interpolation");
+  static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode.con1('URI_WITH_INTERPOLATION', 137, "URIs cannot use string interpolation");
 
   /**
    * 7.1.1 Operators: It is a compile-time error if the arity of the user-declared operator []= is
@@ -1889,7 +1901,7 @@
    * @param expectedNumberOfParameters the number of parameters expected
    * @param actualNumberOfParameters the number of parameters found in the operator declaration
    */
-  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 136, "Operator '%s' should declare exactly %d parameter(s), but %d found");
+  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 138, "Operator '%s' should declare exactly %d parameter(s), but %d found");
 
   /**
    * 7.1.1 Operators: It is a compile time error if the arity of the user-declared operator - is not
@@ -1897,13 +1909,13 @@
    *
    * @param actualNumberOfParameters the number of parameters found in the operator declaration
    */
-  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS', 137, "Operator '-' should declare 0 or 1 parameter, but %d found");
+  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS', 139, "Operator '-' should declare 0 or 1 parameter, but %d found");
 
   /**
    * 7.3 Setters: It is a compile-time error if a setter's formal parameter list does not include
    * exactly one required formal parameter <i>p</i>.
    */
-  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 138, "Setters should declare exactly one required parameter");
+  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 140, "Setters should declare exactly one required parameter");
   static final List<CompileTimeErrorCode> values = [
       AMBIGUOUS_EXPORT,
       ARGUMENT_DEFINITION_TEST_NON_PARAMETER,
@@ -2024,6 +2036,8 @@
       RECURSIVE_INTERFACE_INHERITANCE,
       RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS,
       RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS,
+      REDIRECT_TO_MISSING_CONSTRUCTOR,
+      REDIRECT_TO_NON_CLASS,
       REDIRECT_TO_NON_CONST_CONSTRUCTOR,
       REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER,
       REFERENCED_BEFORE_DECLARATION,
@@ -3234,7 +3248,7 @@
   static final StaticTypeWarningCode INVOCATION_OF_NON_FUNCTION_EXPRESSION = new StaticTypeWarningCode.con1('INVOCATION_OF_NON_FUNCTION_EXPRESSION', 7, "Cannot invoke a non-function");
 
   /**
-   * 12.19 Conditional: It is a static type warning if the type of <i>e<sub>1</sub></i> may not be
+   * 12.20 Conditional: It is a static type warning if the type of <i>e<sub>1</sub></i> may not be
    * assigned to bool.
    *
    * 13.5 If: It is a static type warning if the type of the expression <i>b</i> may not be assigned
@@ -3253,10 +3267,19 @@
   static final StaticTypeWarningCode NON_BOOL_EXPRESSION = new StaticTypeWarningCode.con1('NON_BOOL_EXPRESSION', 9, "Assertions must be on either a 'bool' or '() -> bool'");
 
   /**
+   * 12.28 Unary Expressions: The expression !<i>e</i> is equivalent to the expression
+   * <i>e</i>?<b>false<b> : <b>true</b>.
+   *
+   * 12.20 Conditional: It is a static type warning if the type of <i>e<sub>1</sub></i> may not be
+   * assigned to bool.
+   */
+  static final StaticTypeWarningCode NON_BOOL_NEGATION_EXPRESSION = new StaticTypeWarningCode.con1('NON_BOOL_NEGATION_EXPRESSION', 10, "Negation argument must have a static type of 'bool'");
+
+  /**
    * 15.8 Parameterized Types: It is a static type warning if <i>A<sub>i</sub>, 1 &lt;= i &lt;=
    * n</i> does not denote a type in the enclosing lexical scope.
    */
-  static final StaticTypeWarningCode NON_TYPE_AS_TYPE_ARGUMENT = new StaticTypeWarningCode.con1('NON_TYPE_AS_TYPE_ARGUMENT', 10, "The name '%s' is not a type and cannot be used as a parameterized type");
+  static final StaticTypeWarningCode NON_TYPE_AS_TYPE_ARGUMENT = new StaticTypeWarningCode.con1('NON_TYPE_AS_TYPE_ARGUMENT', 11, "The name '%s' is not a type and cannot be used as a parameterized type");
 
   /**
    * 13.11 Return: It is a static type warning if the type of <i>e</i> may not be assigned to the
@@ -3266,7 +3289,7 @@
    * @param expectedReturnType the expected return type as defined by the method
    * @param methodName the name of the method
    */
-  static final StaticTypeWarningCode RETURN_OF_INVALID_TYPE = new StaticTypeWarningCode.con1('RETURN_OF_INVALID_TYPE', 11, "The return type '%s' is not a '%s', as defined by the method '%s'");
+  static final StaticTypeWarningCode RETURN_OF_INVALID_TYPE = new StaticTypeWarningCode.con1('RETURN_OF_INVALID_TYPE', 12, "The return type '%s' is not a '%s', as defined by the method '%s'");
 
   /**
    * 12.11 Instance Creation: It is a static type warning if any of the type arguments to a
@@ -3290,7 +3313,7 @@
    * @param boundingTypeName the name of the bounding type
    * @see #TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND
    */
-  static final StaticTypeWarningCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new StaticTypeWarningCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 12, "'%s' does not extend '%s'");
+  static final StaticTypeWarningCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new StaticTypeWarningCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 13, "'%s' does not extend '%s'");
 
   /**
    * 10 Generics: It is a static type warning if a type parameter is a supertype of its upper bound.
@@ -3298,7 +3321,7 @@
    * @param typeParameterName the name of the type parameter
    * @see #TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
    */
-  static final StaticTypeWarningCode TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND = new StaticTypeWarningCode.con1('TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND', 13, "'%s' cannot be a supertype of its upper bound");
+  static final StaticTypeWarningCode TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND = new StaticTypeWarningCode.con1('TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND', 14, "'%s' cannot be a supertype of its upper bound");
 
   /**
    * 12.17 Getter Invocation: Let <i>T</i> be the static type of <i>e</i>. It is a static type
@@ -3307,7 +3330,7 @@
    * @param getterName the name of the getter
    * @param enclosingType the name of the enclosing type where the getter is being looked for
    */
-  static final StaticTypeWarningCode UNDEFINED_GETTER = new StaticTypeWarningCode.con1('UNDEFINED_GETTER', 14, "There is no such getter '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_GETTER = new StaticTypeWarningCode.con1('UNDEFINED_GETTER', 15, "There is no such getter '%s' in '%s'");
 
   /**
    * 12.15.1 Ordinary Invocation: Let <i>T</i> be the static type of <i>o</i>. It is a static type
@@ -3316,7 +3339,7 @@
    * @param methodName the name of the method that is undefined
    * @param typeName the resolved type name that the method lookup is happening on
    */
-  static final StaticTypeWarningCode UNDEFINED_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_METHOD', 15, "The method '%s' is not defined for the class '%s'");
+  static final StaticTypeWarningCode UNDEFINED_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_METHOD', 16, "The method '%s' is not defined for the class '%s'");
 
   /**
    * 12.18 Assignment: Evaluation of an assignment of the form
@@ -3334,7 +3357,7 @@
    * @param operator the name of the operator
    * @param enclosingType the name of the enclosing type where the operator is being looked for
    */
-  static final StaticTypeWarningCode UNDEFINED_OPERATOR = new StaticTypeWarningCode.con1('UNDEFINED_OPERATOR', 16, "There is no such operator '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_OPERATOR = new StaticTypeWarningCode.con1('UNDEFINED_OPERATOR', 17, "There is no such operator '%s' in '%s'");
 
   /**
    * 12.18 Assignment: Let <i>T</i> be the static type of <i>e<sub>1</sub></i>. It is a static type
@@ -3344,7 +3367,7 @@
    * @param enclosingType the name of the enclosing type where the setter is being looked for
    * @see #INACCESSIBLE_SETTER
    */
-  static final StaticTypeWarningCode UNDEFINED_SETTER = new StaticTypeWarningCode.con1('UNDEFINED_SETTER', 17, "There is no such setter '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_SETTER = new StaticTypeWarningCode.con1('UNDEFINED_SETTER', 18, "There is no such setter '%s' in '%s'");
 
   /**
    * 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -3355,7 +3378,7 @@
    * @param methodName the name of the method that is undefined
    * @param typeName the resolved type name that the method lookup is happening on
    */
-  static final StaticTypeWarningCode UNDEFINED_SUPER_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_SUPER_METHOD', 18, "There is no such method '%s' in '%s'");
+  static final StaticTypeWarningCode UNDEFINED_SUPER_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_SUPER_METHOD', 19, "There is no such method '%s' in '%s'");
 
   /**
    * 12.15.1 Ordinary Invocation: It is a static type warning if <i>T</i> does not have an
@@ -3365,7 +3388,7 @@
    * able to find the name defined in a supertype. It exists to provide a more informative error
    * message.
    */
-  static final StaticTypeWarningCode UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER = new StaticTypeWarningCode.con1('UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER', 19, "Static members from supertypes must be qualified by the name of the defining type");
+  static final StaticTypeWarningCode UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER = new StaticTypeWarningCode.con1('UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER', 20, "Static members from supertypes must be qualified by the name of the defining type");
 
   /**
    * 15.8 Parameterized Types: It is a static type warning if <i>G</i> is not a generic type with
@@ -3377,7 +3400,7 @@
    * @see CompileTimeErrorCode#CONST_WITH_INVALID_TYPE_PARAMETERS
    * @see CompileTimeErrorCode#NEW_WITH_INVALID_TYPE_PARAMETERS
    */
-  static final StaticTypeWarningCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new StaticTypeWarningCode.con1('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 20, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
+  static final StaticTypeWarningCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new StaticTypeWarningCode.con1('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 21, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
   static final List<StaticTypeWarningCode> values = [
       EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
       EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
@@ -3389,6 +3412,7 @@
       INVOCATION_OF_NON_FUNCTION_EXPRESSION,
       NON_BOOL_CONDITION,
       NON_BOOL_EXPRESSION,
+      NON_BOOL_NEGATION_EXPRESSION,
       NON_TYPE_AS_TYPE_ARGUMENT,
       RETURN_OF_INVALID_TYPE,
       TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index a0fedd3..bf066f2 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2939,6 +2939,11 @@
   ResolverVisitor _resolver;
 
   /**
+   * The element for the library containing the compilation unit being visited.
+   */
+  LibraryElement _definingLibrary;
+
+  /**
    * A flag indicating whether we are running in strict mode. In strict mode, error reporting is
    * based exclusively on the static type information.
    */
@@ -2988,7 +2993,8 @@
    */
   ElementResolver(ResolverVisitor resolver) {
     this._resolver = resolver;
-    AnalysisOptions options = resolver.definingLibrary.context.analysisOptions;
+    this._definingLibrary = resolver.definingLibrary;
+    AnalysisOptions options = _definingLibrary.context.analysisOptions;
     _strictMode = options.strictMode;
     _enableHints = options.hint;
     _dynamicType = resolver.typeProvider.dynamicType;
@@ -3085,7 +3091,7 @@
       }
       if (element == null) {
       } else {
-        if (element.library == null || element.library != _resolver.definingLibrary) {
+        if (element.library == null || element.library != _definingLibrary) {
         }
         simpleIdentifier.staticElement = element;
         if (node.newKeyword != null) {
@@ -3108,14 +3114,14 @@
       } else {
         if (element is PrefixElement) {
           prefix.staticElement = element;
-          element = _resolver.nameScope.lookup(identifier, _resolver.definingLibrary);
+          element = _resolver.nameScope.lookup(identifier, _definingLibrary);
           name.staticElement = element;
           return null;
         }
         LibraryElement library = element.library;
         if (library == null) {
           AnalysisEngine.instance.logger.logError("Found element with null library: ${element.name}");
-        } else if (library != _resolver.definingLibrary) {
+        } else if (library != _definingLibrary) {
         }
         name.staticElement = element;
         if (node.newKeyword == null) {
@@ -3196,11 +3202,10 @@
     ConstructorElement constructor;
     SimpleIdentifier name = node.name;
     InterfaceType interfaceType = type as InterfaceType;
-    LibraryElement definingLibrary = _resolver.definingLibrary;
     if (name == null) {
-      constructor = interfaceType.lookUpConstructor(null, definingLibrary);
+      constructor = interfaceType.lookUpConstructor(null, _definingLibrary);
     } else {
-      constructor = interfaceType.lookUpConstructor(name.name, definingLibrary);
+      constructor = interfaceType.lookUpConstructor(name.name, _definingLibrary);
       name.staticElement = constructor;
     }
     node.staticElement = constructor;
@@ -3274,7 +3279,7 @@
     SimpleIdentifier prefixNode = node.prefix;
     if (prefixNode != null) {
       String prefixName = prefixNode.name;
-      for (PrefixElement prefixElement in _resolver.definingLibrary.prefixes) {
+      for (PrefixElement prefixElement in _definingLibrary.prefixes) {
         if (prefixElement.displayName == prefixName) {
           prefixNode.staticElement = prefixElement;
           break;
@@ -3393,7 +3398,7 @@
           }
         }
         if (classElementContext != null) {
-          _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
+          _subtypeManager.ensureLibraryVisited(_definingLibrary);
           Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes(classElementContext);
           for (ClassElement subtypeElement in subtypeElements) {
             if (subtypeElement.getMethod(methodName.name) != null) {
@@ -3479,9 +3484,9 @@
     SimpleIdentifier identifier = node.identifier;
     Element prefixElement = prefix.staticElement;
     if (prefixElement is PrefixElement) {
-      Element element = _resolver.nameScope.lookup(node, _resolver.definingLibrary);
+      Element element = _resolver.nameScope.lookup(node, _definingLibrary);
       if (element == null && identifier.inSetterContext()) {
-        element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _resolver.definingLibrary);
+        element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _definingLibrary);
       }
       if (element == null) {
         if (identifier.inSetterContext()) {
@@ -3624,7 +3629,7 @@
     }
     SimpleIdentifier name = node.constructorName;
     String superName = name != null ? name.name : null;
-    ConstructorElement element = superType.lookUpConstructor(superName, _resolver.definingLibrary);
+    ConstructorElement element = superType.lookUpConstructor(superName, _definingLibrary);
     if (element == null) {
       if (name != null) {
         _resolver.reportError5(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, node, [superType.displayName, name]);
@@ -3807,7 +3812,7 @@
       if (getterType != null) {
         Type2 getterReturnType = getterType.returnType;
         if (getterReturnType is InterfaceType) {
-          MethodElement callMethod = ((getterReturnType as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
+          MethodElement callMethod = ((getterReturnType as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _definingLibrary);
           if (callMethod != null) {
             return resolveArgumentsToParameters(false, argumentList, callMethod);
           }
@@ -3828,7 +3833,7 @@
         List<ParameterElement> parameters = functionType.parameters;
         return resolveArgumentsToParameters2(false, argumentList, parameters);
       } else if (type is InterfaceType) {
-        MethodElement callMethod = ((type as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
+        MethodElement callMethod = ((type as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _definingLibrary);
         if (callMethod != null) {
           List<ParameterElement> parameters = callMethod.parameters;
           return resolveArgumentsToParameters2(false, argumentList, parameters);
@@ -3862,17 +3867,16 @@
   Element findImportWithoutPrefix(SimpleIdentifier identifier) {
     Element element = null;
     Scope nameScope = _resolver.nameScope;
-    LibraryElement definingLibrary = _resolver.definingLibrary;
-    for (ImportElement importElement in definingLibrary.imports) {
+    for (ImportElement importElement in _definingLibrary.imports) {
       PrefixElement prefixElement = importElement.prefix;
       if (prefixElement != null) {
         Identifier prefixedIdentifier = new ElementResolver_SyntheticIdentifier("${prefixElement.name}.${identifier.name}");
-        Element importedElement = nameScope.lookup(prefixedIdentifier, definingLibrary);
+        Element importedElement = nameScope.lookup(prefixedIdentifier, _definingLibrary);
         if (importedElement != null) {
           if (element == null) {
             element = importedElement;
           } else {
-            element = MultiplyDefinedElementImpl.fromElements(definingLibrary.context, element, importedElement);
+            element = MultiplyDefinedElementImpl.fromElements(_definingLibrary.context, element, importedElement);
           }
         }
       }
@@ -3951,7 +3955,7 @@
       return true;
     } else if (type is InterfaceType) {
       ClassElement classElement = ((type as InterfaceType)).element;
-      MethodElement methodElement = classElement.lookUpMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
+      MethodElement methodElement = classElement.lookUpMethod(CALL_METHOD_NAME, _definingLibrary);
       return methodElement != null;
     }
     return false;
@@ -4020,9 +4024,9 @@
       InterfaceType interfaceType = type as InterfaceType;
       PropertyAccessorElement accessor;
       if (target is SuperExpression) {
-        accessor = interfaceType.lookUpGetterInSuperclass(getterName, _resolver.definingLibrary);
+        accessor = interfaceType.lookUpGetterInSuperclass(getterName, _definingLibrary);
       } else {
-        accessor = interfaceType.lookUpGetter(getterName, _resolver.definingLibrary);
+        accessor = interfaceType.lookUpGetter(getterName, _definingLibrary);
       }
       if (accessor != null) {
         return accessor;
@@ -4052,7 +4056,7 @@
     javaSetAdd(visitedInterfaces, targetClass);
     if (includeTargetType) {
       PropertyAccessorElement getter = targetType.getGetter(getterName);
-      if (getter != null && getter.isAccessibleIn(_resolver.definingLibrary)) {
+      if (getter != null && getter.isAccessibleIn(_definingLibrary)) {
         return getter;
       }
     }
@@ -4088,11 +4092,11 @@
     type = resolveTypeParameter(type);
     if (type is InterfaceType) {
       InterfaceType interfaceType = type as InterfaceType;
-      ExecutableElement member = interfaceType.lookUpMethod(memberName, _resolver.definingLibrary);
+      ExecutableElement member = interfaceType.lookUpMethod(memberName, _definingLibrary);
       if (member != null) {
         return member;
       }
-      member = interfaceType.lookUpGetter(memberName, _resolver.definingLibrary);
+      member = interfaceType.lookUpGetter(memberName, _definingLibrary);
       if (member != null) {
         return member;
       }
@@ -4203,9 +4207,9 @@
       InterfaceType interfaceType = type as InterfaceType;
       MethodElement method;
       if (target is SuperExpression) {
-        method = interfaceType.lookUpMethodInSuperclass(methodName, _resolver.definingLibrary);
+        method = interfaceType.lookUpMethodInSuperclass(methodName, _definingLibrary);
       } else {
-        method = interfaceType.lookUpMethod(methodName, _resolver.definingLibrary);
+        method = interfaceType.lookUpMethod(methodName, _definingLibrary);
       }
       if (method != null) {
         return method;
@@ -4235,7 +4239,7 @@
     javaSetAdd(visitedInterfaces, targetClass);
     if (includeTargetType) {
       MethodElement method = targetType.getMethod(methodName);
-      if (method != null && method.isAccessibleIn(_resolver.definingLibrary)) {
+      if (method != null && method.isAccessibleIn(_definingLibrary)) {
         return method;
       }
     }
@@ -4273,9 +4277,9 @@
       InterfaceType interfaceType = type as InterfaceType;
       PropertyAccessorElement accessor;
       if (target is SuperExpression) {
-        accessor = interfaceType.lookUpSetterInSuperclass(setterName, _resolver.definingLibrary);
+        accessor = interfaceType.lookUpSetterInSuperclass(setterName, _definingLibrary);
       } else {
-        accessor = interfaceType.lookUpSetter(setterName, _resolver.definingLibrary);
+        accessor = interfaceType.lookUpSetter(setterName, _definingLibrary);
       }
       if (accessor != null) {
         return accessor;
@@ -4305,7 +4309,7 @@
     javaSetAdd(visitedInterfaces, targetClass);
     if (includeTargetType) {
       PropertyAccessorElement setter = targetType.getSetter(setterName);
-      if (setter != null && setter.isAccessibleIn(_resolver.definingLibrary)) {
+      if (setter != null && setter.isAccessibleIn(_definingLibrary)) {
         return setter;
       }
     }
@@ -4343,7 +4347,7 @@
    */
   bool memberFoundInSubclass(Element element, String memberName, bool asMethod, bool asAccessor) {
     if (element is ClassElement) {
-      _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
+      _subtypeManager.ensureLibraryVisited(_definingLibrary);
       Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes(element as ClassElement);
       for (ClassElement subtypeElement in subtypeElements) {
         if (asMethod && subtypeElement.getMethod(memberName) != null) {
@@ -4433,8 +4437,7 @@
       ConstructorElement constructor;
       {
         InterfaceType interfaceType = new InterfaceTypeImpl.con1(element as ClassElement);
-        LibraryElement definingLibrary = _resolver.definingLibrary;
-        constructor = interfaceType.lookUpConstructor(name, definingLibrary);
+        constructor = interfaceType.lookUpConstructor(name, _definingLibrary);
       }
       if (constructor == null) {
         _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotation, []);
@@ -4589,7 +4592,7 @@
       if (targetElement is PrefixElement) {
         String name = "${((target as SimpleIdentifier)).name}.${methodName}";
         Identifier functionName = new ElementResolver_SyntheticIdentifier(name);
-        Element element = _resolver.nameScope.lookup(functionName, _resolver.definingLibrary);
+        Element element = _resolver.nameScope.lookup(functionName, _definingLibrary);
         if (element != null) {
           return element;
         }
@@ -4608,7 +4611,7 @@
    * @return the element being invoked
    */
   Element resolveInvokedElement2(SimpleIdentifier methodName) {
-    Element element = _resolver.nameScope.lookup(methodName, _resolver.definingLibrary);
+    Element element = _resolver.nameScope.lookup(methodName, _definingLibrary);
     if (element == null) {
       ClassElement enclosingClass = _resolver.enclosingClass;
       if (enclosingClass != null) {
@@ -4706,7 +4709,7 @@
    * @return the element to which the identifier could be resolved
    */
   Element resolveSimpleIdentifier(SimpleIdentifier node) {
-    Element element = _resolver.nameScope.lookup(node, _resolver.definingLibrary);
+    Element element = _resolver.nameScope.lookup(node, _definingLibrary);
     if (element is PropertyAccessorElement && node.inSetterContext()) {
       PropertyInducingElement variable = ((element as PropertyAccessorElement)).variable;
       if (variable != null) {
@@ -4722,7 +4725,7 @@
         }
       }
     } else if (element == null && node.inSetterContext()) {
-      element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _resolver.definingLibrary);
+      element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _definingLibrary);
     }
     ClassElement enclosingClass = _resolver.enclosingClass;
     if (element == null && enclosingClass != null) {
@@ -5341,14 +5344,13 @@
    */
   void substituteTypeParametersDownHierarchy(InterfaceType superType, MemberMap map) {
     for (int i = 0; i < map.size; i++) {
-      String key = map.getKey(i);
       ExecutableElement executableElement = map.getValue(i);
       if (executableElement is MethodMember) {
         executableElement = MethodMember.from(executableElement as MethodMember, superType);
-        map.put(key, executableElement);
+        map.setValue(i, executableElement);
       } else if (executableElement is PropertyAccessorMember) {
         executableElement = PropertyAccessorMember.from(executableElement as PropertyAccessorMember, superType);
-        map.put(key, executableElement);
+        map.setValue(i, executableElement);
       }
     }
   }
@@ -6608,6 +6610,16 @@
   }
 
   /**
+   * Sets the ExecutableElement at the specified location.
+   *
+   * @param i some non-zero value less than size
+   * @param value the ExecutableElement value to store in the map
+   */
+  void setValue(int i, ExecutableElement value) {
+    _values[i] = value;
+  }
+
+  /**
    * Initializes [keys] and [values].
    */
   void initArrays(int initialCapacity) {
@@ -10823,6 +10835,7 @@
     }
     if (elementValid && element == null) {
       SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName);
+      RedirectingConstructorKind redirectingConstructorKind;
       if (isBuiltInIdentifier(node) && isTypeAnnotation(node)) {
         reportError5(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, typeName, [typeName.name]);
       } else if (typeNameSimple.name == "boolean") {
@@ -10833,8 +10846,9 @@
         reportError5(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
       } else if (isTypeNameInIsExpression(node)) {
         reportError5(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.name]);
-      } else if (isTypeNameTargetInRedirectedConstructor(node)) {
-        reportError5(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeName.name]);
+      } else if ((redirectingConstructorKind = getRedirectingConstructorKind(node)) != null) {
+        ErrorCode errorCode = (identical(redirectingConstructorKind, RedirectingConstructorKind.CONST) ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS : StaticWarningCode.REDIRECT_TO_NON_CLASS) as ErrorCode;
+        reportError5(errorCode, typeName, [typeName.name]);
       } else if (isTypeNameInTypeArgumentList(node)) {
         reportError5(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [typeName.name]);
       } else {
@@ -10871,14 +10885,16 @@
         node.type = type;
       }
     } else {
+      RedirectingConstructorKind redirectingConstructorKind;
       if (isTypeNameInCatchClause(node)) {
         reportError5(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [typeName.name]);
       } else if (isTypeNameInAsExpression(node)) {
         reportError5(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
       } else if (isTypeNameInIsExpression(node)) {
         reportError5(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.name]);
-      } else if (isTypeNameTargetInRedirectedConstructor(node)) {
-        reportError5(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeName.name]);
+      } else if ((redirectingConstructorKind = getRedirectingConstructorKind(node)) != null) {
+        ErrorCode errorCode = (identical(redirectingConstructorKind, RedirectingConstructorKind.CONST) ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS : StaticWarningCode.REDIRECT_TO_NON_CLASS) as ErrorCode;
+        reportError5(errorCode, typeName, [typeName.name]);
       } else if (isTypeNameInTypeArgumentList(node)) {
         reportError5(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [typeName.name]);
       } else {
@@ -11058,6 +11074,31 @@
   }
 
   /**
+   * Checks if the given type name is the target in a redirected constructor.
+   *
+   * @param typeName the type name to analyze
+   * @return some [RedirectingConstructorKind] if the given type name is used as the type in a
+   *         redirected constructor, or `null` otherwise
+   */
+  RedirectingConstructorKind getRedirectingConstructorKind(TypeName typeName) {
+    ASTNode parent = typeName.parent;
+    if (parent is ConstructorName) {
+      ConstructorName constructorName = parent as ConstructorName;
+      parent = constructorName.parent;
+      if (parent is ConstructorDeclaration) {
+        ConstructorDeclaration constructorDeclaration = parent as ConstructorDeclaration;
+        if (identical(constructorDeclaration.redirectedConstructor, constructorName)) {
+          if (constructorDeclaration.constKeyword != null) {
+            return RedirectingConstructorKind.CONST;
+          }
+          return RedirectingConstructorKind.NORMAL;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
    * Given the multiple elements to which a single name could potentially be resolved, return the
    * single interface type that should be used, or `null` if there is no clear choice.
    *
@@ -11190,25 +11231,6 @@
   bool isTypeNameInTypeArgumentList(TypeName typeName) => typeName.parent is TypeArgumentList;
 
   /**
-   * Checks if the given type name is the target in a redirected constructor.
-   *
-   * @param typeName the type name to analyzer
-   * @return `true` if the given type name is used as the type in a redirected constructor
-   */
-  bool isTypeNameTargetInRedirectedConstructor(TypeName typeName) {
-    ASTNode parent = typeName.parent;
-    if (parent is ConstructorName) {
-      ConstructorName constructorName = parent as ConstructorName;
-      parent = constructorName.parent;
-      if (parent is ConstructorDeclaration) {
-        ConstructorDeclaration constructorDeclaration = parent as ConstructorDeclaration;
-        return constructorName == constructorDeclaration.redirectedConstructor;
-      }
-    }
-    return false;
-  }
-
-  /**
    * Record that the static type of the given node is the given type.
    *
    * @param expression the node whose type is to be recorded
@@ -11362,6 +11384,15 @@
   }
 }
 /**
+ * Kind of the redirecting constructor.
+ */
+class RedirectingConstructorKind extends Enum<RedirectingConstructorKind> {
+  static final RedirectingConstructorKind CONST = new RedirectingConstructorKind('CONST', 0);
+  static final RedirectingConstructorKind NORMAL = new RedirectingConstructorKind('NORMAL', 1);
+  static final List<RedirectingConstructorKind> values = [CONST, NORMAL];
+  RedirectingConstructorKind(String name, int ordinal) : super(name, ordinal);
+}
+/**
  * Instances of the class `VariableResolverVisitor` are used to resolve
  * [SimpleIdentifier]s to local variables and formal parameters.
  *
@@ -12739,6 +12770,11 @@
   Type2 _dynamicType;
 
   /**
+   * The type representing the type 'bool'.
+   */
+  InterfaceType _boolType;
+
+  /**
    * The object providing access to the types defined by the language.
    */
   TypeProvider _typeProvider;
@@ -12909,13 +12945,14 @@
     _isInInstanceVariableInitializer = false;
     _isInConstructorInitializer = false;
     _isInStaticMethod = false;
+    _boolType = typeProvider.boolType;
     _dynamicType = typeProvider.dynamicType;
     _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = <InterfaceType> [
         typeProvider.nullType,
         typeProvider.numType,
         typeProvider.intType,
         typeProvider.doubleType,
-        typeProvider.boolType,
+        _boolType,
         typeProvider.stringType];
   }
   Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
@@ -13305,10 +13342,14 @@
     return super.visitPrefixedIdentifier(node);
   }
   Object visitPrefixExpression(PrefixExpression node) {
-    if (node.operator.type.isIncrementOperator) {
-      checkForAssignmentToFinal2(node.operand);
+    sc.TokenType operatorType = node.operator.type;
+    Expression operand = node.operand;
+    if (identical(operatorType, sc.TokenType.BANG)) {
+      checkForNonBoolNegationExpression(operand);
+    } else if (operatorType.isIncrementOperator) {
+      checkForAssignmentToFinal2(operand);
     }
-    checkForIntNotAssignable(node.operand);
+    checkForIntNotAssignable(operand);
     return super.visitPrefixExpression(node);
   }
   Object visitPropertyAccess(PropertyAccess node) {
@@ -13872,7 +13913,8 @@
         if (redirectedConstructor.name != null) {
           constructorStrName += ".${redirectedConstructor.name.name}";
         }
-        _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR, redirectedConstructor, [constructorStrName, redirectedType.displayName]);
+        ErrorCode errorCode = (node.constKeyword != null ? CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR : StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR) as ErrorCode;
+        _errorReporter.reportError2(errorCode, redirectedConstructor, [constructorStrName, redirectedType.displayName]);
         return true;
       }
       return false;
@@ -15879,7 +15921,7 @@
    */
   bool checkForNonBoolCondition(Expression condition) {
     Type2 conditionType = getStaticType(condition);
-    if (conditionType != null && !conditionType.isAssignableTo(_typeProvider.boolType)) {
+    if (conditionType != null && !conditionType.isAssignableTo(_boolType)) {
       _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_CONDITION, condition, []);
       return true;
     }
@@ -15897,13 +15939,13 @@
     Expression expression = node.condition;
     Type2 type = getStaticType(expression);
     if (type is InterfaceType) {
-      if (!type.isAssignableTo(_typeProvider.boolType)) {
+      if (!type.isAssignableTo(_boolType)) {
         _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression, []);
         return true;
       }
     } else if (type is FunctionType) {
       FunctionType functionType = type as FunctionType;
-      if (functionType.typeArguments.length == 0 && !functionType.returnType.isAssignableTo(_typeProvider.boolType)) {
+      if (functionType.typeArguments.length == 0 && !functionType.returnType.isAssignableTo(_boolType)) {
         _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression, []);
         return true;
       }
@@ -15912,6 +15954,22 @@
   }
 
   /**
+   * Checks to ensure that the given expression is assignable to bool.
+   *
+   * @param expression the expression expression to test
+   * @return `true` if and only if an error code is generated on the passed node
+   * @see StaticTypeWarningCode#NON_BOOL_NEGATION_EXPRESSION
+   */
+  bool checkForNonBoolNegationExpression(Expression expression) {
+    Type2 conditionType = getStaticType(expression);
+    if (conditionType != null && !conditionType.isAssignableTo(_boolType)) {
+      _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression, []);
+      return true;
+    }
+    return false;
+  }
+
+  /**
    * This verifies the passed map literal either:
    *
    * * has `const modifier`
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index a9cfe4d..1df9ef8 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.9.0
+version: 0.9.1
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 4a0fb46b..ec6d987 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -2557,6 +2557,18 @@
     assertNoErrors(source);
     verify([source]);
   }
+  void test_nonBoolNegationExpression() {
+    Source source = addSource(EngineTestCase.createSource([
+        "f(bool pb, pd) {",
+        "  !true;",
+        "  !false;",
+        "  !pb;",
+        "  !pd;",
+        "}"]));
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
   void test_nonConstantDefaultValue_function_named() {
     Source source = addSource(EngineTestCase.createSource(["f({x : 2 + 3}) {}"]));
     resolve(source);
@@ -4367,6 +4379,10 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
       });
+      _ut.test('test_nonBoolNegationExpression', () {
+        final __test = new NonErrorResolverTest();
+        runJUnitTest(__test, __test.test_nonBoolNegationExpression);
+      });
       _ut.test('test_nonConstCaseExpression', () {
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_nonConstCaseExpression);
@@ -5201,6 +5217,12 @@
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
     verify([source]);
   }
+  void test_nonBoolNegationExpression() {
+    Source source = addSource(EngineTestCase.createSource(["f() {", "  !42;", "}"]));
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION]);
+    verify([source]);
+  }
   void test_nonTypeAsTypeArgument_notAType() {
     Source source = addSource(EngineTestCase.createSource(["int A;", "class B<E> {}", "f(B<A> b) {}"]));
     resolve(source);
@@ -5875,6 +5897,10 @@
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
       });
+      _ut.test('test_nonBoolNegationExpression', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_nonBoolNegationExpression);
+      });
       _ut.test('test_nonTypeAsTypeArgument_notAType', () {
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_nonTypeAsTypeArgument_notAType);
@@ -10493,6 +10519,40 @@
     assertErrors(source, [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]);
     verify([source]);
   }
+  void test_redirectToMissingConstructor_named() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A implements B{",
+        "  A() {}",
+        "}",
+        "class B {",
+        "  const factory B() = A.name;",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
+  }
+  void test_redirectToMissingConstructor_unnamed() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A implements B{",
+        "  A.name() {}",
+        "}",
+        "class B {",
+        "  const factory B() = A;",
+        "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
+  }
+  void test_redirectToNonClass_notAType() {
+    Source source = addSource(EngineTestCase.createSource(["int A;", "class B {", "  const factory B() = A;", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
+    verify([source]);
+  }
+  void test_redirectToNonClass_undefinedIdentifier() {
+    Source source = addSource(EngineTestCase.createSource(["class B {", "  const factory B() = A;", "}"]));
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
+    verify([source]);
+  }
   void test_redirectToNonConstConstructor() {
     Source source = addSource(EngineTestCase.createSource([
         "class A {",
@@ -12038,6 +12098,22 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_recursiveInterfaceInheritance_tail3);
       });
+      _ut.test('test_redirectToMissingConstructor_named', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_redirectToMissingConstructor_named);
+      });
+      _ut.test('test_redirectToMissingConstructor_unnamed', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_redirectToMissingConstructor_unnamed);
+      });
+      _ut.test('test_redirectToNonClass_notAType', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_redirectToNonClass_notAType);
+      });
+      _ut.test('test_redirectToNonClass_undefinedIdentifier', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_redirectToNonClass_undefinedIdentifier);
+      });
       _ut.test('test_redirectToNonConstConstructor', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_redirectToNonConstConstructor);
diff --git a/pkg/barback/lib/barback.dart b/pkg/barback/lib/barback.dart
index d6dfccf..37c1506 100644
--- a/pkg/barback/lib/barback.dart
+++ b/pkg/barback/lib/barback.dart
@@ -8,9 +8,9 @@
 export 'src/asset_id.dart';
 export 'src/asset_set.dart';
 export 'src/barback.dart';
-export 'src/barback_logger.dart';
 export 'src/build_result.dart';
 export 'src/errors.dart' hide flattenAggregateExceptions;
+export 'src/log.dart';
 export 'src/package_provider.dart';
 export 'src/transform.dart' show Transform;
 export 'src/transform_logger.dart';
diff --git a/pkg/barback/lib/src/asset_cascade.dart b/pkg/barback/lib/src/asset_cascade.dart
index 9857c80..cc90560 100644
--- a/pkg/barback/lib/src/asset_cascade.dart
+++ b/pkg/barback/lib/src/asset_cascade.dart
@@ -11,7 +11,7 @@
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
-import 'barback_logger.dart';
+import 'log.dart';
 import 'build_result.dart';
 import 'cancelable_future.dart';
 import 'errors.dart';
@@ -85,7 +85,7 @@
   /// A controller whose stream feeds into [_onDirtyPool].
   final _onDirtyController = new StreamController.broadcast(sync: true);
 
-  /// A stream that emits an event whenever any transforms in this cascade log
+  /// A stream that emits an event whenever any transforms in this cascade logs
   /// an entry.
   Stream<LogEntry> get onLog => _onLogPool.stream;
   final _onLogPool = new StreamPool<LogEntry>.broadcast();
diff --git a/pkg/barback/lib/src/barback.dart b/pkg/barback/lib/src/barback.dart
index 932077e..1027369 100644
--- a/pkg/barback/lib/src/barback.dart
+++ b/pkg/barback/lib/src/barback.dart
@@ -9,7 +9,7 @@
 import 'asset.dart';
 import 'asset_id.dart';
 import 'asset_set.dart';
-import 'barback_logger.dart';
+import 'log.dart';
 import 'build_result.dart';
 import 'errors.dart';
 import 'package_graph.dart';
@@ -65,8 +65,14 @@
   /// emitted through the [results] stream's error channel.
   Stream get errors => _graph.errors;
 
-  Barback(PackageProvider provider, {BarbackLogger logger})
-      : _graph = new PackageGraph(provider, logger: logger);
+  /// The stream of [LogEntry] objects used to report transformer log entries.
+  ///
+  /// If this stream has listeners, then log entries will go to that.
+  /// Otherwise, a default logger will display them.
+  Stream<LogEntry> get log => _graph.log;
+
+  Barback(PackageProvider provider)
+      : _graph = new PackageGraph(provider);
 
   /// Gets the asset identified by [id].
   ///
diff --git a/pkg/barback/lib/src/build_result.dart b/pkg/barback/lib/src/build_result.dart
index 00c702c..65e8269 100644
--- a/pkg/barback/lib/src/build_result.dart
+++ b/pkg/barback/lib/src/build_result.dart
@@ -8,7 +8,6 @@
 
 import 'package:stack_trace/stack_trace.dart';
 
-import 'barback_logger.dart';
 import 'errors.dart';
 import 'utils.dart';
 
diff --git a/pkg/barback/lib/src/file_pool.dart b/pkg/barback/lib/src/file_pool.dart
index 7e95c68..ace7ae4 100644
--- a/pkg/barback/lib/src/file_pool.dart
+++ b/pkg/barback/lib/src/file_pool.dart
@@ -5,7 +5,6 @@
 library barback.file_pool;
 
 import 'dart:async';
-import 'dart:collection';
 import 'dart:convert';
 import 'dart:io';
 
diff --git a/pkg/barback/lib/src/group_runner.dart b/pkg/barback/lib/src/group_runner.dart
index dc7b4b4..4718d18 100644
--- a/pkg/barback/lib/src/group_runner.dart
+++ b/pkg/barback/lib/src/group_runner.dart
@@ -8,7 +8,7 @@
 
 import 'asset_cascade.dart';
 import 'asset_node.dart';
-import 'barback_logger.dart';
+import 'log.dart';
 import 'phase.dart';
 import 'stream_pool.dart';
 import 'transformer_group.dart';
@@ -32,8 +32,8 @@
   /// Whether this group is dirty and needs to be run.
   bool get isDirty => _phases.any((phase) => phase.isDirty);
 
-  /// A stream that emits an event whenever any transforms in this group log an
-  /// entry.
+  /// A stream that emits an event whenever any transforms in this group logs
+  /// an entry.
   Stream<LogEntry> get onLog => _onLogPool.stream;
   final _onLogPool = new StreamPool<LogEntry>.broadcast();
 
diff --git a/pkg/barback/lib/src/barback_logger.dart b/pkg/barback/lib/src/log.dart
similarity index 61%
rename from pkg/barback/lib/src/barback_logger.dart
rename to pkg/barback/lib/src/log.dart
index c343c59..809d8a9 100644
--- a/pkg/barback/lib/src/barback_logger.dart
+++ b/pkg/barback/lib/src/log.dart
@@ -2,32 +2,13 @@
 // 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.
 
-library barback.barback_logger;
+library barback.log;
 
 import 'package:source_maps/span.dart';
 
 import 'asset_id.dart';
 import 'errors.dart';
 
-/// Object used to report warnings and errors encountered while running a
-/// transformer.
-class BarbackLogger {
-  /// Logs [entry].
-  void logEntry(LogEntry entry) {
-    var buffer = new StringBuffer();
-    buffer.write("[${entry.level} ${entry.transform}] ");
-
-    var message = entry.message;
-    if (entry.span == null) {
-      buffer.write(entry.span.getLocationMessage(entry.message));
-    } else {
-      buffer.write(message);
-    }
-
-    print(buffer);
-  }
-}
-
 /// The severity of a logged message.
 class LogLevel {
   static const INFO = const LogLevel("Info");
@@ -46,7 +27,7 @@
   final TransformInfo transform;
 
   /// The asset that the message is associated with.
-  final AssetId asset;
+  final AssetId assetId;
 
   final LogLevel level;
   final String message;
@@ -55,5 +36,5 @@
   /// a source [Span].
   final Span span;
 
-  LogEntry(this.transform, this.asset, this.level, this.message, this.span);
+  LogEntry(this.transform, this.assetId, this.level, this.message, this.span);
 }
diff --git a/pkg/barback/lib/src/package_graph.dart b/pkg/barback/lib/src/package_graph.dart
index dcc3d7f..95ecbb1 100644
--- a/pkg/barback/lib/src/package_graph.dart
+++ b/pkg/barback/lib/src/package_graph.dart
@@ -10,9 +10,9 @@
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
-import 'barback_logger.dart';
 import 'build_result.dart';
 import 'errors.dart';
+import 'log.dart';
 import 'package_provider.dart';
 import 'pool.dart';
 import 'transformer.dart';
@@ -26,10 +26,6 @@
   /// The provider that exposes asset and package information.
   final PackageProvider provider;
 
-  /// The logger used to report transformer log entries. If this is null, then
-  /// [_defaultLogger] will be used instead.
-  final BarbackLogger _logger;
-
   /// The [AssetCascade] for each package.
   final _cascades = <String, AssetCascade>{};
 
@@ -60,6 +56,10 @@
   Stream<BarbackException> get errors => _errors;
   Stream<BarbackException> _errors;
 
+  /// The stream of [LogEntry] objects used to report transformer log entries.
+  Stream<LogEntry> get log => _logController.stream;
+  final _logController = new StreamController<LogEntry>.broadcast();
+
   /// The most recent error emitted from a cascade's result stream.
   ///
   /// This is used to pipe an unexpected error from a build to the resulting
@@ -75,8 +75,7 @@
 
   /// Creates a new [PackageGraph] that will transform assets in all packages
   /// made available by [provider].
-  PackageGraph(this.provider, {BarbackLogger logger})
-      : _logger = logger != null ? logger : new BarbackLogger() {
+  PackageGraph(this.provider) {
     for (var package in provider.packages) {
       var cascade = new AssetCascade(this, package);
       // The initial result for each cascade is "success" since the cascade
@@ -87,7 +86,23 @@
         _cascadeResults[package] = null;
       });
 
-      cascade.onLog.listen(_logger.logEntry);
+      cascade.onLog.listen((entry) {
+        if (_logController.hasListener) {
+          _logController.add(entry);
+        } else {
+          // No listeners, so just print entry.
+          var buffer = new StringBuffer();
+          buffer.write("[${entry.level} ${entry.transform}] ");
+
+          if (entry.span != null) {
+            buffer.write(entry.span.getLocationMessage(entry.message));
+          } else {
+            buffer.write(entry.message);
+          }
+
+          print(buffer);
+        }
+      });
 
       cascade.results.listen((result) {
         _cascadeResults[cascade.package] = result;
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index 8680e60..d712354 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -5,15 +5,12 @@
 library barback.phase;
 
 import 'dart:async';
-import 'dart:collection';
 
 import 'asset_cascade.dart';
 import 'asset_id.dart';
 import 'asset_node.dart';
-import 'asset_set.dart';
-import 'barback_logger.dart';
 import 'group_runner.dart';
-import 'errors.dart';
+import 'log.dart';
 import 'multiset.dart';
 import 'phase_forwarder.dart';
 import 'phase_input.dart';
@@ -92,8 +89,8 @@
   bool get isDirty => _inputs.values.any((input) => input.isDirty) ||
       _groups.values.any((group) => group.isDirty);
 
-  /// A stream that emits an event whenever any transforms in this phase log an
-  /// entry.
+  /// A stream that emits an event whenever any transforms in this phase logs
+  /// an entry.
   Stream<LogEntry> get onLog => _onLogPool.stream;
   final _onLogPool = new StreamPool<LogEntry>.broadcast();
 
diff --git a/pkg/barback/lib/src/phase_forwarder.dart b/pkg/barback/lib/src/phase_forwarder.dart
index 90831f7e..c1f7abd 100644
--- a/pkg/barback/lib/src/phase_forwarder.dart
+++ b/pkg/barback/lib/src/phase_forwarder.dart
@@ -7,8 +7,6 @@
 import 'dart:async';
 
 import 'asset_node.dart';
-import 'asset_forwarder.dart';
-import 'phase_output.dart';
 
 /// A class that takes care of forwarding assets within a phase.
 ///
diff --git a/pkg/barback/lib/src/phase_input.dart b/pkg/barback/lib/src/phase_input.dart
index 1b96ee0..240fb03 100644
--- a/pkg/barback/lib/src/phase_input.dart
+++ b/pkg/barback/lib/src/phase_input.dart
@@ -10,8 +10,8 @@
 import 'asset.dart';
 import 'asset_forwarder.dart';
 import 'asset_node.dart';
-import 'barback_logger.dart';
 import 'errors.dart';
+import 'log.dart';
 import 'phase.dart';
 import 'stream_pool.dart';
 import 'transform_node.dart';
diff --git a/pkg/barback/lib/src/pool.dart b/pkg/barback/lib/src/pool.dart
index 8da8434..3224fbe 100644
--- a/pkg/barback/lib/src/pool.dart
+++ b/pkg/barback/lib/src/pool.dart
@@ -1,3 +1,9 @@
+// Copyright (c) 2013, 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.
+
+library barback.pool;
+
 import 'dart:async';
 import 'dart:collection';
 
diff --git a/pkg/barback/lib/src/stream_replayer.dart b/pkg/barback/lib/src/stream_replayer.dart
index bb04007..705f97a 100644
--- a/pkg/barback/lib/src/stream_replayer.dart
+++ b/pkg/barback/lib/src/stream_replayer.dart
@@ -11,10 +11,16 @@
 
 /// Records the values and errors that are sent through a stream and allows them
 /// to be replayed arbitrarily many times.
+///
+/// This only listens to the wrapped stream when a replayed stream gets a
+/// listener.
 class StreamReplayer<T> {
   /// The wrapped stream.
   final Stream<T> _stream;
 
+  /// Whether or not [this] has started listening to [_stream].
+  bool _isSubscribed = false;
+
   /// Whether or not [_stream] has been closed.
   bool _isClosed = false;
 
@@ -28,7 +34,32 @@
   /// The controllers that are listening for future events from [_stream].
   final _controllers = new Set<StreamController<T>>();
 
-  StreamReplayer(this._stream) {
+  StreamReplayer(this._stream);
+
+  /// Returns a stream that replays the values and errors of the input stream.
+  ///
+  /// This stream is a buffered stream.
+  Stream<T> getReplay() {
+    var controller = new StreamController<T>(onListen: _subscribe);
+
+    for (var eventOrError in _buffer) {
+      eventOrError.match(controller.add, (pair) {
+        controller.addError(pair.first, pair.second);
+      });
+    }
+    if (_isClosed) {
+      controller.close();
+    } else {
+      _controllers.add(controller);
+    }
+    return controller.stream;
+  }
+
+  /// Subscribe to [_stream] if we haven't yet done so.
+  void _subscribe() {
+    if (_isSubscribed || _isClosed) return;
+    _isSubscribed = true;
+
     _stream.listen((data) {
       _buffer.add(new Either<T, dynamic>.withFirst(data));
       for (var controller in _controllers) {
@@ -48,23 +79,4 @@
       _controllers.clear();
     });
   }
-
-  /// Returns a stream that replays the values and errors of the input stream.
-  ///
-  /// This stream is a buffered stream regardless of whether the input stream
-  /// was broadcast or buffered.
-  Stream<T> getReplay() {
-    var controller = new StreamController<T>();
-    for (var eventOrError in _buffer) {
-      eventOrError.match(controller.add, (pair) {
-        controller.addError(pair.first, pair.second);
-      });
-    }
-    if (_isClosed) {
-      controller.close();
-    } else {
-      _controllers.add(controller);
-    }
-    return controller.stream;
-  }
 }
diff --git a/pkg/barback/lib/src/transform.dart b/pkg/barback/lib/src/transform.dart
index fa1df82..7f0d217 100644
--- a/pkg/barback/lib/src/transform.dart
+++ b/pkg/barback/lib/src/transform.dart
@@ -13,8 +13,8 @@
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
-import 'barback_logger.dart';
 import 'errors.dart';
+import 'log.dart';
 import 'transform_logger.dart';
 import 'transform_node.dart';
 import 'utils.dart';
diff --git a/pkg/barback/lib/src/transform_logger.dart b/pkg/barback/lib/src/transform_logger.dart
index d046460..6067b36 100644
--- a/pkg/barback/lib/src/transform_logger.dart
+++ b/pkg/barback/lib/src/transform_logger.dart
@@ -7,7 +7,7 @@
 import 'package:source_maps/span.dart';
 
 import 'asset_id.dart';
-import 'barback_logger.dart';
+import 'log.dart';
 import 'transform.dart';
 
 /// Object used to report warnings and errors encountered while running a
@@ -19,8 +19,8 @@
 
   /// Logs an informative message.
   ///
-  /// If [asset] is provided, the log entry is associated with that asset,
-  /// otherwise it's associated with the primary input of [transformer].
+  /// If [asset] is provided, the log entry is associated with that asset.
+  /// Otherwise it's associated with the primary input of [transformer].
   /// If [span] is provided, indicates the location in the input asset that
   /// caused the message.
   void info(String message, {AssetId asset, Span span}) {
@@ -29,8 +29,8 @@
 
   /// Logs a warning message.
   ///
-  /// If [asset] is provided, the log entry is associated with that asset,
-  /// otherwise it's associated with the primary input of [transformer].
+  /// If [asset] is provided, the log entry is associated with that asset.
+  /// Otherwise it's associated with the primary input of [transformer].
   /// If present, [span] indicates the location in the input asset that caused
   /// the warning.
   void warning(String message, {AssetId asset, Span span}) {
@@ -39,8 +39,8 @@
 
   /// Logs an error message.
   ///
-  /// If [asset] is provided, the log entry is associated with that asset,
-  /// otherwise it's associated with the primary input of [transformer].
+  /// If [asset] is provided, the log entry is associated with that asset.
+  /// Otherwise it's associated with the primary input of [transformer].
   /// If present, [span] indicates the location in the input asset that caused
   /// the error.
   // TODO(sigmund,nweiz): clarify when an error should be logged or thrown.
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index aa77d72..1ef1919 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -12,8 +12,8 @@
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
-import 'barback_logger.dart';
 import 'errors.dart';
+import 'log.dart';
 import 'phase.dart';
 import 'transform.dart';
 import 'transformer.dart';
@@ -218,7 +218,6 @@
   void _log(AssetId asset, LogLevel level, String message, Span span) {
     // If the log isn't already associated with an asset, use the primary.
     if (asset == null) asset = primary.id;
-    var info = new TransformInfo(transformer, primary.id);
     var entry = new LogEntry(info, asset, level, message, span);
     _onLogController.add(entry);
   }
diff --git a/pkg/barback/lib/src/transformer_group.dart b/pkg/barback/lib/src/transformer_group.dart
index f6bf2b8..49359c9 100644
--- a/pkg/barback/lib/src/transformer_group.dart
+++ b/pkg/barback/lib/src/transformer_group.dart
@@ -4,8 +4,6 @@
 
 library barback.transformer_group;
 
-import 'dart:async';
-
 /// A [TransformerGroup] encapsulates a phased collection of transformers.
 ///
 /// A transformer group is defined like a collection of phases, such as you
diff --git a/pkg/barback/lib/src/utils.dart b/pkg/barback/lib/src/utils.dart
index a925bec..22203b4 100644
--- a/pkg/barback/lib/src/utils.dart
+++ b/pkg/barback/lib/src/utils.dart
@@ -5,7 +5,6 @@
 library barback.utils;
 
 import 'dart:async';
-import 'dart:io';
 
 /// A pair of values.
 class Pair<E, F> {
diff --git a/pkg/barback/test/stream_replayer_test.dart b/pkg/barback/test/stream_replayer_test.dart
index f341a29..9bc8224 100644
--- a/pkg/barback/test/stream_replayer_test.dart
+++ b/pkg/barback/test/stream_replayer_test.dart
@@ -76,4 +76,26 @@
       expect(isClosed, isTrue);
     }), completes);
   });
+
+  test("the wrapped stream isn't opened if there are no replays", () {
+    var isOpened = false;
+    var controller = new StreamController<int>(onListen: () {
+      isOpened = true;
+    });
+    var replayer = new StreamReplayer<int>(controller.stream);
+
+    expect(pumpEventQueue().then((_) => isOpened), completion(isFalse));
+  });
+
+  test("the wrapped stream isn't opened if no replays are opened", () {
+    var isOpened = false;
+    var controller = new StreamController<int>(onListen: () {
+      isOpened = true;
+    });
+    var replayer = new StreamReplayer<int>(controller.stream);
+    replayer.getReplay();
+    replayer.getReplay();
+
+    expect(pumpEventQueue().then((_) => isOpened), completion(isFalse));
+  });
 }
diff --git a/pkg/custom_element/test/analyzer_test.dart b/pkg/custom_element/test/analyzer_test.dart
index 1ac251b..0cbe620 100644
--- a/pkg/custom_element/test/analyzer_test.dart
+++ b/pkg/custom_element/test/analyzer_test.dart
@@ -6,8 +6,6 @@
 
 import 'package:custom_element/custom_element.dart';
 
-// @static-clean
-
 // This test ensures CustomElement compiles without errors.
 void main() {
 }
diff --git a/pkg/docgen/README.md b/pkg/docgen/README.md
index 66d0a46..343d9c0 100644
--- a/pkg/docgen/README.md
+++ b/pkg/docgen/README.md
@@ -8,7 +8,7 @@
 about all classes, variables, functions, and methods defined in the library and 
 its imported libraries.
 
-### Generating Files & Uploading to Cloud Storage
+### Generating files & uploading to Cloud Storage
 
 The viewer uses YAML files generated by the docgen package as the data 
 being displayed. These files are stored in Google Cloud Storage.
@@ -20,7 +20,7 @@
 
 ##### 
 
-#### Generating YAML Files
+#### Generating YAML files
 
 YAML files can be generated using the docgen package in the dart repository. 
 
@@ -44,7 +44,7 @@
 for the outputted documentation.
 
 
-###### Output Directory
+###### Output directory
 Documented libraries will be located at bin/docs in either YAML or JSON format 
 depending on options specified. There will also be a library_list.json, 
 containing a list of all the libraries inside the docs folder. 
@@ -68,7 +68,7 @@
 a new version of documentation. You can see the format of the VERSION file 
 by running `python gsutil cat gs://dartlang-docgen/VERSION`.
 
-### Viewing Generated Documentation
+### Viewing generated documentation
 
 Docgen's generated YAML files can be used by the 
 [Dart Documentation Viewer][dartdoc-viewer] for easy viewing and navigation 
diff --git a/pkg/docgen/bin/dartdoc.py b/pkg/docgen/bin/dartdoc.py
index 15f0de1..7fa875b 100644
--- a/pkg/docgen/bin/dartdoc.py
+++ b/pkg/docgen/bin/dartdoc.py
@@ -51,7 +51,7 @@
 def main():
   options = GetOptions()
   docgen = [DART, '--checked', '--package-root=' + PACKAGE_ROOT,
-    join(DIRECTORY, 'docgen.dart')]
+    join(DIRECTORY, 'docgen.dart'), '--json',  '--package-root=' + PACKAGE_ROOT]
   docgen.extend(options.options.split())
   ExecuteCommand(docgen)
   ExecuteCommand(['git', 'clone', '-b', 'master',
@@ -59,9 +59,7 @@
   ExecuteCommand(['mv', 'docs', 'dartdoc-viewer/client/local'])
   os.chdir('dartdoc-viewer/client/')
   subprocess.call([PUB, 'install'])
-  subprocess.call([DART, 'build.dart'])
-  subprocess.call([DART2JS, '-o', 'web/out/index.html_bootstrap.dart.js', 
-    './web/out/index.html_bootstrap.dart'])
+  subprocess.call([DART, 'deploy.dart'])
   server = subprocess.Popen(['python', 
     join(abspath(join(dirname(__file__), options.gae_sdk)), 'dev_appserver.py'),
     '..'])
diff --git a/pkg/docgen/bin/docgen.dart b/pkg/docgen/bin/docgen.dart
index 293f3cf..82140a9 100644
--- a/pkg/docgen/bin/docgen.dart
+++ b/pkg/docgen/bin/docgen.dart
@@ -8,34 +8,35 @@
 import 'package:logging/logging.dart';
 
 import '../lib/docgen.dart';
+import 'package:path/path.dart' as path;
 
 /**
- * Analyzes Dart files and generates a representation of included libraries, 
- * classes, and members. 
+ * Analyzes Dart files and generates a representation of included libraries,
+ * classes, and members.
  */
 void main() {
   logger.onRecord.listen((record) => print(record.message));
   var results = _initArgParser().parse(new Options().arguments);
-  
-  docgen(results.rest, 
-      packageRoot: results['package-root'], 
-      outputToYaml: !results['json'],  
-      includePrivate: results['include-private'], 
-      includeSdk: results['parse-sdk'] || results['include-sdk'], 
+
+  docgen(results.rest.map(path.normalize).toList(),
+      packageRoot: results['package-root'],
+      outputToYaml: !results['json'],
+      includePrivate: results['include-private'],
+      includeSdk: results['parse-sdk'] || results['include-sdk'],
       parseSdk: results['parse-sdk'],
       append: results['append'] && new Directory('docs').existsSync(),
-      introduction: results['parse-sdk'] ? 
+      introduction: results['parse-sdk'] ?
           'sdk-introduction.md' : results['introduction']);
 }
 
 /**
- * Creates parser for docgen command line arguments. 
+ * Creates parser for docgen command line arguments.
  */
 ArgParser _initArgParser() {
   var parser = new ArgParser();
-  parser.addFlag('help', abbr: 'h', 
-      help: 'Prints help and usage information.', 
-      negatable: false, 
+  parser.addFlag('help', abbr: 'h',
+      help: 'Prints help and usage information.',
+      negatable: false,
       callback: (help) {
         if (help) {
           logger.info(parser.getUsage());
@@ -43,31 +44,31 @@
           exit(0);
         }
       });
-  parser.addFlag('verbose', abbr: 'v', 
-      help: 'Output more logging information.', negatable: false, 
+  parser.addFlag('verbose', abbr: 'v',
+      help: 'Output more logging information.', negatable: false,
       callback: (verbose) {
         if (verbose) Logger.root.level = Level.FINEST;
       });
-  parser.addFlag('json', abbr: 'j', 
-      help: 'Outputs to JSON. Files are outputted to YAML by default. ' 
+  parser.addFlag('json', abbr: 'j',
+      help: 'Outputs to JSON. Files are outputted to YAML by default. '
         'If --append is used, it takes the file-format of the previous '
-        'run stated in library_list.json ignoring the flag.', 
+        'run stated in library_list.json ignoring the flag.',
       negatable: true);
-  parser.addFlag('include-private', 
+  parser.addFlag('include-private',
       help: 'Flag to include private declarations.', negatable: false);
-  parser.addFlag('include-sdk', 
+  parser.addFlag('include-sdk',
       help: 'Flag to parse SDK Library files.', negatable: false);
-  parser.addFlag('parse-sdk', 
-      help: 'Parses the SDK libraries only.', 
+  parser.addFlag('parse-sdk',
+      help: 'Parses the SDK libraries only.',
       defaultsTo: false, negatable: false);
-  parser.addOption('package-root', 
+  parser.addOption('package-root',
       help: 'Sets the package root of the library being analyzed.');
-  parser.addFlag('append', 
-      help: 'Append to the docs folder, library_list.json and index.txt', 
+  parser.addFlag('append',
+      help: 'Append to the docs folder, library_list.json and index.txt',
       defaultsTo: false, negatable: false);
-  parser.addOption('introduction', 
-      help: 'Adds the provided markdown text file as the introduction' 
+  parser.addOption('introduction',
+      help: 'Adds the provided markdown text file as the introduction'
         ' for the outputted documentation.', defaultsTo: '');
-  
+
   return parser;
 }
diff --git a/pkg/docgen/bin/generate_all_docs.sh b/pkg/docgen/bin/generate_all_docs.sh
new file mode 100755
index 0000000..8d5d82c
--- /dev/null
+++ b/pkg/docgen/bin/generate_all_docs.sh
@@ -0,0 +1,6 @@
+# A simple shell script to generate all docs for the sdk and pkg directories
+# into the docs folder in this directory.
+# TODO(alanknight): This should get subsumed into the python scripts
+dart --package-root=$DART_SDK/../packages/ docgen.dart --parse-sdk --json
+dart --old_gen_heap_size=1024 --package-root=$DART_SDK/../packages/ docgen.dart \
+  --package-root=$DART_SDK/../packages/ --append --json $DART_SDK/../../../pkg
diff --git a/pkg/docgen/bin/upload_docgen.py b/pkg/docgen/bin/upload_docgen.py
index 22903e1..9e2d335 100644
--- a/pkg/docgen/bin/upload_docgen.py
+++ b/pkg/docgen/bin/upload_docgen.py
@@ -69,7 +69,7 @@
   # Execute Docgen.dart on the SDK.
   ExecuteCommand([DART, '--checked', '--package-root=' + PACKAGE_ROOT, 
       abspath(join(dirname(__file__), 'docgen.dart')), 
-      '--parse-sdk'])
+      '--parse-sdk', '--json'])
   
   # Use SVN Revision to get the revision number.
   revision = utils.GetSVNRevision()
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index 7ec72ec..a31cf70 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -22,6 +22,7 @@
 import 'package:logging/logging.dart';
 import 'package:markdown/markdown.dart' as markdown;
 import 'package:path/path.dart' as path;
+import 'package:yaml/yaml.dart';
 
 import 'dart2yaml.dart';
 import 'src/io.dart';
@@ -38,8 +39,8 @@
 const String USAGE = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]';
 
 
-List<String> validAnnotations = const ['metadata.Experimental', 
-    'metadata.DomName', 'metadata.Deprecated', 'metadata.Unstable', 
+List<String> validAnnotations = const ['metadata.Experimental',
+    'metadata.DomName', 'metadata.Deprecated', 'metadata.Unstable',
     'meta.deprecated', 'metadata.SupportedBrowser'];
 
 /// Current library being documented to be used for comment links.
@@ -65,9 +66,9 @@
 /// This is set from the command line arguments flag --include-private
 bool _includePrivate = false;
 
-// TODO(janicejl): Make MDN content generic or pluggable. Maybe move 
+// TODO(janicejl): Make MDN content generic or pluggable. Maybe move
 // MDN-specific code to its own library that is imported into the default impl?
-/// Map of all the comments for dom elements from MDN. 
+/// Map of all the comments for dom elements from MDN.
 Map _mdn;
 
 /**
@@ -109,26 +110,50 @@
       if (mirrorSystem.libraries.isEmpty) {
         throw new StateError('No library mirrors were created.');
       }
-      _documentLibraries(mirrorSystem.libraries.values,includeSdk: includeSdk,
-          outputToYaml: outputToYaml, append: append, parseSdk: parseSdk, 
+      var librariesWeAskedFor = _listLibraries(files);
+      var librariesWeGot = mirrorSystem.libraries.values.where((each)
+          => each.uri.scheme == 'file');
+      var sdkLibraries = mirrorSystem.libraries.values.where(
+          (each) => each.uri.scheme == 'dart');
+      var librariesWeGotByPath = new Map.fromIterables(
+          librariesWeGot.map((each) => each.uri.toFilePath()),
+          librariesWeGot);
+      var librariesToDocument = librariesWeAskedFor.map((each) =>
+        librariesWeGotByPath
+            .putIfAbsent(each, () => throw "Missing library $each")).toList();
+      librariesToDocument.addAll((includeSdk || parseSdk) ? sdkLibraries : []);
+      _documentLibraries(librariesToDocument, includeSdk: includeSdk,
+          outputToYaml: outputToYaml, append: append, parseSdk: parseSdk,
           introduction: introduction);
-
       return true;
     });
 }
 
-List<String> _listLibraries(List<String> args) {
-  if (args.length != 1) throw new UnsupportedError(USAGE);
-  var libraries = new List<String>();
-  var type = FileSystemEntity.typeSync(args[0]);
+/// For a [library] and its corresponding [mirror] that we believe come
+/// from a package (because it has a file
+/// URI) look for the package name and set it on [library].
+_findPackage(Library library, LibraryMirror mirror) {
+    if (mirror.uri.scheme != 'file') return;
+    var filePath = mirror.uri.toFilePath();
+    // We assume that we are documenting only libraries under package/lib
+    var rootdir = path.dirname((path.dirname(filePath)));
+    var pubspec = path.join(rootdir, 'pubspec.yaml');
+    library.packageName = _packageName(pubspec);
+}
 
-  if (type == FileSystemEntityType.FILE) {
-    if (args[0].endsWith('.dart')) {
-      libraries.add(path.absolute(args[0]));
-      logger.info('Added to libraries: ${libraries.last}');
+List<String> _listLibraries(List<String> args) {
+  var libraries = new List<String>();
+  for (var arg in args) {
+    var type = FileSystemEntity.typeSync(arg);
+
+    if (type == FileSystemEntityType.FILE) {
+      if (arg.endsWith('.dart')) {
+        libraries.add(path.absolute(arg));
+        logger.info('Added to libraries: ${libraries.last}');
+      }
+    } else {
+      libraries.addAll(_listDartFromDir(arg));
     }
-  } else {
-    libraries.addAll(_listDartFromDir(args[0]));
   }
   return libraries;
 }
@@ -141,15 +166,18 @@
   var files = listDir(args, recursive: true).where((f) => f.endsWith('.dart') &&
       (!f.contains('${path.separator}packages') ||
           args.contains('${path.separator}packages'))).toList();
-  
-  files.forEach((f) {
-    // Only add the file if it does not contain 'part of' 
-    // TODO(janicejl): Remove when Issue(12406) is resolved.
-    var contents = new File(f).readAsStringSync();
-    if (!(contents.contains(new RegExp('\npart of ')) || 
-        contents.startsWith(new RegExp('part of ')))) {
-      libraries.add(f);
-      logger.info('Added to libraries: $f');
+
+  files.forEach((String f) {
+    // Only include libraries at the top level of "lib"
+    if (path.basename(path.dirname(f)) == 'lib') {
+      // Only add the file if it does not contain 'part of'
+      // TODO(janicejl): Remove when Issue(12406) is resolved.
+      var contents = new File(f).readAsStringSync();
+      if (!(contents.contains(new RegExp('\npart of ')) ||
+          contents.startsWith(new RegExp('part of ')))) {
+        libraries.add(f);
+        logger.info('Added to libraries: $f');
+      }
     }
   });
   return libraries;
@@ -166,6 +194,17 @@
   return packageRoot;
 }
 
+/**
+ * Read a pubspec and return the library name.
+ */
+String _packageName(String pubspecName) {
+  File pubspec = new File(pubspecName);
+  if (!pubspec.existsSync()) return '';
+  var contents = pubspec.readAsStringSync();
+  var spec = loadYaml(contents);
+  return spec["name"];
+}
+
 List<String> _listSdk() {
   var sdk = new List<String>();
   LIBRARIES.forEach((String name, LibraryInfo info) {
@@ -200,7 +239,10 @@
       String libraryRoot, {String packageRoot}) {
   SourceFileProvider provider = new CompilerSourceFileProvider();
   api.DiagnosticHandler diagnosticHandler =
-        new FormattingDiagnosticHandler(provider).diagnosticHandler;
+      (new FormattingDiagnosticHandler(provider)
+        ..showHints = false
+        ..showWarnings = false)
+          .diagnosticHandler;
   Uri libraryUri = new Uri(scheme: 'file', path: appendSlash(libraryRoot));
   Uri packageUri = null;
   if (packageRoot != null) {
@@ -227,7 +269,7 @@
  * Creates documentation for filtered libraries.
  */
 void _documentLibraries(List<LibraryMirror> libs, {bool includeSdk: false,
-    bool outputToYaml: true, bool append: false, bool parseSdk: false, 
+    bool outputToYaml: true, bool append: false, bool parseSdk: false,
     String introduction: ''}) {
   libs.forEach((lib) {
     // Files belonging to the SDK have a uri that begins with 'dart:'.
@@ -244,8 +286,8 @@
   if (parseSdk) entityMap['dart.core.Object'].subclasses.clear();
 
   var filteredEntities = entityMap.values.where(_isVisible);
-  
-  // Outputs a JSON file with all libraries and their preview comments. 
+
+  // Outputs a JSON file with all libraries and their preview comments.
   // This will help the viewer know what libraries are available to read in.
   var libraryMap;
   if (append) {
@@ -262,19 +304,19 @@
       var intro = libraryMap['introduction'];
       if (intro.isNotEmpty) intro += '<br/><br/>';
       intro += markdown.markdownToHtml(
-          new File(introduction).readAsStringSync(), 
+          new File(introduction).readAsStringSync(),
               linkResolver: linkResolver, inlineSyntaxes: markdownSyntaxes);
       libraryMap['introduction'] = intro;
     }
     outputToYaml = libraryMap['filetype'] == 'yaml';
   } else {
     libraryMap = {
-      'libraries' : filteredEntities.where((e) => 
+      'libraries' : filteredEntities.where((e) =>
           e is Library).map((e) => e.previewMap).toList(),
-      'introduction' : introduction == '' ? 
+      'introduction' : introduction == '' ?
           '' : markdown.markdownToHtml(new File(introduction)
-              .readAsStringSync(), linkResolver: linkResolver, 
-                  inlineSyntaxes: markdownSyntaxes), 
+              .readAsStringSync(), linkResolver: linkResolver,
+                  inlineSyntaxes: markdownSyntaxes),
       'filetype' : outputToYaml ? 'yaml' : 'json'
     };
   }
@@ -285,9 +327,18 @@
   });
   // Outputs all the qualified names documented with their type.
   // This will help generate search results.
-  _writeToFile(filteredEntities.map((e) => 
-      '${e.qualifiedName} ${e.typeName}').join('\n'),
+  _writeToFile(filteredEntities.map((e) =>
+      '${e.qualifiedName} ${e.typeName}').join('\n') + '\n',
       'index.txt', append: append);
+  var index = new Map.fromIterables(
+      filteredEntities.map((e) => e.qualifiedName),
+      filteredEntities.map((e) => e.typeName));
+  if (append) {
+    var previousIndex =
+        JSON.decode(new File('docs/index.json').readAsStringSync());
+    index.addAll(previousIndex);
+  }
+  _writeToFile(JSON.encode(index), 'index.json');
 }
 
 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) {
@@ -296,6 +347,7 @@
       _variables(library.variables),
       _methods(library.functions),
       _classes(library.classes), _isHidden(library));
+  _findPackage(result, library);
   logger.fine('Generated library for ${result.name}');
   return result;
 }
@@ -320,7 +372,7 @@
   var sdkLibrary = LIBRARIES[mirror.simpleName];
   if (sdkLibrary != null) {
     return !sdkLibrary.documented;
-  } else if (mirror.simpleName.startsWith('_') || 
+  } else if (mirror.simpleName.startsWith('_') ||
       mirror.simpleName.contains('._')) {
     return true;
   }
@@ -392,12 +444,12 @@
 }
 
 /**
- * Generates MDN comments from database.json. 
+ * Generates MDN comments from database.json.
  */
 void _mdnComment(Indexable item) {
-  //Check if MDN is loaded. 
+  //Check if MDN is loaded.
   if (_mdn == null) {
-    // Reading in MDN related json file. 
+    // Reading in MDN related json file.
     var mdnDir = path.join(path.dirname(path.dirname(path.dirname(path.dirname(
         path.absolute(new Options().script))))), 'utils', 'apidoc', 'mdn');
     _mdn = JSON.decode(new File(path.join(mdnDir, 'database.json'))
@@ -414,12 +466,12 @@
 }
 
 /**
- * Generates the MDN Comment for variables and method DOM elements. 
+ * Generates the MDN Comment for variables and method DOM elements.
  */
 String _mdnMemberComment(String type, String member) {
   var mdnType = _mdn[type];
   if (mdnType == null) return '';
-  var mdnMember = mdnType['members'].firstWhere((e) => e['name'] == member, 
+  var mdnMember = mdnType['members'].firstWhere((e) => e['name'] == member,
       orElse: () => null);
   if (mdnMember == null) return '';
   if (mdnMember['help'] == null || mdnMember['help'] == '') return '';
@@ -428,7 +480,7 @@
 }
 
 /**
- * Generates the MDN Comment for class DOM elements. 
+ * Generates the MDN Comment for class DOM elements.
  */
 String _mdnTypeComment(String type) {
   var mdnType = _mdn[type];
@@ -627,10 +679,10 @@
 
   Indexable(this.name, this.comment, this.qualifiedName, this.isPrivate,
       this.owner);
-  
+
   /// The type of this member to be used in index.txt.
   String get typeName => '';
-  
+
   /**
    * Creates a [Map] with this [Indexable]'s name and a preview comment.
    */
@@ -658,6 +710,10 @@
   /// Classes defined within the library
   ClassGroup classes;
 
+  String packageName = '';
+
+  Map get previewMap => super.previewMap..['packageName'] = packageName;
+
   Library(String name, String comment, this.variables,
       this.functions, this.classes, bool isPrivate) : super(name, comment,
           name, isPrivate, "") {}
@@ -669,9 +725,10 @@
     'comment': comment,
     'variables': recurseMap(variables),
     'functions': functions.toMap(),
-    'classes': classes.toMap()
+    'classes': classes.toMap(),
+    'packageName': packageName,
   };
-  
+
   String get typeName => 'library';
 }
 
@@ -709,13 +766,13 @@
 
   Class(String name, this.superclass, String comment, this.interfaces,
       this.variables, this.methods, this.annotations, this.generics,
-      String qualifiedName, bool isPrivate, String owner, this.isAbstract) 
+      String qualifiedName, bool isPrivate, String owner, this.isAbstract)
       : super(name, comment, qualifiedName, isPrivate, owner) {
     _mdnComment(this);
   }
 
   String get typeName => 'class';
-  
+
   /**
    * Returns a list of all the parent classes.
    */
@@ -752,12 +809,12 @@
       subclasses.add(subclass.qualifiedName);
     }
   }
-  
+
   /**
    * Check if this [Class] is an error or exception.
    */
   bool isError() {
-    if (qualifiedName == 'dart.core.Error' || 
+    if (qualifiedName == 'dart.core.Error' ||
         qualifiedName == 'dart.core.Exception')
       return true;
     for (var interface in interfaces) {
@@ -847,16 +904,16 @@
       }
     } else {
       var clazz = _class(mirror);
-  
+
       // Adding inherited parent variables and methods.
       clazz.parent().forEach((parent) {
         if (_isVisible(clazz)) {
           parent.addSubclass(clazz);
         }
       });
-  
+
       clazz.ensureComments();
-  
+
       if (clazz.isError()) {
         errors[mirror.simpleName] = clazz;
       } else if (mirror.isClass) {
@@ -873,7 +930,7 @@
   bool containsKey(String name) {
     return classes.containsKey(name) || errors.containsKey(name);
   }
-  
+
   Map toMap() => {
     'class': classes.values.where(_isVisible)
       .map((e) => e.previewMap).toList(),
@@ -896,7 +953,7 @@
 
   Typedef(String name, this.returnType, String comment, this.generics,
       this.parameters, this.annotations,
-      String qualifiedName, bool isPrivate, String owner) 
+      String qualifiedName, bool isPrivate, String owner)
         : super(name, comment, qualifiedName, isPrivate, owner);
 
   Map toMap() => {
@@ -908,7 +965,7 @@
     'annotations': annotations.map((a) => a.toMap()).toList(),
     'generics': recurseMap(generics)
   };
-  
+
   String get typeName => 'typedef';
 }
 
@@ -942,7 +999,7 @@
     'type': new List.filled(1, type.toMap()),
     'annotations': annotations.map((a) => a.toMap()).toList()
   };
-  
+
   String get typeName => 'property';
 }
 
@@ -972,7 +1029,7 @@
   Method(String name, this.isStatic, this.isAbstract, this.isConst,
       this.returnType, String comment, this.parameters, this.annotations,
       String qualifiedName, bool isPrivate, String owner, this.isConstructor,
-      this.isGetter, this.isSetter, this.isOperator) 
+      this.isGetter, this.isSetter, this.isOperator)
         : super(name, comment, qualifiedName, isPrivate, owner) {
     _mdnComment(this);
   }
@@ -1001,7 +1058,7 @@
     'parameters': recurseMap(parameters),
     'annotations': annotations.map((a) => a.toMap()).toList()
   };
-  
+
   String get typeName => isConstructor ? 'constructor' :
     isGetter ? 'getter' : isSetter ? 'setter' :
     isOperator ? 'operator' : 'method';
diff --git a/pkg/docgen/pubspec.yaml b/pkg/docgen/pubspec.yaml
index 70e3958..254e477 100644
--- a/pkg/docgen/pubspec.yaml
+++ b/pkg/docgen/pubspec.yaml
@@ -5,5 +5,6 @@
   logging: any
   markdown: any
   path: any
+  yaml: any
 dev_dependencies:
   unittest: any
diff --git a/pkg/html_import/README.md b/pkg/html_import/README.md
index c394a6e..066c525 100644
--- a/pkg/html_import/README.md
+++ b/pkg/html_import/README.md
@@ -7,7 +7,7 @@
 definitions from external URLs.
 
 
-## Getting Started
+## Getting started
 
 Include the `html_import.debug.js` or `html_import.min.js` (minified) file in
 your project.
diff --git a/pkg/http_server/README.md b/pkg/http_server/README.md
index 8653f9f..9d82386 100644
--- a/pkg/http_server/README.md
+++ b/pkg/http_server/README.md
@@ -3,7 +3,7 @@
 This package contains a set of high-level classes that, together with
 HttpServer, makes is easy to provide content through HTTP servers.
 
-## Virtual Directory
+## Virtual directory
 
 The VirtualDirectory class makes it possible to easy serve static content from
 the drive. It supports:
@@ -25,7 +25,7 @@
 http://api.dartlang.org/docs/http_server/VirtualDirectory.html)
 for more info about how to customize the class.
 
-## Virtual Host
+## Virtual host
 
 The VirtualHost class makes it possible to serve multiple hosts on the same
 address, by using the `Host` field of the incoming requests. It also provides
diff --git a/pkg/http_server/lib/src/http_body_impl.dart b/pkg/http_server/lib/src/http_body_impl.dart
index 81c7ede..7682902 100644
--- a/pkg/http_server/lib/src/http_body_impl.dart
+++ b/pkg/http_server/lib/src/http_body_impl.dart
@@ -21,17 +21,27 @@
 class _HttpBodyHandlerTransformerSink implements EventSink<HttpRequest> {
   final Encoding _defaultEncoding;
   final EventSink<HttpRequestBody> _outSink;
+  int _pending = 0;
+  bool _closed = false;
 
   _HttpBodyHandlerTransformerSink(this._defaultEncoding, this._outSink);
 
   void add(HttpRequest request) {
+    _pending++;
     _HttpBodyHandler.processRequest(request, _defaultEncoding)
-        .then(_outSink.add, onError: _outSink.addError);
+        .then(_outSink.add, onError: _outSink.addError)
+        .whenComplete(() {
+          _pending--;
+          if (_closed && _pending == 0) _outSink.close();
+        });
   }
   void addError(Object error, [StackTrace stackTrace]) {
     _outSink.addError(error, stackTrace);
   }
-  void close() => _outSink.close();
+  void close() {
+    _closed = true;
+    if (_pending == 0) _outSink.close();
+  }
 }
 
 class _HttpBodyHandler {
@@ -44,7 +54,6 @@
                 // Try to send BAD_REQUEST response.
                 request.response.statusCode = HttpStatus.BAD_REQUEST;
                 request.response.close();
-                request.response.done.catchError((_) {});
                 throw error;
               });
   }
diff --git a/pkg/http_server/lib/src/virtual_directory.dart b/pkg/http_server/lib/src/virtual_directory.dart
index 4b38466..88a9d50 100644
--- a/pkg/http_server/lib/src/virtual_directory.dart
+++ b/pkg/http_server/lib/src/virtual_directory.dart
@@ -64,7 +64,7 @@
             return;
           }
           if (entity is File) {
-            _serveFile(entity, request);
+            serveFile(entity, request);
           } else if (entity is Directory) {
             _serveDirectory(entity, request);
           } else {
@@ -141,7 +141,20 @@
         });
   }
 
-  void _serveFile(File file, HttpRequest request) {
+  /**
+   * Serve the content of [file] to [request].
+   *
+   * This is usefull when e.g. overriding [directoryHandler] to redirect to
+   * some index file.
+   *
+   * In the request contains the [HttpStatus.IF_MODIFIED_SINCE] header,
+   * [serveFile] will send a [HttpStatus.NOT_MODIFIED] response if the file
+   * was not changed.
+   *
+   * Note that if it was unabled to read from [file], the [request]s response
+   * is closed with error-code [HttpStatus.NOT_FOUND].
+   */
+  void serveFile(File file, HttpRequest request) {
     var response = request.response;
     // TODO(ajohnsen): Set up Zone support for these errors.
     file.lastModified().then((lastModified) {
@@ -201,6 +214,7 @@
             .catchError((_) {});
       });
     }).catchError((_) {
+      response.statusCode = HttpStatus.NOT_FOUND;
       response.close();
     });
   }
diff --git a/pkg/http_server/test/http_body_test.dart b/pkg/http_server/test/http_body_test.dart
index bae4e1b..e8d84c0 100644
--- a/pkg/http_server/test/http_body_test.dart
+++ b/pkg/http_server/test/http_body_test.dart
@@ -90,6 +90,7 @@
     HttpServer.bind("127.0.0.1", 0).then((server) {
       server.transform(new HttpBodyHandler(defaultEncoding: defaultEncoding))
           .listen((body) {
+            if (shouldFail) return;
             expect(shouldFail, isFalse);
             expect(body.type, equals(type));
             switch (type) {
@@ -157,9 +158,12 @@
             }
             return response.drain();
           })
-          .then((_) {
+          .whenComplete(() {
             client.close();
             server.close();
+          })
+          .catchError((e) {
+            if (!shouldFail) throw e;
           });
     });
   }
diff --git a/pkg/http_server/test/virtual_directory_test.dart b/pkg/http_server/test/virtual_directory_test.dart
index a368c73..027f044 100644
--- a/pkg/http_server/test/virtual_directory_test.dart
+++ b/pkg/http_server/test/virtual_directory_test.dart
@@ -669,5 +669,28 @@
     testEncoding('%2f', HttpStatus.NOT_FOUND, false);
     testEncoding('%2f', HttpStatus.OK, true);
   });
+
+  group('serve-file', () {
+    test('from-dir-handler', () {
+      expect(HttpServer.bind('localhost', 0).then((server) {
+        var dir = Directory.systemTemp.createTempSync('http_server_virtual_');
+        new File('${dir.path}/file')..writeAsStringSync('file contents');
+        var virDir = new VirtualDirectory(dir.path);
+        virDir.allowDirectoryListing = true;
+        virDir.directoryHandler = (d, request) {
+          expect(FileSystemEntity.identicalSync(dir.path, d.path), isTrue);
+          virDir.serveFile(new File('${d.path}/file'), request);
+        };
+
+        virDir.serve(server);
+
+        return getAsString(server.port, '/')
+            .whenComplete(() {
+              server.close();
+              dir.deleteSync(recursive: true);
+            });
+      }), completion(equals('file contents')));
+    });
+  });
 }
 
diff --git a/pkg/mutation_observer/test/mutation_observer_test.dart b/pkg/mutation_observer/test/mutation_observer_test.dart
index 24dbccf..e3bbdf4 100644
--- a/pkg/mutation_observer/test/mutation_observer_test.dart
+++ b/pkg/mutation_observer/test/mutation_observer_test.dart
@@ -101,14 +101,5 @@
       container.append(div1);
       div1.append(div2);
     });
-
-    test('mutation event', () {
-      var event = new MutationEvent('something', prevValue: 'prev',
-          newValue: 'new', attrName: 'attr');
-      expect(event is MutationEvent, isTrue);
-      expect(event.prevValue, 'prev');
-      expect(event.newValue, 'new');
-      expect(event.attrName, 'attr');
-    });
   });
 }
diff --git a/pkg/observe/lib/observe.dart b/pkg/observe/lib/observe.dart
index abce718..9da8d5e 100644
--- a/pkg/observe/lib/observe.dart
+++ b/pkg/observe/lib/observe.dart
@@ -77,34 +77,15 @@
  */
 library observe;
 
-import 'dart:async';
-import 'dart:collection';
-
-// Note: ObservableProperty is in this list only for the unusual use case of
-// dart2js without deploy tool. The deploy tool (see "transformer.dart") will
-// add the @reflectable annotation, which makes it work with Polymer's
-// @published.
-@MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty],
-    override: 'observe')
-import 'dart:mirrors';
-
-import 'package:meta/meta.dart';
-
-// Note: this is an internal library so we can import it from tests.
-// TODO(jmesserly): ideally we could import this with a prefix, but it caused
-// strange problems on the VM when I tested out the dirty-checking example
-// above.
-import 'src/dirty_check.dart';
-
-part 'src/bind_property.dart';
-part 'src/change_notifier.dart';
-part 'src/change_record.dart';
-part 'src/compound_binding.dart';
-part 'src/list_path_observer.dart';
-part 'src/metadata.dart';
-part 'src/observable.dart';
-part 'src/observable_box.dart';
-part 'src/observable_list.dart';
-part 'src/observable_map.dart';
-part 'src/path_observer.dart';
-part 'src/to_observable.dart';
+export 'src/bind_property.dart';
+export 'src/change_notifier.dart';
+export 'src/change_record.dart';
+export 'src/compound_path_observer.dart';
+export 'src/list_path_observer.dart';
+export 'src/metadata.dart';
+export 'src/observable.dart' hide notifyPropertyChangeHelper, objectType;
+export 'src/observable_box.dart';
+export 'src/observable_list.dart';
+export 'src/observable_map.dart';
+export 'src/path_observer.dart';
+export 'src/to_observable.dart';
diff --git a/pkg/observe/lib/src/bind_property.dart b/pkg/observe/lib/src/bind_property.dart
index a31d1ab..59f867f 100644
--- a/pkg/observe/lib/src/bind_property.dart
+++ b/pkg/observe/lib/src/bind_property.dart
@@ -2,7 +2,10 @@
 // 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.
 
-part of observe;
+library observe.src.bind_property;
+
+import 'dart:async';
+import 'package:observe/observe.dart';
 
 /**
  * Forwards an observable property from one object to another. For example:
diff --git a/pkg/observe/lib/src/change_notifier.dart b/pkg/observe/lib/src/change_notifier.dart
index a51fda6..133c6c8 100644
--- a/pkg/observe/lib/src/change_notifier.dart
+++ b/pkg/observe/lib/src/change_notifier.dart
@@ -2,7 +2,12 @@
 // 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.
 
-part of observe;
+library observe.src.change_notifier;
+
+import 'dart:async';
+import 'dart:collection' show UnmodifiableListView;
+import 'package:observe/observe.dart';
+import 'package:observe/src/observable.dart' show notifyPropertyChangeHelper;
 
 /**
  * Mixin and base class for implementing an [Observable] object that performs
@@ -19,7 +24,7 @@
   Stream<List<ChangeRecord>> get changes {
     if (_changes == null) {
       _changes = new StreamController.broadcast(sync: true,
-          onListen: _observed, onCancel: _unobserved);
+          onListen: observed, onCancel: unobserved);
     }
     return _changes.stream;
   }
@@ -29,13 +34,13 @@
   /**
    * Override this method to be called when the [changes] are first observed.
    */
-  void _observed() {}
+  void observed() {}
 
   /**
    * Override this method to be called when the [changes] are no longer being
    * observed.
    */
-  void _unobserved() {}
+  void unobserved() {}
 
   bool deliverChanges() {
     var records = _records;
@@ -69,7 +74,7 @@
    *     }
    */
   notifyPropertyChange(Symbol field, Object oldValue, Object newValue)
-      => _notifyPropertyChange(this, field, oldValue, newValue);
+      => notifyPropertyChangeHelper(this, field, oldValue, newValue);
 
   void notifyChange(ChangeRecord record) {
     if (!hasObservers) return;
diff --git a/pkg/observe/lib/src/change_record.dart b/pkg/observe/lib/src/change_record.dart
index bb584e8..39e5964 100644
--- a/pkg/observe/lib/src/change_record.dart
+++ b/pkg/observe/lib/src/change_record.dart
@@ -2,7 +2,10 @@
 // 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.
 
-part of observe;
+library observe.src.change_record;
+
+import 'package:observe/observe.dart';
+
 
 /** Records a change to an [Observable]. */
 // TODO(jmesserly): remove this type
@@ -10,13 +13,6 @@
 
 /** A change record to a field of an observable object. */
 class PropertyChangeRecord<T> extends ChangeRecord {
-  /**
-   * *Deprecated* use [name] instead.
-   * The field that was changed.
-   */
-  @deprecated
-  Symbol get field => name;
-
   /** The object that changed. */
   final object;
 
@@ -31,13 +27,6 @@
 
   PropertyChangeRecord(this.object, this.name, this.oldValue, this.newValue);
 
-  /*
-   * *Deprecated* instead of `record.changes(key)` simply do
-   * `key == record.name`.
-   */
-  @deprecated
-  bool changes(key) => key is Symbol && name == key;
-
   String toString() =>
       '#<PropertyChangeRecord $name from: $oldValue to: $newValue>';
 }
@@ -60,13 +49,6 @@
     }
   }
 
-  /**
-   * *Deprecated* use [indexChanged] instead.
-   * Returns true if the provided index was changed by this operation.
-   */
-  @deprecated
-  bool changes(value) => indexChanged(value);
-
   /** Returns true if the provided index was changed by this operation. */
   bool indexChanged(otherIndex) {
     // If key isn't an int, or before the index, then it wasn't changed.
diff --git a/pkg/observe/lib/src/compound_binding.dart b/pkg/observe/lib/src/compound_binding.dart
deleted file mode 100644
index 3d27926..0000000
--- a/pkg/observe/lib/src/compound_binding.dart
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2013, 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.
-
-part of observe;
-
-/** The callback used in the [CompoundBinding.combinator] field. */
-typedef Object CompoundBindingCombinator(Map objects);
-
-/**
- * CompoundBinding is an object which knows how to listen to multiple path
- * values (registered via [bind]) and invoke its [combinator] when one or more
- * of the values have changed and set its [value] property to the return value
- * of the function. When any value has changed, all current values are provided
- * to the [combinator] in the single `values` argument.
- *
- * For example:
- *
- *     var binding = new CompoundBinding((values) {
- *       var combinedValue;
- *       // compute combinedValue based on the current values which are provided
- *       return combinedValue;
- *     });
- *     binding.bind('name1', obj1, path1);
- *     binding.bind('name2', obj2, path2);
- *     //...
- *     binding.bind('nameN', objN, pathN);
- */
-// TODO(jmesserly): rename to something that indicates it's a computed value?
-class CompoundBinding extends ChangeNotifier {
-  CompoundBindingCombinator _combinator;
-
-  // TODO(jmesserly): ideally these would be String keys, but sometimes we
-  // use integers.
-  Map<dynamic, StreamSubscription> _observers = new Map();
-  Map _values = new Map();
-  Object _value;
-
-  /**
-   * True if [resolve] is scheduled. You can set this to true if you plan to
-   * call [resolve] manually, avoiding the need for scheduling an asynchronous
-   * resolve.
-   */
-  // TODO(jmesserly): I don't like having this public, is the optimization
-  // really needed? "scheduleMicrotask" in Dart should be pretty cheap.
-  bool scheduled = false;
-
-  /**
-   * Creates a new CompoundBinding, optionally proving the [combinator] function
-   * for computing the value. You can also set [schedule] to true if you plan
-   * to invoke [resolve] manually after initial construction of the binding.
-   */
-  CompoundBinding([CompoundBindingCombinator combinator]) {
-    // TODO(jmesserly): this is a tweak to the original code, it seemed to me
-    // that passing the combinator to the constructor should be equivalent to
-    // setting it via the property.
-    // I also added a null check to the combinator setter.
-    this.combinator = combinator;
-  }
-
-  CompoundBindingCombinator get combinator => _combinator;
-
-  set combinator(CompoundBindingCombinator combinator) {
-    _combinator = combinator;
-    if (combinator != null) _scheduleResolve();
-  }
-
-  int get length => _observers.length;
-
-  @reflectable get value => _value;
-
-  @reflectable void set value(newValue) {
-    _value = notifyPropertyChange(#value, _value, newValue);
-  }
-
-  void bind(name, model, String path) {
-    unbind(name);
-
-     // TODO(jmesserly): should we delay observing until we are observed,
-     // similar to PathObserver?
-    _observers[name] = new PathObserver(model, path).bindSync((value) {
-      _values[name] = value;
-      _scheduleResolve();
-    });
-  }
-
-  void unbind(name, {bool suppressResolve: false}) {
-    var binding = _observers.remove(name);
-    if (binding == null) return;
-
-    binding.cancel();
-    _values.remove(name);
-    if (!suppressResolve) _scheduleResolve();
-  }
-
-  // TODO(rafaelw): Is this the right processing model?
-  // TODO(rafaelw): Consider having a seperate ChangeSummary for
-  // CompoundBindings so to excess dirtyChecks.
-  void _scheduleResolve() {
-    if (scheduled) return;
-    scheduled = true;
-    scheduleMicrotask(resolve);
-  }
-
-  void resolve() {
-    if (_observers.isEmpty) return;
-    scheduled = false;
-
-    if (_combinator == null) {
-      throw new StateError(
-          'CompoundBinding attempted to resolve without a combinator');
-    }
-
-    value = _combinator(_values);
-  }
-
-  /**
-   * Closes the observer.
-   *
-   * This happens automatically if the [value] property is no longer observed,
-   * but this can also be called explicitly.
-   */
-  void close() {
-    for (var binding in _observers.values) {
-      binding.cancel();
-    }
-    _observers.clear();
-    _values.clear();
-    value = null;
-  }
-
-  _unobserved() => close();
-}
diff --git a/pkg/observe/lib/src/compound_path_observer.dart b/pkg/observe/lib/src/compound_path_observer.dart
new file mode 100644
index 0000000..6fee689
--- /dev/null
+++ b/pkg/observe/lib/src/compound_path_observer.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2013, 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.
+
+library observe.src.compound_path_observer;
+
+import 'dart:async';
+import 'package:observe/observe.dart';
+
+/**
+ * CompoundPathObserver is an object which knows how to listen to multiple path
+ * values (registered via [addPath]) and invoke a function when one or more
+ * of the values have changed. The result of this function will be set into the
+ * [value] property. When any value has changed, all current values are provided
+ * to the function in the single `values` argument.
+ *
+ * For example:
+ *
+ *     var binding = new CompoundPathObserver(computeValue: (values) {
+ *       var combinedValue;
+ *       // compute combinedValue based on the current values which are provided
+ *       return combinedValue;
+ *     });
+ *     binding.addPath(obj1, path1);
+ *     binding.addPath(obj2, path2);
+ *     //...
+ *     binding.addPath(objN, pathN);
+ */
+// TODO(jmesserly): this isn't a full port of CompoundPathObserver. It is only
+// what was needed for TemplateBinding.
+class CompoundPathObserver extends ChangeNotifier {
+  List<PathObserver> _observers = [];
+  List<StreamSubscription> _subs = [];
+  Object _value; // the last computed value
+
+  // TODO(jmesserly): this is public in observe.js
+  final Function _computeValue;
+
+  bool _started = false;
+
+  /** True if [start] has been called, otherwise false. */
+  bool get started => _started;
+
+  bool _scheduled = false;
+
+  /**
+   * Creates a new observer, optionally proving the [computeValue] function
+   * for computing the value. You can also set [schedule] to true if you plan
+   * to invoke [resolve] manually after initial construction of the binding.
+   */
+  CompoundPathObserver({computeValue(List values)})
+      : _computeValue = computeValue;
+
+  int get length => _observers.length;
+
+  @reflectable get value => _value;
+
+  void addPath(model, String path) {
+    if (_started) {
+      throw new StateError('Cannot add more paths once started.');
+    }
+
+    _observers.add(new PathObserver(model, path));
+  }
+
+  void start() {
+    if (_started) return;
+    _started = true;
+
+    final scheduleResolve = _scheduleResolve;
+    for (var observer in _observers) {
+      _subs.add(observer.changes.listen(scheduleResolve));
+    }
+    _resolve();
+  }
+
+  // TODO(rafaelw): Is this the right processing model?
+  // TODO(rafaelw): Consider having a seperate ChangeSummary for
+  // CompoundBindings so to excess dirtyChecks.
+  void _scheduleResolve(_) {
+    if (_scheduled) return;
+    _scheduled = true;
+    scheduleMicrotask(_resolve);
+  }
+
+  void _resolve() {
+    _scheduled = false;
+    var newValue = _observers.map((o) => o.value).toList();
+    if (_computeValue != null) newValue = _computeValue(newValue);
+    _value = notifyPropertyChange(#value, _value, newValue);
+  }
+
+  /**
+   * Closes the observer.
+   *
+   * This happens automatically if the [value] property is no longer observed,
+   * but this can also be called explicitly.
+   */
+  void close() {
+    if (_observers.isEmpty) return;
+
+    if (_started) {
+      for (StreamSubscription sub in _subs) {
+        sub.cancel();
+      }
+    }
+    _observers.clear();
+    _subs.clear();
+    _value = null;
+  }
+
+  observed() => start();
+  unobserved() => close();
+}
diff --git a/pkg/observe/lib/src/list_path_observer.dart b/pkg/observe/lib/src/list_path_observer.dart
index f882e12..e67f9d3 100644
--- a/pkg/observe/lib/src/list_path_observer.dart
+++ b/pkg/observe/lib/src/list_path_observer.dart
@@ -2,7 +2,10 @@
 // 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.
 
-part of observe;
+library observe.src.list_path_observer;
+
+import 'dart:async';
+import 'package:observe/observe.dart';
 
 // Inspired by ArrayReduction at:
 // https://raw.github.com/rafaelw/ChangeSummary/master/util/array_reduction.js
diff --git a/pkg/observe/lib/src/metadata.dart b/pkg/observe/lib/src/metadata.dart
index 48d06c2..a1e4e15 100644
--- a/pkg/observe/lib/src/metadata.dart
+++ b/pkg/observe/lib/src/metadata.dart
@@ -2,7 +2,7 @@
 // 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.
 
-part of observe;
+library observe.src.metadata;
 
 /**
  * Use `@observable` to make a field automatically observable, or to indicate
diff --git a/pkg/observe/lib/src/observable.dart b/pkg/observe/lib/src/observable.dart
index ca94085..ee25819 100644
--- a/pkg/observe/lib/src/observable.dart
+++ b/pkg/observe/lib/src/observable.dart
@@ -2,7 +2,26 @@
 // 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.
 
-part of observe;
+library observe.src.observable;
+
+import 'dart:async';
+import 'dart:collection';
+
+// Note: ObservableProperty is in this list only for the unusual use case of
+// dart2js without deploy tool. The deploy tool (see "transformer.dart") will
+// add the @reflectable annotation, which makes it work with Polymer's
+// @published.
+@MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty],
+    override: 'observe.src.observable')
+import 'dart:mirrors';
+
+import 'package:observe/observe.dart';
+
+// Note: this is an internal library so we can import it from tests.
+// TODO(jmesserly): ideally we could import this with a prefix, but it caused
+// strange problems on the VM when I tested out the dirty-checking example
+// above.
+import 'dirty_check.dart';
 
 /**
  * Represents an object with observable properties. This is used by data in
@@ -32,8 +51,6 @@
   Map<Symbol, Object> _values;
   List<ChangeRecord> _records;
 
-  static final _objectType = reflectClass(Object);
-
   /**
    * The stream of change records to this object. Records will be delivered
    * asynchronously.
@@ -64,7 +81,7 @@
     // Note: we scan for @observable regardless of whether the base type
     // actually includes this mixin. While perhaps too inclusive, it lets us
     // avoid complex logic that walks "with" and "implements" clauses.
-    for (var type = mirror.type; type != _objectType; type = type.superclass) {
+    for (var type = mirror.type; type != objectType; type = type.superclass) {
       for (var field in type.variables.values) {
         if (field.isFinal || field.isStatic || field.isPrivate) continue;
 
@@ -148,7 +165,7 @@
    * For convenience this returns [newValue].
    */
   notifyPropertyChange(Symbol field, Object oldValue, Object newValue)
-      => _notifyPropertyChange(this, field, oldValue, newValue);
+      => notifyPropertyChangeHelper(this, field, oldValue, newValue);
 
   /**
    * Notify observers of a change.
@@ -188,7 +205,8 @@
 
 // TODO(jmesserly): remove the instance method and make this top-level method
 // public instead?
-_notifyPropertyChange(Observable obj, Symbol field, Object oldValue,
+// NOTE: this is not exported publically.
+notifyPropertyChangeHelper(Observable obj, Symbol field, Object oldValue,
     Object newValue) {
 
   if (obj.hasObservers && oldValue != newValue) {
@@ -196,3 +214,6 @@
   }
   return newValue;
 }
+
+// NOTE: this is not exported publically.
+final objectType = reflectClass(Object);
diff --git a/pkg/observe/lib/src/observable_box.dart b/pkg/observe/lib/src/observable_box.dart
index 7db72bf..9455dbd 100644
--- a/pkg/observe/lib/src/observable_box.dart
+++ b/pkg/observe/lib/src/observable_box.dart
@@ -2,7 +2,9 @@
 // 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.
 
-part of observe;
+library observe.src.observable_box;
+
+import 'package:observe/observe.dart';
 
 // TODO(jmesserly): should the property name be configurable?
 // That would be more convenient.
diff --git a/pkg/observe/lib/src/observable_list.dart b/pkg/observe/lib/src/observable_list.dart
index 0cf181c..4137957 100644
--- a/pkg/observe/lib/src/observable_list.dart
+++ b/pkg/observe/lib/src/observable_list.dart
@@ -2,7 +2,11 @@
 // 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.
 
-part of observe;
+library observe.src.observable_list;
+
+import 'dart:async';
+import 'dart:collection' show ListBase;
+import 'package:observe/observe.dart';
 
 /**
  * Represents an observable list of model values. If any items are added,
diff --git a/pkg/observe/lib/src/observable_map.dart b/pkg/observe/lib/src/observable_map.dart
index d4da646..27e25da 100644
--- a/pkg/observe/lib/src/observable_map.dart
+++ b/pkg/observe/lib/src/observable_map.dart
@@ -2,7 +2,11 @@
 // 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.
 
-part of observe;
+library observe.src.observable_map;
+
+import 'dart:collection';
+import 'package:observe/observe.dart';
+
 
 // TODO(jmesserly): this needs to be faster. We currently require multiple
 // lookups per key to get the old value.
@@ -34,14 +38,10 @@
       : isInsert = false, isRemove = false;
 
   MapChangeRecord.insert(this.key, this.newValue)
-      : isInsert = true, isRemove = false;
+      : isInsert = true, isRemove = false, oldValue = null;
 
   MapChangeRecord.remove(this.key, this.oldValue)
-      : isInsert = false, isRemove = true;
-
-  /// *Deprecated* compare [key]s instead.
-  @deprecated
-  bool changes(otherKey) => key == otherKey;
+      : isInsert = false, isRemove = true, newValue = null;
 
   String toString() {
     var kind = isInsert ? 'insert' : isRemove ? 'remove' : 'set';
@@ -76,10 +76,11 @@
    * you should use [toObservable].
    */
   factory ObservableMap.from(Map<K, V> other) {
-    return new ObservableMap<K, V>._createFromType(other)..addAll(other);
+    return new ObservableMap<K, V>.createFromType(other)..addAll(other);
   }
 
-  factory ObservableMap._createFromType(Map<K, V> other) {
+  /** Like [ObservableMap.from], but creates an empty map. */
+  factory ObservableMap.createFromType(Map<K, V> other) {
     ObservableMap result;
     if (other is SplayTreeMap) {
       result = new ObservableMap<K, V>.sorted();
diff --git a/pkg/observe/lib/src/path_observer.dart b/pkg/observe/lib/src/path_observer.dart
index 1b6e1a3..6384f6e 100644
--- a/pkg/observe/lib/src/path_observer.dart
+++ b/pkg/observe/lib/src/path_observer.dart
@@ -2,7 +2,15 @@
 // 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.
 
-part of observe;
+library observe.src.path_observer;
+
+import 'dart:async';
+@MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty],
+    override: 'observe.src.path_observer')
+import 'dart:mirrors';
+import 'package:logging/logging.dart' show Logger, Level;
+import 'package:observe/observe.dart';
+import 'package:observe/src/observable.dart' show objectType;
 
 // This code is inspired by ChangeSummary:
 // https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
@@ -21,6 +29,10 @@
  *
  * This class is used to implement [Node.bind] and similar functionality.
  */
+// TODO(jmesserly): consider specialized subclasses for:
+// * empty path
+// * "value"
+// * single token in path, e.g. "foo"
 class PathObserver extends ChangeNotifier {
   /** The path string. */
   final String path;
@@ -32,13 +44,22 @@
   List<Object> _values;
   List<StreamSubscription> _subs;
 
+  final Function _computeValue;
+
   /**
    * Observes [path] on [object] for changes. This returns an object that can be
    * used to get the changes and get/set the value at this path.
+   *
+   * You can optionally use [computeValue] to apply a function to the result of
+   * evaluating the path. The function should be pure, as PathObserver will not
+   * know to observe any of its dependencies. If you need to observe mutliple
+   * values, use [CompoundPathObserver] instead.
+   *
    * See [PathObserver.bindSync] and [PathObserver.value].
    */
-  PathObserver(Object object, String path)
+  PathObserver(Object object, String path, {computeValue(newValue)})
       : path = path,
+        _computeValue = computeValue,
         _isValid = _isPathValid(path),
         _segments = <Object>[] {
 
@@ -54,11 +75,19 @@
     // Note that the path itself can't change after it is initially
     // constructed, even though the objects along the path can change.
     _values = new List<Object>(_segments.length + 1);
+
+    // If we have an empty path, we need to apply the transformation function
+    // to the value. The "value" property should always show the transformed
+    // value.
+    if (_segments.isEmpty && computeValue != null) {
+      object = computeValue(object);
+    }
+
     _values[0] = object;
     _subs = new List<StreamSubscription>(_segments.length);
   }
 
-  /** The object being observed. */
+  /** The object being observed. If the path is empty this will be [value]. */
   get object => _values[0];
 
   /** Gets the last reported value at this path. */
@@ -69,19 +98,19 @@
   }
 
   /** Sets the value at this path. */
-  @reflectable void set value(Object value) {
+  @reflectable void set value(Object newValue) {
     int len = _segments.length;
 
     // TODO(jmesserly): throw if property cannot be set?
     // MDV seems tolerant of these errors.
     if (len == 0) return;
-    if (!hasObservers) _updateValues();
+    if (!hasObservers) _updateValues(end: len - 1);
 
-    if (_setObjectProperty(_values[len - 1], _segments[len - 1], value)) {
+    if (_setObjectProperty(_values[len - 1], _segments[len - 1], newValue)) {
       // Technically, this would get updated asynchronously via a change record.
       // However, it is nice if calling the getter will yield the same value
       // that was just set. So we use this opportunity to update our cache.
-      _values[len] = value;
+      _values[len] = newValue;
     }
   }
 
@@ -96,33 +125,43 @@
     return result;
   }
 
-  void _observed() {
-    super._observed();
+  void observed() {
+    super.observed();
     _updateValues();
     _observePath();
   }
 
-  void _unobserved() {
+  void unobserved() {
     for (int i = 0; i < _subs.length; i++) {
       if (_subs[i] != null) {
         _subs[i].cancel();
         _subs[i] = null;
       }
     }
+    super.unobserved();
   }
 
   // TODO(jmesserly): should we be caching these values if not observing?
-  void _updateValues() {
-    for (int i = 0; i < _segments.length; i++) {
-      _values[i + 1] = _getObjectProperty(_values[i], _segments[i]);
+  void _updateValues({int end}) {
+    if (end == null) end = _segments.length;
+    int last = _segments.length - 1;
+    for (int i = 0; i < end; i++) {
+      var newValue = _getObjectProperty(_values[i], _segments[i]);
+      if (i == last && _computeValue != null) {
+        newValue = _computeValue(newValue);
+      }
+      _values[i + 1] = newValue;
     }
   }
 
-  void _updateObservedValues([int start = 0]) {
+  void _updateObservedValues({int start: 0}) {
     var oldValue, newValue;
-    for (int i = start; i < _segments.length; i++) {
+    for (int i = start, last = _segments.length - 1; i <= last; i++) {
       oldValue = _values[i + 1];
       newValue = _getObjectProperty(_values[i], _segments[i]);
+      if (i == last && _computeValue != null) {
+        newValue = _computeValue(newValue);
+      }
       if (identical(oldValue, newValue)) {
         _observePath(start, i);
         return;
@@ -147,19 +186,14 @@
     final object = _values[i];
     if (object is Observable) {
       // TODO(jmesserly): rather than allocating a new closure for each
-      // property, we could try and have one for the entire path. In that case,
-      // we would lose information about which object changed (note: unless
-      // PropertyChangeRecord is modified to includes the sender object), so
-      // we would need to re-evaluate the entire path. Need to evaluate perf.
+      // property, we could try and have one for the entire path. However we'd
+      // need to do a linear scan to find the index as soon as we got a change.
+      // Also we need to fix ListChangeRecord and MapChangeRecord to contain
+      // the target. Not sure if it's worth it.
       _subs[i] = object.changes.listen((List<ChangeRecord> records) {
-        if (!identical(_values[i], object)) {
-          // Ignore this object if we're now tracking something else.
-          return;
-        }
-
         for (var record in records) {
           if (_changeRecordMatches(record, _segments[i])) {
-            _updateObservedValues(i);
+            _updateObservedValues(start: i);
             return;
           }
         }
@@ -183,85 +217,78 @@
 }
 
 _getObjectProperty(object, property) {
-  if (object == null) {
-    return null;
-  }
+  if (object == null) return null;
 
-  if (object is List && property is int) {
-    if (property >= 0 && property < object.length) {
+  if (property is int) {
+    if (object is List && property >= 0 && property < object.length) {
       return object[property];
-    } else {
-      return null;
+    }
+  } else if (property is Symbol) {
+    var mirror = reflect(object);
+    final type = mirror.type;
+    try {
+      if (_maybeHasGetter(type, property)) {
+        return mirror.getField(property).reflectee;
+      }
+      // Support indexer if available, e.g. Maps or polymer_expressions Scope.
+      // This is the default syntax used by polymer/nodebind and
+      // polymer/observe-js PathObserver.
+      if (_hasMethod(type, const Symbol('[]'))) {
+        return object[MirrorSystem.getName(property)];
+      }
+    } on NoSuchMethodError catch (e) {
+      // Rethrow, unless the type implements noSuchMethod, in which case we
+      // interpret the exception as a signal that the method was not found.
+      if (!_hasMethod(type, #noSuchMethod)) rethrow;
     }
   }
 
-  if (property is Symbol) {
-    var mirror = reflect(object);
-    var result = _tryGetField(mirror, property);
-    if (result != null) return result.reflectee;
+  if (_logger.isLoggable(Level.FINER)) {
+    _logger.log("can't get $property in $object");
   }
-
-  if (object is Map) {
-    if (property is Symbol) property = MirrorSystem.getName(property);
-    return object[property];
-  }
-
   return null;
 }
 
 bool _setObjectProperty(object, property, value) {
-  if (object is List && property is int) {
-    if (property >= 0 && property < object.length) {
+  if (object == null) return false;
+
+  if (property is int) {
+    if (object is List && property >= 0 && property < object.length) {
       object[property] = value;
       return true;
-    } else {
-      return false;
+    }
+  } else if (property is Symbol) {
+    var mirror = reflect(object);
+    final type = mirror.type;
+    try {
+      if (_maybeHasSetter(type, property)) {
+        mirror.setField(property, value);
+        return true;
+      }
+      // Support indexer if available, e.g. Maps or polymer_expressions Scope.
+      if (_hasMethod(type, const Symbol('[]='))) {
+        object[MirrorSystem.getName(property)] = value;
+        return true;
+      }
+    } on NoSuchMethodError catch (e) {
+      if (!_hasMethod(type, #noSuchMethod)) rethrow;
     }
   }
 
-  if (property is Symbol) {
-    var mirror = reflect(object);
-    if (_trySetField(mirror, property, value)) return true;
+  if (_logger.isLoggable(Level.FINER)) {
+    _logger.log("can't set $property in $object");
   }
-
-  if (object is Map) {
-    if (property is Symbol) property = MirrorSystem.getName(property);
-    object[property] = value;
-    return true;
-  }
-
   return false;
 }
 
-InstanceMirror _tryGetField(InstanceMirror mirror, Symbol name) {
-  try {
-    return mirror.getField(name);
-  } on NoSuchMethodError catch (e) {
-    if (_hasMember(mirror, name, (m) =>
-        m is VariableMirror || m is MethodMirror && m.isGetter)) {
-      // The field/getter is there but threw a NoSuchMethod exception.
-      // This is a legitimate error in the code so rethrow.
-      rethrow;
-    }
-    // The field isn't there. PathObserver does not treat this as an error.
-    return null;
+bool _maybeHasGetter(ClassMirror type, Symbol name) {
+  while (type != objectType) {
+    final members = type.members;
+    if (members.containsKey(name)) return true;
+    if (members.containsKey(#noSuchMethod)) return true;
+    type = _safeSuperclass(type);
   }
-}
-
-bool _trySetField(InstanceMirror mirror, Symbol name, Object value) {
-  try {
-    mirror.setField(name, value);
-    return true;
-  } on NoSuchMethodError catch (e) {
-    if (_hasMember(mirror, name, (m) => m is VariableMirror) ||
-        _hasMember(mirror, _setterName(name))) {
-      // The field/setter is there but threw a NoSuchMethod exception.
-      // This is a legitimate error in the code so rethrow.
-      rethrow;
-    }
-    // The field isn't there. PathObserver does not treat this as an error.
-    return false;
-  }
+  return false;
 }
 
 // TODO(jmesserly): workaround for:
@@ -269,23 +296,41 @@
 Symbol _setterName(Symbol getter) =>
     new Symbol('${MirrorSystem.getName(getter)}=');
 
-bool _hasMember(InstanceMirror mirror, Symbol name, [bool test(member)]) {
-  var type = mirror.type;
-  while (type != null) {
-    final member = type.members[name];
-    if (member != null && (test == null || test(member))) return true;
-
-    try {
-      type = type.superclass;
-    } on UnsupportedError catch (e) {
-      // TODO(jmesserly): dart2js throws this error when the type is not
-      // reflectable.
-      return false;
-    }
+bool _maybeHasSetter(ClassMirror type, Symbol name) {
+  var setterName = _setterName(name);
+  while (type != objectType) {
+    final members = type.members;
+    if (members[name] is VariableMirror) return true;
+    if (members.containsKey(setterName)) return true;
+    if (members.containsKey(#noSuchMethod)) return true;
+    type = _safeSuperclass(type);
   }
   return false;
 }
 
+/**
+ * True if the type has a method, other than on Object.
+ * Doesn't consider noSuchMethod, unless [name] is `#noSuchMethod`.
+ */
+bool _hasMethod(ClassMirror type, Symbol name) {
+  while (type != objectType) {
+    final member = type.members[name];
+    if (member is MethodMirror && member.isRegularMethod) return true;
+    type = _safeSuperclass(type);
+  }
+  return false;
+}
+
+ClassMirror _safeSuperclass(ClassMirror type) {
+  try {
+    return type.superclass;
+  } on UnsupportedError catch (e) {
+    // TODO(jmesserly): dart2js throws this error when the type is not
+    // reflectable.
+    return objectType;
+  }
+}
+
 // From: https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
 
 final _pathRegExp = () {
@@ -307,3 +352,5 @@
   if (s[0] == '.') return false;
   return _pathRegExp.hasMatch(s);
 }
+
+final _logger = new Logger('observe.PathObserver');
diff --git a/pkg/observe/lib/src/to_observable.dart b/pkg/observe/lib/src/to_observable.dart
index d4b1668..4684935 100644
--- a/pkg/observe/lib/src/to_observable.dart
+++ b/pkg/observe/lib/src/to_observable.dart
@@ -2,7 +2,9 @@
 // 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.
 
-part of observe;
+library observe.src.to_observable;
+
+import 'package:observe/observe.dart';
 
 /**
  * Converts the [Iterable] or [Map] to an [ObservableList] or [ObservableMap],
@@ -34,7 +36,7 @@
 _toObservableDeep(value) {
   if (value is Observable) return value;
   if (value is Map) {
-    var result = new ObservableMap._createFromType(value);
+    var result = new ObservableMap.createFromType(value);
     value.forEach((k, v) {
       result[_toObservableDeep(k)] = _toObservableDeep(v);
     });
diff --git a/pkg/observe/lib/transform.dart b/pkg/observe/lib/transform.dart
index ede5a0d..5e261c0 100644
--- a/pkg/observe/lib/transform.dart
+++ b/pkg/observe/lib/transform.dart
@@ -256,11 +256,11 @@
 }
 
 SimpleIdentifier _getSimpleIdentifier(Identifier id) =>
-    id is PrefixedIdentifier ? (id as PrefixedIdentifier).identifier : id;
+    id is PrefixedIdentifier ? id.identifier : id;
 
 
 bool _hasKeyword(Token token, Keyword keyword) =>
-    token is KeywordToken && (token as KeywordToken).keyword == keyword;
+    token is KeywordToken && token.keyword == keyword;
 
 String _getOriginalCode(TextEditTransaction code, ASTNode node) =>
     code.original.substring(node.offset, node.end);
diff --git a/pkg/observe/pubspec.yaml b/pkg/observe/pubspec.yaml
index 36aa73b..d55ca35 100644
--- a/pkg/observe/pubspec.yaml
+++ b/pkg/observe/pubspec.yaml
@@ -11,7 +11,6 @@
   analyzer: any
   barback: any
   logging: any
-  meta: any
   path: any
   source_maps: any
 dev_dependencies:
diff --git a/pkg/observe/test/observe_test.dart b/pkg/observe/test/observe_test.dart
index 691634b..9376ed3 100644
--- a/pkg/observe/test/observe_test.dart
+++ b/pkg/observe/test/observe_test.dart
@@ -9,9 +9,6 @@
 import 'package:unittest/unittest.dart';
 import 'observe_test_utils.dart';
 
-// Note: this ensures we run the dartanalyzer on the @observe package.
-// @static-clean
-
 void main() {
   // Note: to test the basic Observable system, we use ObservableBox due to its
   // simplicity. We also test a variant that is based on dirty-checking.
diff --git a/pkg/observe/test/path_observer_test.dart b/pkg/observe/test/path_observer_test.dart
index c620204..91d68a1 100644
--- a/pkg/observe/test/path_observer_test.dart
+++ b/pkg/observe/test/path_observer_test.dart
@@ -213,6 +213,105 @@
     performMicrotaskCheckpoint();
     expect(values, [1, 2]);
   });
+
+  observeTest('errors thrown from getter/setter', () {
+    var model = new ObjectWithErrors();
+    var observer = new PathObserver(model, 'foo');
+
+    expect(() => observer.value, throws);
+    expect(model.getFooCalled, 1);
+
+    expect(() { observer.value = 123; }, throws);
+    expect(model.setFooCalled, [123]);
+  });
+
+  observeTest('object with noSuchMethod', () {
+    var model = new NoSuchMethodModel();
+    var observer = new PathObserver(model, 'foo');
+
+    expect(observer.value, 42);
+    observer.value = 'hi';
+    expect(model._foo, 'hi');
+    expect(observer.value, 'hi');
+
+    expect(model.log, [#foo, const Symbol('foo='), #foo]);
+
+    // These shouldn't throw
+    observer = new PathObserver(model, 'bar');
+    expect(observer.value, null, reason: 'path not found');
+    observer.value = 42;
+    expect(observer.value, null, reason: 'path not found');
+  });
+
+  observeTest('object with indexer', () {
+    var model = new IndexerModel();
+    var observer = new PathObserver(model, 'foo');
+
+    expect(observer.value, 42);
+    expect(model.log, ['[] foo']);
+    model.log.clear();
+
+    observer.value = 'hi';
+    expect(model.log, ['[]= foo hi']);
+    expect(model._foo, 'hi');
+
+    expect(observer.value, 'hi');
+
+    // These shouldn't throw
+    model.log.clear();
+    observer = new PathObserver(model, 'bar');
+    expect(observer.value, null, reason: 'path not found');
+    expect(model.log, ['[] bar']);
+    model.log.clear();
+
+    observer.value = 42;
+    expect(model.log, ['[]= bar 42']);
+    model.log.clear();
+  });
+}
+
+class ObjectWithErrors {
+  int getFooCalled = 0;
+  List setFooCalled = [];
+  @reflectable get foo {
+    getFooCalled++;
+    (this as dynamic).bar;
+  }
+  @reflectable set foo(value) {
+    setFooCalled.add(value);
+    (this as dynamic).bar = value;
+  }
+}
+
+class NoSuchMethodModel {
+  var _foo = 42;
+  List log = [];
+
+  noSuchMethod(Invocation invocation) {
+    final name = invocation.memberName;
+    log.add(name);
+    if (name == #foo && invocation.isGetter) return _foo;
+    if (name == const Symbol('foo=')) {
+      _foo = invocation.positionalArguments[0];
+      return null;
+    }
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class IndexerModel {
+  var _foo = 42;
+  List log = [];
+
+  operator [](index) {
+    log.add('[] $index');
+    if (index == 'foo') return _foo;
+  }
+
+  operator []=(index, value) {
+    log.add('[]= $index $value');
+    if (index == 'foo') _foo = value;
+  }
 }
 
 @reflectable
diff --git a/pkg/observe/test/transform_test.dart b/pkg/observe/test/transform_test.dart
index 064ac87..b42f578 100644
--- a/pkg/observe/test/transform_test.dart
+++ b/pkg/observe/test/transform_test.dart
@@ -161,7 +161,7 @@
   readInputAsString(id, {encoding}) => throw new UnimplementedError();
 
   static void _mockLogFn(AssetId asset, LogLevel level, String message,
-                         Span span) {
+                         span) {
     // Do nothing.
   }
 }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index e5a8df6..2a8bfdc 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -29,6 +29,7 @@
 collection_helpers/test/equality_test/04: Fail # Issue 1533
 collection_helpers/test/equality_test/05: Fail # Issue 1533
 collection_helpers/test/equality_test/none: Pass, Fail # Issue 14348
+intl/test/number_closure_test: Pass, CompileTimeError # Issue 14603
 
 [ $compiler == dart2js && $checked && $runtime == ie9 ]
 crypto/test/base64_test: Timeout # Issue 12486
@@ -55,6 +56,7 @@
 polymer/test/prop_attr_bind_reflection_test: Skip #uses dart:html
 polymer/test/prop_attr_reflection_test: Skip #uses dart:html
 polymer/test/publish_attributes_test: Skip #uses dart:html
+polymer/test/publish_inherited_properties_test: Skip #uses dart:html
 polymer/test/register_test: Skip #uses dart:html
 polymer/test/take_attributes_test: Skip #uses dart:html
 polymer/test/template_distribute_dynamic_test: Skip #uses dart:html
@@ -84,7 +86,6 @@
 stack_trace/test/trace_test: Fail # http://dartbug.com/12380
 crypto/test/sha256_test: Pass, Fail # Issue 12502
 crypto/test/hmac_sha256_test: Pass, Fail # Issue 12502
-polymer_expressions/test/globals_test: Fail # Issue 13890
 
 [ $runtime == ie9 || $runtime == ie10 ]
 polymer/example/canonicalization/test/canonicalization_deploy_test: Pass, Timeout
@@ -102,11 +103,11 @@
 polymer/test/prop_attr_reflection_test: Pass, Timeout # Issue 13260
 polymer/test/prop_attr_bind_reflection_test: Pass, Timeout # Issue 13260
 polymer/test/publish_attributes_test: Pass, Timeout # Issue 13260
+polymer/test/publish_inherited_properties_test: Pass, Timeout # Issue 13260
 polymer/test/register_test: Pass, Timeout # Issue 13260
 polymer/test/take_attributes_test: Pass, Timeout # Issue 13260
 polymer/test/template_distribute_dynamic_test: Pass, Timeout # Issue 13260
 polymer/test/unbind_test: Pass, Timeout # Issue 13260
-polymer_expressions/test/globals_test: Fail # Issue 13890
 
 # Skip browser-specific tests on VM
 [ $runtime == vm ]
@@ -149,7 +150,9 @@
 # printed. Minified versions of these tests exist that test the behavior when
 # minified.
 unittest/test/*_unminified_test: Skip # DO NOT COPY THIS UNLESS YOU WORK ON DART2JS
-analyzer/test/generated/ast_test: Fail # Issue 12336
+
+ # Issue 9217: Uses unspecified Type.toString.
+analyzer/test/generated/ast_test: Fail
 
 [ $compiler == dart2js && $browser ]
 stack_trace/test/vm_test: Fail, OK # VM-specific traces
@@ -270,8 +273,6 @@
 unittest/test/unittest_test_returning_future_using_runasync_test: Fail # 13921
 unittest/test/unittest_testcases_immutable_test: Fail # 13921
 unittest/test/unitttest_group_name_test: Fail # 13921
-template_binding/test/template_element_test: Pass, Fail # Flaky, 14330
-polymer_expressions/test/bindings_test: Pass, Fail # Flaky, 14330
 polymer/test/custom_event_test: Pass, Crash # 14360
 polymer/example/canonicalization/test/canonicalization_deploy_test: Fail, OK # tests deploy only behavior
 
@@ -290,7 +291,7 @@
 scheduled_test/test/scheduled_server_test: Skip # Uses dart:io
 
 [ $browser || $runtime == vm ]
-unittest/test/missing_tick_test: Fail, OK # This test should fail, not time out.
+unittest/test/missing_tick_test: Timeout, Fail, OK # This test should fail, not time out.
 
 # Issue http://dartbug.com/12930
 [ $runtime == vm ]
@@ -303,14 +304,82 @@
 [ $compiler == dartanalyzer ]
 # pkg issue 13944; Missing inherited member 'Observable._mirror'
 custom_element/test/analyzer_test: fail
-template_binding/test/analyzer_test: fail
-observe/test/observe_test: fail
 
 [ $compiler == dart2analyzer ]
 # pkg issue 13944; Missing inherited members: 'ListChangeRecord.addedCount' and 'ListChangeRecord.removedCount'
 custom_element/test/analyzer_test: fail
-template_binding/test/analyzer_test: fail
-observe/test/observe_test: fail
 
-# pkg issue 13945; Missing inherited member 'Trace.frames'
-observe/test/observe_test: fail
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+barback/test/asset_id_test: StaticWarning
+barback/test/asset_set_test: StaticWarning
+barback/test/asset_test: StaticWarning
+barback/test/cancelable_future_test: StaticWarning
+barback/test/mutliset_test: StaticWarning
+barback/test/package_graph/add_remove_transform_test: StaticWarning
+barback/test/package_graph/errors_test: StaticWarning
+barback/test/package_graph/get_all_assets_test: StaticWarning
+barback/test/package_graph/group_test: StaticWarning
+barback/test/package_graph/many_parallel_transformers_test: StaticWarning
+barback/test/package_graph/repetition_test: StaticWarning
+barback/test/package_graph/source_test: StaticWarning
+barback/test/package_graph/transform_test: StaticWarning
+barback/test/stream_pool_test: StaticWarning
+barback/test/stream_replayer_test: StaticWarning
+barback/test/too_many_open_files_test: StaticWarning
+barback/test/transformer_test: StaticWarning
+csslib/test/big_1_test: StaticWarning
+csslib/test/compiler_test: StaticWarning
+csslib/test/declaration_test: StaticWarning
+csslib/test/error_test: StaticWarning
+csslib/test/extend_test: StaticWarning
+csslib/test/mixin_test: StaticWarning
+csslib/test/nested_test: StaticWarning
+csslib/test/selector_test: StaticWarning
+csslib/test/var_test: StaticWarning
+csslib/test/visitor_test: StaticWarning
+docgen/test/single_library_test: StaticWarning
+http_server/test/http_body_test: StaticWarning
+http_server/test/http_multipart_test: StaticWarning
+http_server/test/virtual_directory_test: StaticWarning
+http_server/test/virtual_host_test: StaticWarning
+http/test/client_test: StaticWarning
+http/test/http_test: StaticWarning
+http/test/mock_client_test: StaticWarning
+http/test/multipart_test: StaticWarning
+http/test/request_test: StaticWarning
+http/test/streamed_request_test: StaticWarning
+intl/test/date_time_format_file_even_test: StaticWarning
+intl/test/date_time_format_file_odd_test: StaticWarning
+intl/test/date_time_format_http_request_test: StaticWarning
+intl/test/date_time_format_local_even_test: StaticWarning
+intl/test/date_time_format_local_odd_test: StaticWarning
+observe/test/transform_test: StaticWarning
+polymer/test/build/*: StaticWarning
+polymer/test/build/utils_test: Pass
+scheduled_test/test/descriptor/async_test: StaticWarning
+scheduled_test/test/descriptor/directory_test: StaticWarning
+scheduled_test/test/descriptor/file_test: StaticWarning
+scheduled_test/test/descriptor/nothing_test: StaticWarning
+scheduled_test/test/descriptor/pattern_test: StaticWarning
+scheduled_test/test/scheduled_future_matchers_test: StaticWarning
+scheduled_test/test/scheduled_process_test: StaticWarning
+scheduled_test/test/scheduled_test/abort_test: StaticWarning
+scheduled_test/test/scheduled_test/current_schedule_current_task_test: StaticWarning
+scheduled_test/test/scheduled_test/current_schedule_errors_test: StaticWarning
+scheduled_test/test/scheduled_test/current_schedule_state_test: StaticWarning
+scheduled_test/test/scheduled_test/nested_task_test: StaticWarning
+scheduled_test/test/scheduled_test/on_complete_test: StaticWarning
+scheduled_test/test/scheduled_test/on_exception_test: StaticWarning
+scheduled_test/test/scheduled_test/out_of_band_task_test: StaticWarning
+scheduled_test/test/scheduled_test/set_up_test: StaticWarning
+scheduled_test/test/scheduled_test/signal_error_test: StaticWarning
+scheduled_test/test/scheduled_test/simple_test: StaticWarning
+scheduled_test/test/scheduled_test/task_return_value_test: StaticWarning
+scheduled_test/test/scheduled_test/timeout_test: StaticWarning
+scheduled_test/test/scheduled_test/wrap_async_test: StaticWarning
+scheduled_test/test/scheduled_test/wrap_future_test: StaticWarning
+unittest/test/matchers_test: StaticWarning
+unittest/test/mock_test: StaticWarning
+watcher/test/directory_watcher_test: StaticWarning
+watcher/test/no_subscription_test: StaticWarning
+watcher/test/ready_test: StaticWarning
diff --git a/pkg/polymer/lib/src/build/script_compactor.dart b/pkg/polymer/lib/src/build/script_compactor.dart
index 01885f7..8ac8fd0 100644
--- a/pkg/polymer/lib/src/build/script_compactor.dart
+++ b/pkg/polymer/lib/src/build/script_compactor.dart
@@ -81,7 +81,10 @@
         mainScriptTag.attributes['src'] = 
             path.url.basename(bootstrapId.path);
 
-        libraries.add(mainLibraryId);
+        // TODO(sigmund): stop renaming the file (see dartbug.com/14554)
+        var modifiedMainId = mainLibraryId.addExtension('_modified.dart');
+
+        libraries.add(modifiedMainId);
         var urls = libraries.map((id) => assetUrlFor(id, bootstrapId, logger))
             .where((url) => url != null).toList();
         var buffer = new StringBuffer()..writeln(MAIN_HEADER);
@@ -95,12 +98,17 @@
             ..writeln('  configureForDeployment([')
             ..writeAll(urls.map((url) => "      '$url',\n"))
             ..writeln('    ]);')
-            ..writeln('  i${i - 1}.main();')
+            ..writeln('  i${i - 1}.polymerMainWrapper();')
             ..writeln('}');
 
         transform.addOutput(new Asset.fromString(
               bootstrapId, buffer.toString()));
         transform.addOutput(new Asset.fromString(id, document.outerHtml));
+
+        return transform.readInputAsString(mainLibraryId).then((contents) {
+          transform.addOutput(new Asset.fromString(modifiedMainId,
+              '$contents\n\npolymerMainWrapper() => main();\n'));
+        });
       });
     });
   }
diff --git a/pkg/polymer/lib/src/declaration.dart b/pkg/polymer/lib/src/declaration.dart
index ba2beff..bb6b225 100644
--- a/pkg/polymer/lib/src/declaration.dart
+++ b/pkg/polymer/lib/src/declaration.dart
@@ -242,9 +242,13 @@
   void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) {
     // get properties to publish
     if (superDecl != null && superDecl._publish != null) {
+      // Dart note: even though we walk the type hierarchy in
+      // _getPublishedProperties, this will additionally include any names
+      // published via the `attributes` attribute.
       _publish = new Map.from(superDecl._publish);
     }
-    _publish = _getProperties(cls, _publish, (x) => x is PublishedProperty);
+
+    _publish = _getPublishedProperties(cls, _publish);
 
     // merge names from 'attributes' attribute
     var attrs = attributes['attributes'];
@@ -491,12 +495,14 @@
 
 final _objectType = reflectClass(Object);
 
-Map _getProperties(ClassMirror cls, Map props, bool matches(metadata)) {
+Map _getPublishedProperties(ClassMirror cls, Map props) {
+  if (cls == _objectType) return props;
+  props = _getPublishedProperties(cls.superclass, props);
   for (var field in cls.variables.values) {
     if (field.isFinal || field.isStatic || field.isPrivate) continue;
 
     for (var meta in field.metadata) {
-      if (matches(meta.reflectee)) {
+      if (meta.reflectee is PublishedProperty) {
         if (props == null) props = {};
         props[field.simpleName] = field;
         break;
@@ -508,7 +514,7 @@
     if (getter.isStatic || getter.isPrivate) continue;
 
     for (var meta in getter.metadata) {
-      if (matches(meta.reflectee)) {
+      if (meta.reflectee is PublishedProperty) {
         if (_hasSetter(cls, getter)) {
           if (props == null) props = {};
           props[getter.simpleName] = getter;
diff --git a/pkg/polymer/lib/src/instance.dart b/pkg/polymer/lib/src/instance.dart
index e46fda3..348a61f 100644
--- a/pkg/polymer/lib/src/instance.dart
+++ b/pkg/polymer/lib/src/instance.dart
@@ -437,6 +437,8 @@
   }
 
   Map<String, NodeBinding> get bindings => nodeBindFallback(this).bindings;
+  TemplateInstance get templateInstance =>
+      nodeBindFallback(this).templateInstance;
 
   void unbind(String name) => nodeBindFallback(this).unbind(name);
 
@@ -579,7 +581,7 @@
     }
   }
 
-  void unbindProperty(String name) => unregisterObserver(name);
+  bool unbindProperty(String name) => unregisterObserver(name);
 
   void unbindAllProperties() {
     if (_propertyObserver != null) {
@@ -738,38 +740,39 @@
   // we implement this by wrapping/overriding getBinding instead.
   // TODO(sorvell): we're patching the syntax while evaluating
   // event bindings. we'll move this to a better spot when that's done
-  static getBindingWithEvents(
-      model, String path, name, node, originalGetBinding) {
+  static PrepareBindingFunction prepareBinding(String path, String name, node,
+      originalPrepareBinding) {
+
     // if lhs an event prefix,
-    if (name is! String || !_hasEventPrefix(name)) {
-      return originalGetBinding(model, path, name, node);
-    }
+    if (!_hasEventPrefix(name)) return originalPrepareBinding(path, name, node);
 
     // provide an event-binding callback.
-    // return (model, name, node) {
-    if (_eventsLog.isLoggable(Level.FINE)) {
-      _eventsLog.fine('event: [${node.localName}].$name => '
-          '[${model.localName}].$path())');
-    }
-    var eventName = _removeEventPrefix(name);
-    // TODO(sigmund): polymer.js dropped event translations. reconcile?
-    var translated = _eventTranslations[eventName];
-    eventName = translated != null ? translated : eventName;
-    return node.on[eventName].listen((event) {
-      var ctrlr = _findController(node);
-      if (ctrlr is! Polymer) return;
-      var obj = ctrlr;
-      var method = path;
-      if (path[0] == '@') {
-        obj = model;
-        // Dart note: using getBinding gets us the result of evaluating the
-        // original path (without the @) as a normal expression.
-        method = originalGetBinding(model, path.substring(1), name, node).value;
+    return (model, node) {
+      if (_eventsLog.isLoggable(Level.FINE)) {
+        _eventsLog.fine('event: [$node].$name => [$model].$path())');
       }
-      var detail = event is CustomEvent ?
-          (event as CustomEvent).detail : null;
-      ctrlr.dispatchMethod(obj, method, [event, detail, node]);
-    });
+      var eventName = _removeEventPrefix(name);
+      // TODO(sigmund): polymer.js dropped event translations. reconcile?
+      var translated = _eventTranslations[eventName];
+      eventName = translated != null ? translated : eventName;
+
+      // TODO(jmesserly): returning a StreamSubscription as the model is quite
+      // strange. package:template_binding doesn't have any cleanup logic to
+      // handle that.
+      return node.on[eventName].listen((event) {
+        var ctrlr = _findController(node);
+        if (ctrlr is! Polymer) return;
+        var obj = ctrlr;
+        var method = path;
+        if (path[0] == '@') {
+          obj = model;
+          method = new PathObserver(model, path.substring(1)).value;
+        }
+        var detail = event is CustomEvent ?
+            (event as CustomEvent).detail : null;
+        ctrlr.dispatchMethod(obj, method, [event, detail, node]);
+      });
+    };
   }
 
   // TODO(jmesserly): this won't find the correct host unless the ShadowRoot
@@ -902,7 +905,7 @@
         decl = decl.superDeclaration;
       }
       if (cssText.length > 0) {
-        var style = this.element.cssTextToScopeStyle(cssText.toString(),
+        var style = decl.cssTextToScopeStyle(cssText.toString(),
               _STYLE_CONTROLLER_SCOPE);
         // TODO(sorvell): for now these styles are not shimmed
         // but we may need to shim them
@@ -1074,8 +1077,6 @@
 }
 
 class _PolymerExpressionsWithEventDelegate extends PolymerExpressions {
-  getBinding(model, String path, name, node) {
-    return Polymer.getBindingWithEvents(
-        model, path, name, node, super.getBinding);
-  }
+  prepareBinding(String path, name, node) =>
+      Polymer.prepareBinding(path, name, node, super.prepareBinding);
 }
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart
index c999660..eb0a726 100644
--- a/pkg/polymer/lib/src/loader.dart
+++ b/pkg/polymer/lib/src/loader.dart
@@ -32,12 +32,13 @@
  * The urls in [libraries] can be absolute or relative to
  * `currentMirrorSystem().isolate.rootLibrary.uri`.
  */
-void initPolymer() {
+Zone initPolymer() {
   if (_useDirtyChecking) {
-    dirtyCheckZone().run(_initPolymerOptimized);
-  } else {
-    _initPolymerOptimized();
+    return dirtyCheckZone()..run(_initPolymerOptimized);
   }
+
+  _initPolymerOptimized();
+  return Zone.current;
 }
 
 /**
diff --git a/pkg/polymer/lib/transformer.dart b/pkg/polymer/lib/transformer.dart
index 4d132cf..a4f0e10 100644
--- a/pkg/polymer/lib/transformer.dart
+++ b/pkg/polymer/lib/transformer.dart
@@ -35,26 +35,29 @@
 
 
 TransformOptions _parseArgs(Map args) {
-  var entryPoints;
-  if (args.containsKey('entry_points')) {
-    entryPoints = [];
-    var value = args['entry_points'];
-    bool error;
-    if (value is List) {
-      entryPoints = value;
-      error = value.any((e) => e is! String);
-    } else if (value is String) {
-      entryPoints = [value];
-      error = false;
-    } else {
-      error = true;
-    }
+  return new TransformOptions(
+      entryPoints: _readEntrypoints(args['entry_points']),
+      directlyIncludeJS: args['js'] != false, // default to true
+      contentSecurityPolicy: args['csp'] == true); // default to false
+}
 
-    if (error) {
-      print('Invalid value for "entry_points" in the polymer transformer.');
-    }
+_readEntrypoints(value) {
+  if (value == null) return null;
+  var entryPoints = [];
+  bool error;
+  if (value is List) {
+    entryPoints = value;
+    error = value.any((e) => e is! String);
+  } else if (value is String) {
+    entryPoints = [value];
+    error = false;
+  } else {
+    error = true;
   }
-  return new TransformOptions(entryPoints: entryPoints);
+  if (error) {
+    print('Invalid value for "entry_points" in the polymer transformer.');
+  }
+  return entryPoints;
 }
 
 List<List<Transformer>> _createDeployPhases(TransformOptions options) {
diff --git a/pkg/polymer/test/bind_test.dart b/pkg/polymer/test/bind_test.dart
index e3f25ca..1fd6515 100644
--- a/pkg/polymer/test/bind_test.dart
+++ b/pkg/polymer/test/bind_test.dart
@@ -50,5 +50,5 @@
 
   setUp(() => Polymer.onReady);
 
-  test('ready called', () => query('x-foo').onTestDone);
+  test('ready called', () => (query('x-foo') as XFoo).onTestDone);
 }
diff --git a/pkg/polymer/test/build/all_phases_test.dart b/pkg/polymer/test/build/all_phases_test.dart
index 9a1fccd..4b6b759 100644
--- a/pkg/polymer/test/build/all_phases_test.dart
+++ b/pkg/polymer/test/build/all_phases_test.dart
@@ -33,7 +33,7 @@
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
           '<script type="application/dart" src="a.dart"></script>',
-      'a|web/test.dart': _sampleObservable('A', 'foo'),
+      'a|web/a.dart': _sampleObservable('A', 'foo'),
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
@@ -45,16 +45,18 @@
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
-          import 'a.dart' as i0;
+          import 'a.dart_modified.dart' as i0;
 
           void main() {
             configureForDeployment([
-                'a.dart',
+                'a.dart_modified.dart',
               ]);
-            i0.main();
+            i0.polymerMainWrapper();
           }
           '''.replaceAll('\n          ', '\n'),
-      'a|web/test.dart': _sampleObservableOutput('A', 'foo'),
+      'a|web/a.dart': _sampleObservableOutput('A', 'foo'),
+      'a|web/a.dart_modified.dart':
+          _sampleObservableOutput('A', 'foo', includeMain: true),
     });
 
   testPhases('single inline script', phases, {
@@ -73,16 +75,19 @@
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
-          import 'test.html.0.dart' as i0;
+          import 'test.html.0.dart_modified.dart' as i0;
 
           void main() {
             configureForDeployment([
-                'test.html.0.dart',
+                'test.html.0.dart_modified.dart',
               ]);
-            i0.main();
+            i0.polymerMainWrapper();
           }
           '''.replaceAll('\n          ', '\n'),
-      'a|web/test.html.0.dart': _sampleObservableOutput("B", "bar"),
+      'a|web/test.html.0.dart':
+          _sampleObservableOutput("B", "bar"),
+      'a|web/test.html.0.dart_modified.dart':
+          _sampleObservableOutput("B", "bar", includeMain: true),
     });
 
   testPhases('several scripts', phases, {
@@ -114,16 +119,18 @@
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
-          import 'a.dart' as i0;
+          import 'a.dart_modified.dart' as i0;
 
           void main() {
             configureForDeployment([
-                'a.dart',
+                'a.dart_modified.dart',
               ]);
-            i0.main();
+            i0.polymerMainWrapper();
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/a.dart': _sampleObservableOutput('A', 'foo'),
+      'a|web/a.dart_modified.dart':
+          _sampleObservableOutput('A', 'foo', includeMain: true),
       'a|web/test.html.0.dart': _sampleObservableOutput("B", "bar"),
       'a|web/test.html.1.dart': _sampleObservableOutput("C", "car"),
     });
@@ -153,17 +160,19 @@
       'a|web/index.html_bootstrap.dart':
           '''$MAIN_HEADER
           import 'test2.html.0.dart' as i0;
-          import 'b.dart' as i1;
+          import 'b.dart_modified.dart' as i1;
 
           void main() {
             configureForDeployment([
                 'test2.html.0.dart',
-                'b.dart',
+                'b.dart_modified.dart',
               ]);
-            i1.main();
+            i1.polymerMainWrapper();
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/test2.html.0.dart': _sampleObservableOutput("A", "foo"),
+      'a|web/test2.html.0.dart_modified.dart':
+          _sampleObservableOutput("A", "foo", includeMain: true),
       'a|web/b.dart': _sampleObservableOutput('B', 'bar'),
     });
 }
@@ -178,7 +187,8 @@
 }
 ''';
 
-String _sampleObservableOutput(String className, String field) =>
+String _sampleObservableOutput(String className, String field,
+    {bool includeMain: false}) =>
     "library ${className}_$field;\n"
     "import 'package:observe/observe.dart';\n\n"
     "class $className extends ChangeNotifier {\n"
@@ -188,4 +198,5 @@
       "__\$$field = notifyPropertyChange(#$field, __\$$field, value); "
       "}\n"
     "  $className($field) : __\$$field = $field;\n"
-    "}\n";
+    "}\n"
+    "${includeMain ? '\n\npolymerMainWrapper() => main();\n' : ''}";
diff --git a/pkg/polymer/test/build/script_compactor_test.dart b/pkg/polymer/test/build/script_compactor_test.dart
index 32bd762..946c90d 100644
--- a/pkg/polymer/test/build/script_compactor_test.dart
+++ b/pkg/polymer/test/build/script_compactor_test.dart
@@ -36,6 +36,7 @@
           '<!DOCTYPE html><html><head>'
           '<script type="application/dart" src="a.dart"></script>',
       'a|web/test.html.scriptUrls': '[]',
+      'a|web/a.dart': 'library a;\nmain(){}',
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
@@ -45,15 +46,19 @@
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
-          import 'a.dart' as i0;
+          import 'a.dart_modified.dart' as i0;
 
           void main() {
             configureForDeployment([
-                'a.dart',
+                'a.dart_modified.dart',
               ]);
-            i0.main();
+            i0.polymerMainWrapper();
           }
           '''.replaceAll('\n          ', '\n'),
+      'a|web/a.dart': 'library a;\nmain(){}',
+      'a|web/a.dart_modified.dart':
+          'library a;\nmain(){}'
+          '\n\npolymerMainWrapper() => main();\n',
     });
 
   testPhases('several scripts', phases, {
@@ -64,6 +69,7 @@
           '</div>',
       'a|web/test.html.scriptUrls':
           '[["a", "web/a.dart"],["a", "web/b.dart"],["a", "web/c.dart"]]',
+      'a|web/d.dart': 'library d;\nmain(){}',
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head></head><body><div>'
@@ -77,16 +83,16 @@
           import 'a.dart' as i0;
           import 'b.dart' as i1;
           import 'c.dart' as i2;
-          import 'd.dart' as i3;
+          import 'd.dart_modified.dart' as i3;
 
           void main() {
             configureForDeployment([
                 'a.dart',
                 'b.dart',
                 'c.dart',
-                'd.dart',
+                'd.dart_modified.dart',
               ]);
-            i3.main();
+            i3.polymerMainWrapper();
           }
           '''.replaceAll('\n          ', '\n'),
     });
diff --git a/pkg/polymer/test/event_handlers_test.dart b/pkg/polymer/test/event_handlers_test.dart
index 779ccb6..8267e0a 100644
--- a/pkg/polymer/test/event_handlers_test.dart
+++ b/pkg/polymer/test/event_handlers_test.dart
@@ -7,10 +7,11 @@
 import 'dart:async';
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
+import 'package:logging/logging.dart';
 import 'package:polymer/polymer.dart';
 import 'package:template_binding/template_binding.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
 
 @CustomTag('x-test')
 class XTest extends PolymerElement {
@@ -19,12 +20,9 @@
   String _lastMessage;
   List list1 = [];
   List list2 = [];
-  final _ready = new Completer();
   Future _onTestDone;
 
-  XTest.created() : super.created() {
-    _onTestDone = _ready.future.then(_runTest);
-  }
+  XTest.created() : super.created();
 
   ready() {
     super.ready();
@@ -33,7 +31,8 @@
       list1.add(model);
       list2.add(model);
     }
-    _ready.complete();
+
+    _onTestDone = new Future.sync(_runTests);
   }
 
   hostTapAction(event, detail, node) => _logEvent(event);
@@ -57,7 +56,7 @@
     _lastMessage = message;
   }
 
-  _runTest(_) {
+  Future _runTests() {
     fire('tap', toNode: $['div']);
     expect(_testCount, 2, reason: 'event heard at div and host');
     expect(_lastEvent, 'tap', reason: 'tap handled');
@@ -70,6 +69,7 @@
     fire('scroll', toNode: $['list'], canBubble: false);
     expect(_testCount, 5, reason: 'event heard by list');
     expect(_lastEvent, 'scroll', reason: 'scroll handled');
+
     return onMutation($['list']).then((_) {
       var l1 = $['list'].querySelectorAll('.list1')[4];
       fire('tap', toNode: l1, canBubble: false);
@@ -103,6 +103,9 @@
 }
 
 main() {
+  Logger.root..level = Level.FINE
+      ..onRecord.listen((m) => print('${m.loggerName} ${m.message}'));
+
   initPolymer();
 }
 
@@ -110,6 +113,8 @@
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
-  test('events handled', () => (query('x-test') as XTest)._onTestDone);
+  test('events handled', () {
+    XTest test = query('x-test');
+    expect(test._onTestDone, isNotNull, reason: 'ready was called');
+  });
 }
-
diff --git a/pkg/polymer/test/publish_attributes_test.dart b/pkg/polymer/test/publish_attributes_test.dart
index c6ea12a..b22132e 100644
--- a/pkg/polymer/test/publish_attributes_test.dart
+++ b/pkg/polymer/test/publish_attributes_test.dart
@@ -48,8 +48,8 @@
   setUp(() => Polymer.onReady);
 
   test('published properties', () {
-    published(tag) =>
-        query('polymer-element[name=$tag]').publishedProperties;
+    published(tag) => (query('polymer-element[name=$tag]')
+        as PolymerDeclaration).publishedProperties;
 
     expect(published('x-foo'), [#Foo, #baz]);
     expect(published('x-bar'), [#Foo, #baz, #Bar]);
diff --git a/pkg/polymer/test/publish_inherited_properties_test.dart b/pkg/polymer/test/publish_inherited_properties_test.dart
new file mode 100644
index 0000000..7eec80a
--- /dev/null
+++ b/pkg/polymer/test/publish_inherited_properties_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2013, 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.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+// Dart note: unlike JS, you can't publish something that doesn't
+// have a corresponding field because we can't dynamically add properties.
+// So we define XFoo and XBar types here.
+class XFoo extends PolymerElement {
+  XFoo.created() : super.created();
+
+  @published var Foo;
+}
+
+class XBar extends XFoo {
+  XBar.created() : super.created();
+
+  @published var Bar;
+}
+
+@CustomTag('x-zot')
+class XZot extends XBar {
+  XZot.created() : super.created();
+
+  var m;
+  @published int zot = 3;
+}
+
+// TODO(sigmund): uncomment this part of the test too (see dartbug.com/14559)
+// class XWho extends XZot {
+//   XWho.created() : super.created();
+//
+//   @published var zap;
+// }
+
+@CustomTag('x-squid')
+class XSquid extends XZot {
+  XSquid.created() : super.created();
+
+  @published int baz = 13;
+  @published int zot = 5;
+  @published int squid = 7;
+}
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('published properties', () {
+    published(tag) => (query('polymer-element[name=$tag]')
+        as PolymerDeclaration).publishedProperties;
+
+    expect(published('x-zot'), [#Foo, #Bar, #zot, #m]);
+    expect(published('x-squid'), [#Foo, #Bar, #zot, #m, #baz, #squid]);
+    expect(published('x-noscript'), [#Foo, #Bar, #zot, #m]);
+    // TODO(sigmund): uncomment, see above
+    // expect(published('x-squid'), [#Foo, #Bar, #zot, #zap, #baz, #squid]);
+  });
+}
diff --git a/pkg/polymer/test/publish_inherited_properties_test.html b/pkg/polymer/test/publish_inherited_properties_test.html
new file mode 100644
index 0000000..8fafba7
--- /dev/null
+++ b/pkg/polymer/test/publish_inherited_properties_test.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, 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.
+-->
+<html>
+  <head>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
+    <title>publish inherited properties</title>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+    <polymer-element name="x-zot" attributes="m">
+    </polymer-element>
+
+    <polymer-element name="x-squid" extends="x-zot" attributes="squid">
+    </polymer-element>
+
+    <polymer-element name="x-noscript" extends="x-zot" noscript>
+    </polymer-element>
+
+  <script type="application/dart" src="publish_inherited_properties_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/test/register_test.dart b/pkg/polymer/test/register_test.dart
index 070ee0f..8afb734 100644
--- a/pkg/polymer/test/register_test.dart
+++ b/pkg/polymer/test/register_test.dart
@@ -23,8 +23,8 @@
 }
 
 @CustomTag('x-div-two')
-class XDiv2lElement extends XDivElement {
-  XDiv2lElement.created() : super.created();
+class XDiv2Element extends XDivElement {
+  XDiv2Element.created() : super.created();
 }
 
 main() {
diff --git a/pkg/polymer/test/template_distribute_dynamic_test.dart b/pkg/polymer/test/template_distribute_dynamic_test.dart
index 86c469e..e80c624 100644
--- a/pkg/polymer/test/template_distribute_dynamic_test.dart
+++ b/pkg/polymer/test/template_distribute_dynamic_test.dart
@@ -58,5 +58,5 @@
 
   setUp(() => Polymer.onReady);
 
-  test('inserted called', () => query('x-test').onTestDone);
+  test('inserted called', () => (query('x-test') as XTest).onTestDone);
 }
diff --git a/pkg/polymer_expressions/README.md b/pkg/polymer_expressions/README.md
index 9cc3da4..6f0db01 100644
--- a/pkg/polymer_expressions/README.md
+++ b/pkg/polymer_expressions/README.md
@@ -48,7 +48,7 @@
 
 [mdv]: http://www.polymer-project.org/platform/mdv.html
 
-### Custom Binding Syntaxes with BindingDelegate
+### Custom binding syntaxes with binding delegate
 
 While MDV's built-in syntax is very basic, it does allow custom syntaxes called
 "binding delegates" to be installed and used. A binding delegate can interpret
@@ -81,7 +81,7 @@
 
     import 'package:polymer_expressions/polymer_expressions.dart';
 
-### Registering a Binding Delegate
+### Registering a binding delegate
 
 **Polymer Expressions are now the default syntax for `<polymer-element>` custom
 elements.**
@@ -106,7 +106,7 @@
     }
 ```
 
-### Registering Top-Level Variables
+### Registering top-level variables
 
 Before a top-level variable can be used, it must be registered. The
 PolymerExpressions constructor takes a map of named values to use as variables.
@@ -124,7 +124,7 @@
 
 ## Features
 
-### The Model and Scope
+### The model and scope
 
 Polymer Expressions allow binding to more than just the model assigned to a
 template instance. Top-level variables can be defined so that you can use
@@ -132,7 +132,7 @@
 model are held together in a container called a Scope. Scopes can be nested,
 which happens when template tags are nested.
 
-### Two-way Bindings
+### Two-way bindings
 
 Bindings can be used to modify the data model based on events in the DOM. The
 most common case is to bind an &lt;input&gt; element's value field to a model
@@ -177,7 +177,7 @@
 
 ## Syntax
 
-### Property Access
+### Property access
 
 Properties on the model and in the scope are looked up via simple property
 names, like `foo`. Property names are looked up first in the top-level
@@ -200,7 +200,7 @@
 
 List literals are planned, see [issue 9](https://github.com/dart-lang/polymer_expressions/issues/9)
 
-### Functions and Methods
+### Functions and methods
 
 If a property is a function in the scope, a method on the model, or a method on
 an object, it can be invoked with standard function syntax. Functions and
@@ -224,7 +224,7 @@
 
 Expressions do not support bitwise operators such as &, |, << and >>, or increment/decrement operators (++ and --)
 
-### List and Map Indexing
+### List and Map indexing
 
 List and Map like objects can be accessed via the index operator: []
 
@@ -238,7 +238,7 @@
 and `people.john`. This ensures that access to properties and methods on Lists
 and Maps is preserved.
 
-### Filters and Transformers
+### Filters and transformers
 
 A filter is a function that transforms a value into another, used via the pipe
 syntax: `value | filter` Any function that takes exactly one argument can be
@@ -254,7 +254,7 @@
 has an inverse function. Transformers must extend or implement the `Transformer`
 class, which has `forward()` and `reverse()` methods.
 
-### Repeating Templates
+### Repeating templates
 
 A template can be repeated by using the "repeat" attribute with a binding. The
 binding can either evaluate to an Iterable, in which case the template is
diff --git a/pkg/polymer_expressions/lib/filter.dart b/pkg/polymer_expressions/lib/filter.dart
index cd9b932..c972584 100644
--- a/pkg/polymer_expressions/lib/filter.dart
+++ b/pkg/polymer_expressions/lib/filter.dart
@@ -10,14 +10,15 @@
 
   T forward(V v);
   V reverse(T t);
-  Transformer<V, T> get inverse => new _InverseTransformer<V, T>(this);
+  Transformer<V, T> get inverse => new _InverseTransformer/*<V, T>*/(this);
 }
 
-class _InverseTransformer<V, T> implements Transformer<V, T> {
-  final Transformer<T, V> _t;
+// TODO(jmesserly): restore types when Issue 14094 is fixed.
+class _InverseTransformer/*<V, T>*/ implements Transformer/*<V, T>*/ {
+  final Transformer/*<T, V>*/ _t;
   _InverseTransformer(this._t);
 
-  V forward(T v) => _t.reverse(v);
-  T reverse(V t) => _t.forward(t);
-  Transformer<T, V> get inverse => _t;
+  /*V*/ forward(/*T*/ v) => _t.reverse(v);
+  /*T*/ reverse(/*V*/ t) => _t.forward(t);
+  Transformer/*<T, V>*/ get inverse => _t;
 }
diff --git a/pkg/polymer_expressions/lib/polymer_expressions.dart b/pkg/polymer_expressions/lib/polymer_expressions.dart
index 3f70c4b..354fb5e 100644
--- a/pkg/polymer_expressions/lib/polymer_expressions.dart
+++ b/pkg/polymer_expressions/lib/polymer_expressions.dart
@@ -67,28 +67,25 @@
       : globals = (globals == null) ?
           new Map<String, Object>.from(DEFAULT_GLOBALS) : globals;
 
-  _Binding getBinding(model, String path, name, node) {
+  prepareBinding(String path, name, node) {
     if (path == null) return null;
     var expr = new Parser(path).parse();
-    if (model is! Scope) {
-      model = new Scope(model: model, variables: globals);
-    }
-    if (node is Element && name == "class") {
-      return new _Binding(expr, model, _classAttributeConverter);
-    }
-    if (node is Element && name == "style") {
-      return new _Binding(expr, model, _styleAttributeConverter);
-    }
-    return new _Binding(expr, model);
+    return (model, node) {
+      if (model is! Scope) {
+        model = new Scope(model: model, variables: globals);
+      }
+      if (node is Element && name == "class") {
+        return new _Binding(expr, model, _classAttributeConverter);
+      }
+      if (node is Element && name == "style") {
+        return new _Binding(expr, model, _styleAttributeConverter);
+      }
+      return new _Binding(expr, model);
+    };
   }
 
-  getInstanceModel(Element template, model) {
-    if (model is! Scope) {
-      var _scope = new Scope(model: model, variables: globals);
-      return _scope;
-    }
-    return model;
-  }
+  prepareInstanceModel(Element template) => (model) =>
+      model is Scope ? model : new Scope(model: model, variables: globals);
 }
 
 class _Binding extends ChangeNotifier {
diff --git a/pkg/polymer_expressions/test/bindings_test.dart b/pkg/polymer_expressions/test/bindings_test.dart
index 9851ded..26a3a14 100644
--- a/pkg/polymer_expressions/test/bindings_test.dart
+++ b/pkg/polymer_expressions/test/bindings_test.dart
@@ -37,7 +37,7 @@
     observeTest('should update binding when data changes', () {
       var model = new NotifyModel();
       var binding = new PolymerExpressions()
-          .getBinding(model, 'x', null, null);
+          .prepareBinding('x', null, null)(model, null);
       expect(binding.value, isNull);
       model.x = "hi";
       performMicrotaskCheckpoint();
diff --git a/pkg/scheduled_test/lib/scheduled_test.dart b/pkg/scheduled_test/lib/scheduled_test.dart
index aab455e..1be401c 100644
--- a/pkg/scheduled_test/lib/scheduled_test.dart
+++ b/pkg/scheduled_test/lib/scheduled_test.dart
@@ -49,7 +49,7 @@
 ///       });
 ///     }
 ///
-/// ## Setting Up and Tearing Down
+/// ## Setting up and tearing down
 ///
 /// The `scheduled_test` package defines its own [setUp] method that works just
 /// like the one in `unittest`. Tasks can be scheduled in [setUp]; they'll be
@@ -77,7 +77,7 @@
 ///       // ...
 ///     }
 ///
-/// ## Passing Values Between Tasks
+/// ## Passing values between tasks
 ///
 /// It's often useful to use values computed in one task in other tasks that are
 /// scheduled afterwards. There are two ways to do this. The most
diff --git a/pkg/scheduled_test/test/descriptor/async_test.dart b/pkg/scheduled_test/test/descriptor/async_test.dart
index 48fa883..72e7ceb 100644
--- a/pkg/scheduled_test/test/descriptor/async_test.dart
+++ b/pkg/scheduled_test/test/descriptor/async_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import 'utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/descriptor/directory_test.dart b/pkg/scheduled_test/test/descriptor/directory_test.dart
index dfc1f3b..0c9cdea 100644
--- a/pkg/scheduled_test/test/descriptor/directory_test.dart
+++ b/pkg/scheduled_test/test/descriptor/directory_test.dart
@@ -12,8 +12,8 @@
 import '../metatest.dart';
 import 'utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/descriptor/file_test.dart b/pkg/scheduled_test/test/descriptor/file_test.dart
index bf62f62..f319819 100644
--- a/pkg/scheduled_test/test/descriptor/file_test.dart
+++ b/pkg/scheduled_test/test/descriptor/file_test.dart
@@ -11,8 +11,8 @@
 import '../metatest.dart';
 import 'utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/descriptor/nothing_test.dart b/pkg/scheduled_test/test/descriptor/nothing_test.dart
index 8afe303..34d02e9 100644
--- a/pkg/scheduled_test/test/descriptor/nothing_test.dart
+++ b/pkg/scheduled_test/test/descriptor/nothing_test.dart
@@ -11,8 +11,8 @@
 import '../metatest.dart';
 import 'utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/descriptor/pattern_test.dart b/pkg/scheduled_test/test/descriptor/pattern_test.dart
index 826343d..9b92ad2 100644
--- a/pkg/scheduled_test/test/descriptor/pattern_test.dart
+++ b/pkg/scheduled_test/test/descriptor/pattern_test.dart
@@ -10,8 +10,8 @@
 
 String sandbox;
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/metatest.dart b/pkg/scheduled_test/test/metatest.dart
index e846773..0c7725d 100644
--- a/pkg/scheduled_test/test/metatest.dart
+++ b/pkg/scheduled_test/test/metatest.dart
@@ -9,8 +9,8 @@
 /// isolate, then reporting the results back to the parent isolate.
 library metatest;
 
-import 'dart:io';
 import 'dart:async';
+import 'dart:io';
 import 'dart:isolate';
 
 import 'package:path/path.dart' as path;
@@ -19,11 +19,6 @@
 
 import 'utils.dart';
 
-// TODO(nweiz): get rid of this once issue 8863 is fixed.
-/// The path to the Dart executable. This is only set in a child isolate.
-String get dartExecutable => _executable;
-String _executable;
-
 /// Declares a test with the given [description] and [body]. [body] corresponds
 /// to the `main` method of a test file, and will be run in an isolate. By
 /// default, this expects that all tests defined in [body] pass, but if
@@ -75,77 +70,62 @@
 /// Runs [setUpFn] before every metatest. Note that [setUpFn] will be
 /// overwritten if the test itself calls [setUp].
 void metaSetUp(void setUpFn()) {
-  _inChildIsolate.then((inIsolate) {
-    if (inIsolate) scheduled_test.setUp(setUpFn);
-  });
+  if (_inChildIsolate) scheduled_test.setUp(setUpFn);
 }
 
 /// Sets up a test with the given [description] and [body]. After the test runs,
 /// calls [validate] with the result map.
 void _setUpTest(String description, void body(), void validate(Map)) {
-  _inChildIsolate.then((inIsolate) {
-    if (inIsolate) {
-      _ensureInitialized();
-      if (_testToRun == description) body();
-    } else {
-      test(description, () {
-        expect(_runInIsolate(description).then(validate), completes);
-      });
-    }
-  });
+  if (_inChildIsolate) {
+    _ensureInitialized();
+    if (_testToRun == description) body();
+  } else {
+    test(description, () {
+      expect(_runInIsolate(description).then(validate), completes);
+    });
+  }
 }
 
-/// The description of the test to run in the child isolate. `null` in the
-/// parent isolate. Not set until [_inChildIsolate] completes.
+/// The description of the test to run in the child isolate.
+///
+/// `null` in the parent isolate.
 String _testToRun;
 
 /// The port with which the child isolate should communicate with the parent
-/// isolate. `null` in the parent isolate. Not set until [_inChildIsolate]
-/// completes.
+/// isolate.
+///
+/// `null` in the parent isolate.
 SendPort _replyTo;
 
-/// The cached [Future] for [_inChildIsolate].
-Future<bool> _inChildIsolateFuture;
+/// Whether or not we're running in a child isolate that's supposed to run a
+/// test.
+bool _inChildIsolate;
 
-/// The initial message received by the isolate.
-var _initialMessage;
-
-void metaTestInit(message) {
-  _initialMessage = message;
-}
-
-/// Returns whether or not we're running in a child isolate that's supposed to
-/// run a test.
-Future<bool> get _inChildIsolate {
-  if (_inChildIsolateFuture != null) return _inChildIsolateFuture;
-
-  if (_initialMessage == null) {
-    _inChildIsolateFuture = new Future.value(false);
+/// Initialize metatest.
+///
+/// [message] should be the second argument to [main]. It's used to determine
+/// whether this test is in the parent isolate or a child isolate.
+void initMetatest(message) {
+  if (message == null) {
+    _inChildIsolate = false;
   } else {
-    _testToRun = _initialMessage['testToRun'];
-    _executable = _initialMessage['executable'];
-    _replyTo = _initialMessage['replyTo'];
-    _inChildIsolateFuture = new Future.value(true);
+    _testToRun = message['testToRun'];
+    _replyTo = message['replyTo'];
+    _inChildIsolate = true;
   }
-  return _inChildIsolateFuture;
 }
 
 /// Runs the test described by [description] in its own isolate. Returns a map
 /// describing the results of that test run.
 Future<Map> _runInIsolate(String description) {
   var replyPort = new ReceivePort();
-  // TODO(nweiz): Don't use path here once issue 8440 is fixed.
-  return Isolate.spawnUri(Uri.parse(path.join(path.current, Platform.script)),
-      [], {
+  return Isolate.spawnUri(Uri.parse(Platform.script), [], {
     'testToRun': description,
-    'executable': Platform.executable,
     'replyTo': replyPort.sendPort
   }).then((_) {
-    var future = replyPort.first;
-
     // TODO(nweiz): Remove this timeout once issue 8417 is fixed and we can
     // capture top-level exceptions.
-    return timeout(future, 30 * 1000, () {
+    return timeout(replyPort.first, 30 * 1000, () {
       throw 'Timed out waiting for test to complete.';
     });
   });
diff --git a/pkg/scheduled_test/test/scheduled_future_matchers_test.dart b/pkg/scheduled_test/test/scheduled_future_matchers_test.dart
index 10efdc1..1a0c77c 100644
--- a/pkg/scheduled_test/test/scheduled_future_matchers_test.dart
+++ b/pkg/scheduled_test/test/scheduled_future_matchers_test.dart
@@ -9,8 +9,8 @@
 import 'metatest.dart';
 import 'utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_process_test.dart b/pkg/scheduled_test/test/scheduled_process_test.dart
index 2f9387f..e09c536 100644
--- a/pkg/scheduled_test/test/scheduled_process_test.dart
+++ b/pkg/scheduled_test/test/scheduled_process_test.dart
@@ -15,8 +15,8 @@
 import 'metatest.dart';
 import 'utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
@@ -389,5 +389,6 @@
     });
   }, 'clean up temp dir');
 
-  return new ScheduledProcess.start(dartExecutable, ['--checked', dartPath]);
+  return new ScheduledProcess.start(Platform.executable,
+      ['--checked', dartPath]);
 }
diff --git a/pkg/scheduled_test/test/scheduled_server_test.dart b/pkg/scheduled_test/test/scheduled_server_test.dart
index 77dd13c..63edc69 100644
--- a/pkg/scheduled_test/test/scheduled_server_test.dart
+++ b/pkg/scheduled_test/test/scheduled_server_test.dart
@@ -15,8 +15,8 @@
 import 'metatest.dart';
 import 'utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/abort_test.dart b/pkg/scheduled_test/test/scheduled_test/abort_test.dart
index d41632f..fc4622c 100644
--- a/pkg/scheduled_test/test/scheduled_test/abort_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/abort_test.dart
@@ -9,8 +9,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart b/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart
index e2999d1..97f2d19 100644
--- a/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart
@@ -9,8 +9,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart b/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart
index 988ac79..a3648f1 100644
--- a/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart b/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart
index 1f84779..0c4f587 100644
--- a/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart
@@ -7,8 +7,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart b/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart
index 7ad9685..ecb88d0 100644
--- a/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart b/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart
index dc1cdac..b603456 100644
--- a/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart
@@ -9,8 +9,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart b/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart
index b100c36..890b8fa 100644
--- a/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart
@@ -9,8 +9,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart b/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart
index 35d292d..dec4a7c 100644
--- a/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/set_up_test.dart b/pkg/scheduled_test/test/scheduled_test/set_up_test.dart
index fa3d47e..1fbf80f 100644
--- a/pkg/scheduled_test/test/scheduled_test/set_up_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/set_up_test.dart
@@ -7,8 +7,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart b/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart
index 5d67443..e9b6476 100644
--- a/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/simple_test.dart b/pkg/scheduled_test/test/scheduled_test/simple_test.dart
index 3c6a9dd..00ab216 100644
--- a/pkg/scheduled_test/test/scheduled_test/simple_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/simple_test.dart
@@ -9,8 +9,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart b/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart
index 2abf508..ae7ddb1 100644
--- a/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/timeout_test.dart b/pkg/scheduled_test/test/scheduled_test/timeout_test.dart
index 7151a48..0328d73 100644
--- a/pkg/scheduled_test/test/scheduled_test/timeout_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/timeout_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart b/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart
index d28e22c..6e89962 100644
--- a/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart b/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart
index 84cb29c..307cba5 100644
--- a/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart
@@ -10,8 +10,8 @@
 import '../metatest.dart';
 import '../utils.dart';
 
-void main(List<String> args, message) {
-  metaTestInit(message);
+void main(_, message) {
+  initMetatest(message);
 
   setUpTimeout();
 
diff --git a/pkg/shadow_dom/README.md b/pkg/shadow_dom/README.md
index 85f062a..9c2c1c2 100644
--- a/pkg/shadow_dom/README.md
+++ b/pkg/shadow_dom/README.md
@@ -25,7 +25,7 @@
 Because it does extensive DOM patching, it should be included **before** other
 script tags.
 
-## Useful Resources
+## Useful resources
 
 - [What the Heck is Shadow DOM?](http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/)
 - [Web Components Explained - Shadow DOM](https://dvcs.w3.org/hg/webcomponents/raw-file/57f8cfc4a7dc/explainer/index.html#shadow-dom-section)
diff --git a/pkg/shadow_dom/lib/shadow_dom.debug.js b/pkg/shadow_dom/lib/shadow_dom.debug.js
index 158c3d1..c8a4d5b 100644
--- a/pkg/shadow_dom/lib/shadow_dom.debug.js
+++ b/pkg/shadow_dom/lib/shadow_dom.debug.js
@@ -750,6 +750,7 @@
     },
 
     start: function() {
+      this.started = true;
       this.connect();
       this.sync(true);
     },
@@ -1511,20 +1512,24 @@
     return /^on[a-z]+$/.test(name);
   }
 
+  function isIdentifierName(name) {
+    return /^\w[a-zA-Z_0-9]*$/.test(name);
+  }
+
   function getGetter(name) {
-    return hasEval ?
+    return hasEval && isIdentifierName(name) ?
         new Function('return this.impl.' + name) :
         function() { return this.impl[name]; };
   }
 
   function getSetter(name) {
-    return hasEval ?
+    return hasEval && isIdentifierName(name) ?
         new Function('v', 'this.impl.' + name + ' = v') :
         function(v) { this.impl[name] = v; };
   }
 
   function getMethod(name) {
-    return hasEval ?
+    return hasEval && isIdentifierName(name) ?
         new Function('return this.impl.' + name +
                      '.apply(this.impl, arguments)') :
         function() { return this.impl[name].apply(this.impl, arguments); };
@@ -3592,7 +3597,8 @@
     }
   });
 
-  registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement);
+  registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement,
+                  document.createElement('canvas'));
 
   scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;
 })(this.ShadowDOMPolyfill);
@@ -3646,6 +3652,49 @@
   'use strict';
 
   var HTMLElement = scope.wrappers.HTMLElement;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var rewrap = scope.rewrap;
+
+  var OriginalHTMLImageElement = window.HTMLImageElement;
+
+  function HTMLImageElement(node) {
+    HTMLElement.call(this, node);
+  }
+  HTMLImageElement.prototype = Object.create(HTMLElement.prototype);
+
+  registerWrapper(OriginalHTMLImageElement, HTMLImageElement,
+                  document.createElement('img'));
+
+  function Image(width, height) {
+    if (!(this instanceof Image)) {
+      throw new TypeError(
+          'DOM object constructor cannot be called as a function.');
+    }
+
+    var node = unwrap(document.createElement('img'));
+    if (width !== undefined)
+      node.width = width;
+    if (height !== undefined)
+      node.height = height;
+    HTMLElement.call(this, node);
+    rewrap(node, this);
+  }
+
+  Image.prototype = HTMLImageElement.prototype;
+
+  scope.wrappers.HTMLImageElement = HTMLImageElement;
+  scope.wrappers.Image = Image;
+})(this.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
   var mixin = scope.mixin;
   var registerWrapper = scope.registerWrapper;
 
@@ -3790,6 +3839,7 @@
   var mixin = scope.mixin;
   var registerWrapper = scope.registerWrapper;
   var unwrap = scope.unwrap;
+  var unwrapIfNeeded = scope.unwrapIfNeeded;
   var wrap = scope.wrap;
 
   var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;
@@ -3804,7 +3854,7 @@
     },
 
     drawImage: function() {
-      arguments[0] = unwrap(arguments[0]);
+      arguments[0] = unwrapIfNeeded(arguments[0]);
       this.impl.drawImage.apply(this.impl, arguments);
     },
 
@@ -3828,7 +3878,7 @@
 
   var mixin = scope.mixin;
   var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
+  var unwrapIfNeeded = scope.unwrapIfNeeded;
   var wrap = scope.wrap;
 
   var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
@@ -3847,12 +3897,12 @@
     },
 
     texImage2D: function() {
-      arguments[5] = unwrap(arguments[5]);
+      arguments[5] = unwrapIfNeeded(arguments[5]);
       this.impl.texImage2D.apply(this.impl, arguments);
     },
 
     texSubImage2D: function() {
-      arguments[6] = unwrap(arguments[6]);
+      arguments[6] = unwrapIfNeeded(arguments[6]);
       this.impl.texSubImage2D.apply(this.impl, arguments);
     }
   });
@@ -5205,10 +5255,10 @@
     'base': 'HTMLBaseElement',
     'body': 'HTMLBodyElement',
     'button': 'HTMLButtonElement',
-    'canvas': 'HTMLCanvasElement',
     // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.
     'dl': 'HTMLDListElement',
     'datalist': 'HTMLDataListElement',
+    'data': 'HTMLDataElement',
     'dir': 'HTMLDirectoryElement',
     'div': 'HTMLDivElement',
     'embed': 'HTMLEmbedElement',
@@ -5222,17 +5272,13 @@
     'h1': 'HTMLHeadingElement',
     'html': 'HTMLHtmlElement',
     'iframe': 'HTMLIFrameElement',
-
-    // Uses HTMLSpanElement in Firefox.
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=843881
-    // 'image',
-
     'input': 'HTMLInputElement',
     'li': 'HTMLLIElement',
     'label': 'HTMLLabelElement',
     'legend': 'HTMLLegendElement',
     'link': 'HTMLLinkElement',
     'map': 'HTMLMapElement',
+    'marquee': 'HTMLMarqueeElement',
     // 'media', Covered by audio and video
     'menu': 'HTMLMenuElement',
     'menuitem': 'HTMLMenuItemElement',
@@ -5254,6 +5300,7 @@
     'source': 'HTMLSourceElement',
     'span': 'HTMLSpanElement',
     'style': 'HTMLStyleElement',
+    'time': 'HTMLTimeElement',
     'caption': 'HTMLTableCaptionElement',
     // WebKit and Moz are wrong:
     // https://bugs.webkit.org/show_bug.cgi?id=111469
@@ -5265,6 +5312,7 @@
     'thead': 'HTMLTableSectionElement',
     'tbody': 'HTMLTableSectionElement',
     'textarea': 'HTMLTextAreaElement',
+    'track': 'HTMLTrackElement',
     'title': 'HTMLTitleElement',
     'ul': 'HTMLUListElement',
     'video': 'HTMLVideoElement',
diff --git a/pkg/shadow_dom/lib/shadow_dom.min.js b/pkg/shadow_dom/lib/shadow_dom.min.js
index 9108bae..2017c03 100644
--- a/pkg/shadow_dom/lib/shadow_dom.min.js
+++ b/pkg/shadow_dom/lib/shadow_dom.min.js
@@ -1,3 +1,3 @@
-if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:H(a)&&H(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:P.test(a))}function i(a,b){if(b!==Q)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),G&&!F&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=R[a];if(b)return b;if(!h(a))return S;var b=new i(a,Q);return R[a]=b,b}function k(b){for(var c=0;T>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,F){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){V&&(U.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];$[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return db.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case"splice":C(c,g.index,g.removed.slice(),g.addedCount);break;case"new":case"updated":case"deleted":if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F=b(),G=c(),H=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},I="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},J="[$_a-zA-Z]",K="[$_a-zA-Z0-9]",L=J+"+"+K+"*",M="(?:[0-9]|[1-9]+[0-9]+)",N="(?:"+L+"|"+M+")",O="(?:"+N+")(?:\\s*\\.\\s*"+N+")*",P=new RegExp("^"+O+"$"),Q={},R={};i.get=j,i.prototype=I({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++)this[e],c+=a[e],b+=" &&\n     "+c+" != null";return b+=")\n",c+=a[e],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var S=new i("",Q);S.valid=!1,S.getValueFrom=S.setValueFrom=function(){};var T=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(F?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(F&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var U,V=!F||a.forceCollectObservers;p._allObserversCount=0,V&&(U=[]);var W=!1,X="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!W){if(X)return Object.deliverAllChangeRecords(),void 0;if(V){W=!0;var b=0,c={};do{b++;var d=U;U=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(F?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),U.push(f))}}while(T>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=U.length,W=!1}}},V&&(a.Platform.clearObservers=function(){U=[]}),r.prototype=I({__proto__:p.prototype,connect:function(){F&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=o(this.object))},check:function(a){var b,c;if(F){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){F?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=I({__proto__:r.prototype,connect:function(){F&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=this.object.slice())},check:function(a){var b;if(F){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var Y=Object.getPrototypeOf({}),Z=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==Y&&a!==Z){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=I({__proto__:p.prototype,connect:function(){F&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=I({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var $={"new":!0,updated:!0,deleted:!0};u.defineProperty=function(a,b,c){var d=c.object,e=j(c.path),f=w(a,b),g=new u(d,c.path,function(a,b){f&&f("updated",b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var _=0,ab=1,bb=2,cb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(_):(e.push(ab),d=g),b--,c--):f==h?(e.push(cb),b--,d=h):(e.push(bb),c--,d=i)}else e.push(cb),b--;else e.push(bb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,0==c-b&&0==f-e)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case _:j&&(l.push(j),j=void 0),m++,n++;break;case ab:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case bb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case cb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var db=new z;a.Observer=p,a.Observer.hasObjectObserve=F,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return db.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i}("undefined"!=typeof global&&global?global:this),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}();var ShadowDOMPolyfill={};!function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function d(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=C.get(b);if(c)return c;var d=f(b),e=r(d);return o(b,e,a),e}function g(a,b){m(a,b,!0)}function h(a,b){m(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return F?new Function("return this.impl."+a):function(){return this.impl[a]}}function k(a){return F?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function l(a){return F?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function m(b,c,d){Object.getOwnPropertyNames(b).forEach(function(e){if(!(e in c)){I&&b.__lookupGetter__(e);var f;try{f=Object.getOwnPropertyDescriptor(b,e)}catch(g){f=J}var h,m;if(d&&"function"==typeof f.value)return c[e]=l(e),void 0;var n=i(e);h=n?a.getEventHandlerGetter(e):j(e),(f.writable||f.set)&&(m=n?a.getEventHandlerSetter(e):k(e)),Object.defineProperty(c,e,{get:h,set:m,configurable:f.configurable,enumerable:f.enumerable})}})}function n(a,b,c){var e=a.prototype;o(e,b,c),d(b,a)}function o(a,c,d){var e=c.prototype;b(void 0===C.get(a)),C.set(a,c),D.set(e,a),g(a,e),d&&h(e,d)}function p(a,b){return C.get(b.prototype)===a}function q(a){var b=Object.getPrototypeOf(a),c=f(b),d=r(c);return o(b,d,a),d}function r(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function s(a){return a instanceof E.EventTarget||a instanceof E.Event||a instanceof E.Range||a instanceof E.DOMImplementation||a instanceof E.CanvasRenderingContext2D||E.WebGLRenderingContext&&a instanceof E.WebGLRenderingContext}function t(a){return a instanceof M||a instanceof L||a instanceof N||a instanceof O||a instanceof K||a instanceof P||Q&&a instanceof Q}function u(a){return null===a?null:(b(t(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function v(a){return null===a?null:(b(s(a)),a.impl)}function w(a){return a&&s(a)?v(a):a}function x(a){return a&&!s(a)?u(a):a}function y(a,c){null!==c&&(b(t(a)),b(void 0===c||s(c)),a.polymerWrapper_=c)}function z(a,b,c){Object.defineProperty(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function A(a,b){z(a,b,function(){return u(this.impl[b])})}function B(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=x(this);return a[b].apply(a,arguments)}})})}var C=new WeakMap,D=new WeakMap,E=Object.create(null),F=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(F)try{var G=new Function("","return true;");F=G()}catch(H){}Object.getOwnPropertyNames(window);var I=/Firefox/.test(navigator.userAgent),J={get:function(){},set:function(){},configurable:!0,enumerable:!0},K=window.DOMImplementation,L=window.Event,M=window.Node,N=window.Window,O=window.Range,P=window.CanvasRenderingContext2D,Q=window.WebGLRenderingContext;a.assert=b,a.constructorTable=C,a.defineGetter=z,a.defineWrapGetter=A,a.forwardMethodsToWrapper=B,a.isWrapperFor=p,a.mixin=c,a.nativePrototypeTable=D,a.oneOf=e,a.registerObject=q,a.registerWrapper=n,a.rewrap=y,a.unwrap=v,a.unwrapIfNeeded=w,a.wrap=u,a.wrapIfNeeded=x,a.wrappers=E}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||a.getHostForShadowRoot(f);var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(d,e){for(var g=[];d;){for(var i=[],j=e,l=void 0;j;){var n=null;if(i.length){if(c(j)&&(n=h(i),k(l))){var o=i[i.length-1];i.push(o)}}else i.push(j);if(m(j,d))return i[i.length-1];b(j)&&i.pop(),l=j,j=f(j,n,g)}d=b(d)?a.getHostForShadowRoot(d):d.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(b,c){if(b===c)return!0;if(b instanceof O.ShadowRoot){var d=a.getHostForShadowRoot(b);return n(l(d),c)}return!1}function o(){Z++}function p(){Z--}function q(b){if(!Q.get(b)){if(Q.set(b,!0),b instanceof $){if(Z)return}else a.renderAllPending();var c=N(b.target),d=N(b);return r(d,c)}}function r(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),s(a,c)&&t(a,c)&&u(a,c),U.set(a,x.NONE),S.set(a,null),a.defaultPrevented}function s(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=x.CAPTURING_PHASE,!v(b[d],a,c)))return!1}return!0}function t(a,b){var c=x.AT_TARGET;return v(b[0],a,c)}function u(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=x.AT_TARGET;else{if(!d||W.get(a))continue;c=x.BUBBLING_PHASE}if(!v(b[e],a,c))return}}function v(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===x.CAPTURING_PHASE||n.capture&&c===x.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function w(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function x(a,b){return a instanceof _?(this.impl=a,void 0):N(B(_,"Event",a,b))}function y(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function z(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(B(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function A(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function B(a,b,c,d){if(jb)return new a(c,y(d));var e=M(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function C(a){return"function"==typeof a?!0:a&&a.handleEvent}function D(a){this.impl=a}function E(b){return b instanceof O.ShadowRoot&&(b=a.getHostForShadowRoot(b)),M(b)}function F(a){J(a,mb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(nb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers;new WeakMap;var P=new WeakMap,Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=0,$=window.MutationEvent;w.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var _=window.Event;x.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(_,x,document.createEvent("Event"));var ab=z("UIEvent",x),bb=z("CustomEvent",x),cb={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},db=K({initMouseEvent:A("initMouseEvent",14)},cb),eb=K({initFocusEvent:A("initFocusEvent",5)},cb),fb=z("MouseEvent",ab,db),gb=z("FocusEvent",ab,eb),hb=z("MutationEvent",x,{initMutationEvent:A("initMutationEvent",3),get relatedNode(){return N(this.impl.relatedNode)}}),ib=Object.create(null),jb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=K(K({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.EventTarget,mb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;mb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(C(b)){var d=new w(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,q,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,q,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},lb&&L(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.muteMutationEvents=o,a.unmuteMutationEvents=p,a.wrapEventTargetMethods=F,a.wrappers.CustomEvent=bb,a.wrappers.Event=x,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=gb,a.wrappers.MouseEvent=fb,a.wrappers.MutationEvent=hb,a.wrappers.UIEvent=ab}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){o(a instanceof k)}function c(a,b,c,d){if(!(a instanceof DocumentFragment))return a.parentNode&&a.parentNode.removeChild(a),a.parentNode_=b,a.previousSibling_=c,a.nextSibling_=d,c&&(c.nextSibling_=a),d&&(d.previousSibling_=a),[a];for(var e,f=[];e=a.firstChild;)a.removeChild(e),f.push(e),e.parentNode_=b;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||c,f[g].nextSibling_=f[g+1]||d;return c&&(c.nextSibling_=f[0]),d&&(d.previousSibling_=f[f.length-1]),f}function d(a){if(a instanceof DocumentFragment){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}return[a]}function e(a){for(var b=0;b<a.length;b++)a[b].nodeWasAdded_()}function f(a,b){var c=a.nodeType===k.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function g(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function h(a,b){g(a,b);var c=b.length;if(1===c)return r(b[0]);for(var d=r(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(r(b[e]));return d}function i(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){o(b.parentNode===a);var c=b.nextSibling,d=r(b),e=d.parentNode;e&&y.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=r(a),g=f.firstChild;g;)c=g.nextSibling,y.call(f,g),g=c}function j(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function k(a){o(a instanceof u),l.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var l=a.wrappers.EventTarget,m=a.wrappers.NodeList,n=a.defineWrapGetter,o=a.assert,p=a.mixin,q=a.registerWrapper,r=a.unwrap,s=a.wrap,t=a.wrapIfNeeded,u=window.Node,v=u.prototype.appendChild,w=u.prototype.insertBefore,x=u.prototype.replaceChild,y=u.prototype.removeChild,z=u.prototype.compareDocumentPosition;k.prototype=Object.create(l.prototype),p(k.prototype,{appendChild:function(a){b(a);var g;if(this.invalidateShadowRenderer()||j(a)){var i=this.lastChild,k=null;g=c(a,this,i,k),this.lastChild_=g[g.length-1],i||(this.firstChild_=g[0]),v.call(this.impl,h(this,g))}else g=d(a),f(this,a),v.call(this.impl,r(a));return e(g),a},insertBefore:function(a,i){if(!i)return this.appendChild(a);b(a),b(i),o(i.parentNode===this);var k;if(this.invalidateShadowRenderer()||j(a)){var l=i.previousSibling,m=i;k=c(a,this,l,m),this.firstChild===i&&(this.firstChild_=k[0]);var n=r(i),p=n.parentNode;p?w.call(p,h(this,k),n):g(this,k)}else k=d(a),f(this,a),w.call(this.impl,r(a),r(i));return e(k),a},removeChild:function(a){if(b(a),a.parentNode!==this)throw new Error("NotFoundError");var c=r(a);if(this.invalidateShadowRenderer()){var d=this.firstChild,e=this.lastChild,f=a.nextSibling,g=a.previousSibling,h=c.parentNode;h&&y.call(h,c),d===a&&(this.firstChild_=f),e===a&&(this.lastChild_=g),g&&(g.nextSibling_=f),f&&(f.previousSibling_=g),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else y.call(this.impl,c);return a},replaceChild:function(a,g){if(b(a),b(g),g.parentNode!==this)throw new Error("NotFoundError");var i,k=r(g);if(this.invalidateShadowRenderer()||j(a)){var l=g.previousSibling,m=g.nextSibling;m===a&&(m=a.nextSibling),i=c(a,this,l,m),this.firstChild===g&&(this.firstChild_=i[0]),this.lastChild===g&&(this.lastChild_=i[i.length-1]),g.previousSibling_=g.nextSibling_=g.parentNode_=void 0,k.parentNode&&x.call(k.parentNode,h(this,i),k)}else i=d(a),f(this,a),x.call(this.impl,r(a),k);return e(i),g},nodeWasAdded_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeWasAdded_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:s(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:s(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:s(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:s(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:s(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==k.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){if(this.invalidateShadowRenderer()){if(i(this),""!==a){var b=this.impl.ownerDocument.createTextNode(a);this.appendChild(b)}}else this.impl.textContent=a},get childNodes(){for(var a=new m,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){if(!this.invalidateShadowRenderer())return s(this.impl.cloneNode(a));var b=s(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=t(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return z.call(this.impl,r(a))}}),n(k,"ownerDocument"),q(u,k,document.createDocumentFragment()),delete k.prototype.querySelector,delete k.prototype.querySelectorAll,k.prototype=p(Object.create(l.prototype),k.prototype),a.wrappers.Node=k}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null
-}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.mixin,f=a.registerWrapper,g=window.CharacterData;b.prototype=Object.create(d.prototype),e(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a}}),e(b.prototype,c),f(g,b,document.createTextNode("")),a.wrappers.CharacterData=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a){g.call(this,a)}function d(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var e=a.ChildNodeInterface,f=a.GetElementsByInterface,g=a.wrappers.Node,h=a.ParentNodeInterface,i=a.SelectorsInterface;a.addWrapNodeListMethod;var j=a.mixin,k=a.oneOf,l=a.registerWrapper,m=a.wrappers,n=window.Element,o=k(n.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),p=n.prototype[o];c.prototype=Object.create(g.prototype),j(c.prototype,{createShadowRoot:function(){var b=new m.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,c){this.impl.setAttribute(a,c),b(this,a)},removeAttribute:function(a){this.impl.removeAttribute(a),b(this,a)},matches:function(a){return p.call(this.impl,a)}}),c.prototype[o]=function(a){return this.matches(a)},n.prototype.webkitCreateShadowRoot&&(c.prototype.webkitCreateShadowRoot=c.prototype.createShadowRoot),d(c.prototype,"id"),d(c.prototype,"className","class"),j(c.prototype,e),j(c.prototype,f),j(c.prototype,h),j(c.prototype,i),l(n,c),a.matchesName=o,a.wrappers.Element=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case'"':return"&quot;"}}function c(a){return a.replace(r,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",s[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=p(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(q(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.mixin,o=a.registerWrapper,p=a.unwrap,q=a.wrap,r=/&|<|"/g,s={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},t=window.HTMLElement;g.prototype=Object.create(l.prototype),n(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),o(t,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b),a.wrappers.HTMLCanvasElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=o.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);o.set(a,b)}return b}function c(a){var c,d=b(a.ownerDocument),e=l(d.createDocumentFragment());for(h();c=a.firstChild;)e.appendChild(c);return k(),e}function d(a){if(e.call(this,a),!p){var b=c(a);n.set(this,m(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.muteMutationEvents,i=a.registerWrapper,j=a.setInnerHTML,k=a.unmuteMutationEvents,l=a.unwrap,m=a.wrap,n=new WeakMap,o=new WeakMap,p=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return p?m(this.impl.content):n.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){j(this.content,a)}}),p&&i(p,d),a.wrappers.HTMLTemplateElement=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement;a.mixin;var g=a.registerWrapper,h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return f(this.impl.canvas)},drawImage:function(){arguments[0]=e(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(g,b),a.wrappers.CanvasRenderingContext2D=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.WebGLRenderingContext;g&&(c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}}),d(g,b),a.wrappers.WebGLRenderingContext=b)}(this.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b,a.getHostForShadowRoot=function(a){return j.get(a)}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){return I.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof y))return!1;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++)P[a].render();P=[]}function l(){F=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof C)return a;return null}function o(a){return m(D(a))}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof z}function s(a){return a instanceof z}function t(a){return a instanceof A}function u(a){return a instanceof A}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y=a.wrappers.Element,z=a.wrappers.HTMLContentElement,A=a.wrappers.HTMLShadowElement,B=a.wrappers.Node,C=a.wrappers.ShadowRoot;a.assert;var D=a.getHostForShadowRoot;a.mixin,a.muteMutationEvents;var E=a.oneOf;a.unmuteMutationEvents;var F,G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),F)return;F=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},B.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},z.prototype.getDistributedNodes=function(){return k(),g(this)},A.prototype.nodeWasAdded_=z.prototype.nodeWasAdded_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOptionElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods;a.wrapNodeList;var x=new WeakMap;b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)}}),document.register){var z=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);return["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})}),z.call(u(this),b,{prototype:i}),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}function c(a){return new b(a)}function d(a){return a.map(c)}function e(a){var b=this;this.impl=new k(function(c){a.call(b,d(c),b)})}var f=a.defineGetter,g=a.defineWrapGetter,h=a.registerWrapper,i=a.unwrapIfNeeded,j=a.wrapNodeList;a.wrappers;var k=window.MutationObserver||window.WebKitMutationObserver;if(k){var l=window.MutationRecord;b.prototype={get addedNodes(){return j(this.impl.addedNodes)},get removedNodes(){return j(this.impl.removedNodes)}},["target","previousSibling","nextSibling"].forEach(function(a){g(b,a)}),["type","attributeName","attributeNamespace","oldValue"].forEach(function(a){f(b,a,function(){return this.impl[a]})}),l&&h(l,b),window.Node,e.prototype={observe:function(a,b){this.impl.observe(i(a),b)},disconnect:function(){this.impl.disconnect()},takeRecords:function(){return d(this.impl.takeRecords())}},a.wrappers.MutationObserver=e,a.wrappers.MutationRecord=b}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b),a.wrappers.Range=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}a.isWrapperFor;var c={a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"};Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(this.ShadowDOMPolyfill),function(){var a=window.ShadowDOMPolyfill;a.wrap,Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim","")),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b),this.insertPolyfillDirectives(g.rootStyles),this.insertPolyfillRules(g.rootStyles);var h=this.stylesToShimmedCssText(g.scopeStyles,b,e);h+=this.extractPolyfillUnscopedRules(g.rootStyles),g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},stylesToShimmedCssText:function(a,b,c){return this.shimAtHost(a,b,c)+this.shimScoping(a,b,c)},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),new RegExp("^"+c+u,"m")))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n	"})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return f=this.scopeRules(g,c,e)},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(t,function(a,b,c,d){return c?y+c+d+", "+c+" "+b+d:b+d})},convertCombinators:function(a){return a.replace("^^"," ").replace("^"," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n	",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=c?b:"\\[is="+b+"\\]",e=new RegExp("^("+d+")"+u,"m");return!a.match(e)},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(v,x).replace(w,x)},propertiesFromRule:function(a){var b=a.style.cssText;return a.style.content&&!a.style.content.match(/['"]+/)&&(b="content: '"+a.style.content+"';\n"+a.style.cssText.replace(/content:[^;]*;/g,"")),b}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t=/(-host)(?:\(([^)]*)\))?([^,{]*)/gim,u="([>\\s~+[.,{:][\\s\\S]*)?$",v=/@host/gim,w=/\:host/gim,x="-host",y="-host-no-combinator",z=/-host/gim;
-if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=document.querySelector("head");A.insertBefore(g(),A.childNodes[0])}a.ShadowCSS=i}(window.Platform)}
\ No newline at end of file
+if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:H(a)&&H(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:P.test(a))}function i(a,b){if(b!==Q)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),G&&!F&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=R[a];if(b)return b;if(!h(a))return S;var b=new i(a,Q);return R[a]=b,b}function k(b){for(var c=0;T>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,F){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){V&&(U.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];$[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return db.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case"splice":C(c,g.index,g.removed.slice(),g.addedCount);break;case"new":case"updated":case"deleted":if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F=b(),G=c(),H=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},I="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},J="[$_a-zA-Z]",K="[$_a-zA-Z0-9]",L=J+"+"+K+"*",M="(?:[0-9]|[1-9]+[0-9]+)",N="(?:"+L+"|"+M+")",O="(?:"+N+")(?:\\s*\\.\\s*"+N+")*",P=new RegExp("^"+O+"$"),Q={},R={};i.get=j,i.prototype=I({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++)this[e],c+=a[e],b+=" &&\n     "+c+" != null";return b+=")\n",c+=a[e],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var S=new i("",Q);S.valid=!1,S.getValueFrom=S.setValueFrom=function(){};var T=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(F?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(F&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var U,V=!F||a.forceCollectObservers;p._allObserversCount=0,V&&(U=[]);var W=!1,X="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!W){if(X)return Object.deliverAllChangeRecords(),void 0;if(V){W=!0;var b=0,c={};do{b++;var d=U;U=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(F?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),U.push(f))}}while(T>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=U.length,W=!1}}},V&&(a.Platform.clearObservers=function(){U=[]}),r.prototype=I({__proto__:p.prototype,connect:function(){F&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=o(this.object))},check:function(a){var b,c;if(F){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){F?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=I({__proto__:r.prototype,connect:function(){F&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=this.object.slice())},check:function(a){var b;if(F){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var Y=Object.getPrototypeOf({}),Z=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==Y&&a!==Z){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=I({__proto__:p.prototype,connect:function(){F&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=I({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.started=!0,this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var $={"new":!0,updated:!0,deleted:!0};u.defineProperty=function(a,b,c){var d=c.object,e=j(c.path),f=w(a,b),g=new u(d,c.path,function(a,b){f&&f("updated",b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var _=0,ab=1,bb=2,cb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(_):(e.push(ab),d=g),b--,c--):f==h?(e.push(cb),b--,d=h):(e.push(bb),c--,d=i)}else e.push(cb),b--;else e.push(bb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,0==c-b&&0==f-e)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case _:j&&(l.push(j),j=void 0),m++,n++;break;case ab:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case bb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case cb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var db=new z;a.Observer=p,a.Observer.hasObjectObserve=F,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return db.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i}("undefined"!=typeof global&&global?global:this),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}();var ShadowDOMPolyfill={};!function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function d(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=D.get(b);if(c)return c;var d=f(b),e=s(d);return p(b,e,a),e}function g(a,b){n(a,b,!0)}function h(a,b){n(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return G&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return G&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return G&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(b,c,d){Object.getOwnPropertyNames(b).forEach(function(e){if(!(e in c)){J&&b.__lookupGetter__(e);var f;try{f=Object.getOwnPropertyDescriptor(b,e)}catch(g){f=K}var h,j;if(d&&"function"==typeof f.value)return c[e]=m(e),void 0;var n=i(e);h=n?a.getEventHandlerGetter(e):k(e),(f.writable||f.set)&&(j=n?a.getEventHandlerSetter(e):l(e)),Object.defineProperty(c,e,{get:h,set:j,configurable:f.configurable,enumerable:f.enumerable})}})}function o(a,b,c){var e=a.prototype;p(e,b,c),d(b,a)}function p(a,c,d){var e=c.prototype;b(void 0===D.get(a)),D.set(a,c),E.set(e,a),g(a,e),d&&h(e,d)}function q(a,b){return D.get(b.prototype)===a}function r(a){var b=Object.getPrototypeOf(a),c=f(b),d=s(c);return p(b,d,a),d}function s(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function t(a){return a instanceof F.EventTarget||a instanceof F.Event||a instanceof F.Range||a instanceof F.DOMImplementation||a instanceof F.CanvasRenderingContext2D||F.WebGLRenderingContext&&a instanceof F.WebGLRenderingContext}function u(a){return a instanceof N||a instanceof M||a instanceof O||a instanceof P||a instanceof L||a instanceof Q||R&&a instanceof R}function v(a){return null===a?null:(b(u(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function w(a){return null===a?null:(b(t(a)),a.impl)}function x(a){return a&&t(a)?w(a):a}function y(a){return a&&!t(a)?v(a):a}function z(a,c){null!==c&&(b(u(a)),b(void 0===c||t(c)),a.polymerWrapper_=c)}function A(a,b,c){Object.defineProperty(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function B(a,b){A(a,b,function(){return v(this.impl[b])})}function C(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=y(this);return a[b].apply(a,arguments)}})})}var D=new WeakMap,E=new WeakMap,F=Object.create(null),G=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(G)try{var H=new Function("","return true;");G=H()}catch(I){}Object.getOwnPropertyNames(window);var J=/Firefox/.test(navigator.userAgent),K={get:function(){},set:function(){},configurable:!0,enumerable:!0},L=window.DOMImplementation,M=window.Event,N=window.Node,O=window.Window,P=window.Range,Q=window.CanvasRenderingContext2D,R=window.WebGLRenderingContext;a.assert=b,a.constructorTable=D,a.defineGetter=A,a.defineWrapGetter=B,a.forwardMethodsToWrapper=C,a.isWrapperFor=q,a.mixin=c,a.nativePrototypeTable=E,a.oneOf=e,a.registerObject=r,a.registerWrapper=o,a.rewrap=z,a.unwrap=w,a.unwrapIfNeeded=x,a.wrap=v,a.wrapIfNeeded=y,a.wrappers=F}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||a.getHostForShadowRoot(f);var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(d,e){for(var g=[];d;){for(var i=[],j=e,l=void 0;j;){var n=null;if(i.length){if(c(j)&&(n=h(i),k(l))){var o=i[i.length-1];i.push(o)}}else i.push(j);if(m(j,d))return i[i.length-1];b(j)&&i.pop(),l=j,j=f(j,n,g)}d=b(d)?a.getHostForShadowRoot(d):d.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(b,c){if(b===c)return!0;if(b instanceof O.ShadowRoot){var d=a.getHostForShadowRoot(b);return n(l(d),c)}return!1}function o(){Z++}function p(){Z--}function q(b){if(!Q.get(b)){if(Q.set(b,!0),b instanceof $){if(Z)return}else a.renderAllPending();var c=N(b.target),d=N(b);return r(d,c)}}function r(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),s(a,c)&&t(a,c)&&u(a,c),U.set(a,x.NONE),S.set(a,null),a.defaultPrevented}function s(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=x.CAPTURING_PHASE,!v(b[d],a,c)))return!1}return!0}function t(a,b){var c=x.AT_TARGET;return v(b[0],a,c)}function u(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=x.AT_TARGET;else{if(!d||W.get(a))continue;c=x.BUBBLING_PHASE}if(!v(b[e],a,c))return}}function v(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===x.CAPTURING_PHASE||n.capture&&c===x.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function w(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function x(a,b){return a instanceof _?(this.impl=a,void 0):N(B(_,"Event",a,b))}function y(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function z(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(B(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function A(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function B(a,b,c,d){if(jb)return new a(c,y(d));var e=M(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function C(a){return"function"==typeof a?!0:a&&a.handleEvent}function D(a){this.impl=a}function E(b){return b instanceof O.ShadowRoot&&(b=a.getHostForShadowRoot(b)),M(b)}function F(a){J(a,mb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(nb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers;new WeakMap;var P=new WeakMap,Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=0,$=window.MutationEvent;w.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var _=window.Event;x.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(_,x,document.createEvent("Event"));var ab=z("UIEvent",x),bb=z("CustomEvent",x),cb={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},db=K({initMouseEvent:A("initMouseEvent",14)},cb),eb=K({initFocusEvent:A("initFocusEvent",5)},cb),fb=z("MouseEvent",ab,db),gb=z("FocusEvent",ab,eb),hb=z("MutationEvent",x,{initMutationEvent:A("initMutationEvent",3),get relatedNode(){return N(this.impl.relatedNode)}}),ib=Object.create(null),jb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=K(K({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.EventTarget,mb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;mb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(C(b)){var d=new w(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,q,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,q,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},lb&&L(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.muteMutationEvents=o,a.unmuteMutationEvents=p,a.wrapEventTargetMethods=F,a.wrappers.CustomEvent=bb,a.wrappers.Event=x,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=gb,a.wrappers.MouseEvent=fb,a.wrappers.MutationEvent=hb,a.wrappers.UIEvent=ab}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){o(a instanceof k)}function c(a,b,c,d){if(!(a instanceof DocumentFragment))return a.parentNode&&a.parentNode.removeChild(a),a.parentNode_=b,a.previousSibling_=c,a.nextSibling_=d,c&&(c.nextSibling_=a),d&&(d.previousSibling_=a),[a];for(var e,f=[];e=a.firstChild;)a.removeChild(e),f.push(e),e.parentNode_=b;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||c,f[g].nextSibling_=f[g+1]||d;return c&&(c.nextSibling_=f[0]),d&&(d.previousSibling_=f[f.length-1]),f}function d(a){if(a instanceof DocumentFragment){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}return[a]}function e(a){for(var b=0;b<a.length;b++)a[b].nodeWasAdded_()}function f(a,b){var c=a.nodeType===k.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function g(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function h(a,b){g(a,b);var c=b.length;if(1===c)return r(b[0]);for(var d=r(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(r(b[e]));return d}function i(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){o(b.parentNode===a);var c=b.nextSibling,d=r(b),e=d.parentNode;e&&y.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=r(a),g=f.firstChild;g;)c=g.nextSibling,y.call(f,g),g=c}function j(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function k(a){o(a instanceof u),l.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var l=a.wrappers.EventTarget,m=a.wrappers.NodeList,n=a.defineWrapGetter,o=a.assert,p=a.mixin,q=a.registerWrapper,r=a.unwrap,s=a.wrap,t=a.wrapIfNeeded,u=window.Node,v=u.prototype.appendChild,w=u.prototype.insertBefore,x=u.prototype.replaceChild,y=u.prototype.removeChild,z=u.prototype.compareDocumentPosition;k.prototype=Object.create(l.prototype),p(k.prototype,{appendChild:function(a){b(a);var g;if(this.invalidateShadowRenderer()||j(a)){var i=this.lastChild,k=null;g=c(a,this,i,k),this.lastChild_=g[g.length-1],i||(this.firstChild_=g[0]),v.call(this.impl,h(this,g))}else g=d(a),f(this,a),v.call(this.impl,r(a));return e(g),a},insertBefore:function(a,i){if(!i)return this.appendChild(a);b(a),b(i),o(i.parentNode===this);var k;if(this.invalidateShadowRenderer()||j(a)){var l=i.previousSibling,m=i;k=c(a,this,l,m),this.firstChild===i&&(this.firstChild_=k[0]);var n=r(i),p=n.parentNode;p?w.call(p,h(this,k),n):g(this,k)}else k=d(a),f(this,a),w.call(this.impl,r(a),r(i));return e(k),a},removeChild:function(a){if(b(a),a.parentNode!==this)throw new Error("NotFoundError");var c=r(a);if(this.invalidateShadowRenderer()){var d=this.firstChild,e=this.lastChild,f=a.nextSibling,g=a.previousSibling,h=c.parentNode;h&&y.call(h,c),d===a&&(this.firstChild_=f),e===a&&(this.lastChild_=g),g&&(g.nextSibling_=f),f&&(f.previousSibling_=g),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else y.call(this.impl,c);return a},replaceChild:function(a,g){if(b(a),b(g),g.parentNode!==this)throw new Error("NotFoundError");var i,k=r(g);if(this.invalidateShadowRenderer()||j(a)){var l=g.previousSibling,m=g.nextSibling;m===a&&(m=a.nextSibling),i=c(a,this,l,m),this.firstChild===g&&(this.firstChild_=i[0]),this.lastChild===g&&(this.lastChild_=i[i.length-1]),g.previousSibling_=g.nextSibling_=g.parentNode_=void 0,k.parentNode&&x.call(k.parentNode,h(this,i),k)}else i=d(a),f(this,a),x.call(this.impl,r(a),k);return e(i),g},nodeWasAdded_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeWasAdded_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:s(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:s(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:s(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:s(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:s(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==k.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){if(this.invalidateShadowRenderer()){if(i(this),""!==a){var b=this.impl.ownerDocument.createTextNode(a);this.appendChild(b)}}else this.impl.textContent=a},get childNodes(){for(var a=new m,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){if(!this.invalidateShadowRenderer())return s(this.impl.cloneNode(a));var b=s(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=t(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return z.call(this.impl,r(a))}}),n(k,"ownerDocument"),q(u,k,document.createDocumentFragment()),delete k.prototype.querySelector,delete k.prototype.querySelectorAll,k.prototype=p(Object.create(l.prototype),k.prototype),a.wrappers.Node=k}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;
+if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.mixin,f=a.registerWrapper,g=window.CharacterData;b.prototype=Object.create(d.prototype),e(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a}}),e(b.prototype,c),f(g,b,document.createTextNode("")),a.wrappers.CharacterData=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a){g.call(this,a)}function d(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var e=a.ChildNodeInterface,f=a.GetElementsByInterface,g=a.wrappers.Node,h=a.ParentNodeInterface,i=a.SelectorsInterface;a.addWrapNodeListMethod;var j=a.mixin,k=a.oneOf,l=a.registerWrapper,m=a.wrappers,n=window.Element,o=k(n.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),p=n.prototype[o];c.prototype=Object.create(g.prototype),j(c.prototype,{createShadowRoot:function(){var b=new m.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,c){this.impl.setAttribute(a,c),b(this,a)},removeAttribute:function(a){this.impl.removeAttribute(a),b(this,a)},matches:function(a){return p.call(this.impl,a)}}),c.prototype[o]=function(a){return this.matches(a)},n.prototype.webkitCreateShadowRoot&&(c.prototype.webkitCreateShadowRoot=c.prototype.createShadowRoot),d(c.prototype,"id"),d(c.prototype,"className","class"),j(c.prototype,e),j(c.prototype,f),j(c.prototype,h),j(c.prototype,i),l(n,c),a.matchesName=o,a.wrappers.Element=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case'"':return"&quot;"}}function c(a){return a.replace(r,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",s[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=p(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(q(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.mixin,o=a.registerWrapper,p=a.unwrap,q=a.wrap,r=/&|<|"/g,s={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},t=window.HTMLElement;g.prototype=Object.create(l.prototype),n(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),o(t,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));void 0!==a&&(e.width=a),void 0!==b&&(e.height=b),d.call(this,e),g(e,this)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=o.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);o.set(a,b)}return b}function c(a){var c,d=b(a.ownerDocument),e=l(d.createDocumentFragment());for(h();c=a.firstChild;)e.appendChild(c);return k(),e}function d(a){if(e.call(this,a),!p){var b=c(a);n.set(this,m(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.muteMutationEvents,i=a.registerWrapper,j=a.setInnerHTML,k=a.unmuteMutationEvents,l=a.unwrap,m=a.wrap,n=new WeakMap,o=new WeakMap,p=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return p?m(this.impl.content):n.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){j(this.content,a)}}),p&&i(p,d),a.wrappers.HTMLTemplateElement=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement;a.mixin;var g=a.registerWrapper,h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b),a.wrappers.CanvasRenderingContext2D=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;g&&(c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}}),d(g,b),a.wrappers.WebGLRenderingContext=b)}(this.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b,a.getHostForShadowRoot=function(a){return j.get(a)}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){return I.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof y))return!1;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++)P[a].render();P=[]}function l(){F=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof C)return a;return null}function o(a){return m(D(a))}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof z}function s(a){return a instanceof z}function t(a){return a instanceof A}function u(a){return a instanceof A}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y=a.wrappers.Element,z=a.wrappers.HTMLContentElement,A=a.wrappers.HTMLShadowElement,B=a.wrappers.Node,C=a.wrappers.ShadowRoot;a.assert;var D=a.getHostForShadowRoot;a.mixin,a.muteMutationEvents;var E=a.oneOf;a.unmuteMutationEvents;var F,G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),F)return;F=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},B.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},z.prototype.getDistributedNodes=function(){return k(),g(this)},A.prototype.nodeWasAdded_=z.prototype.nodeWasAdded_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOptionElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods;a.wrapNodeList;var x=new WeakMap;b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)}}),document.register){var z=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);return["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})}),z.call(u(this),b,{prototype:i}),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}function c(a){return new b(a)}function d(a){return a.map(c)}function e(a){var b=this;this.impl=new k(function(c){a.call(b,d(c),b)})}var f=a.defineGetter,g=a.defineWrapGetter,h=a.registerWrapper,i=a.unwrapIfNeeded,j=a.wrapNodeList;a.wrappers;var k=window.MutationObserver||window.WebKitMutationObserver;if(k){var l=window.MutationRecord;b.prototype={get addedNodes(){return j(this.impl.addedNodes)},get removedNodes(){return j(this.impl.removedNodes)}},["target","previousSibling","nextSibling"].forEach(function(a){g(b,a)}),["type","attributeName","attributeNamespace","oldValue"].forEach(function(a){f(b,a,function(){return this.impl[a]})}),l&&h(l,b),window.Node,e.prototype={observe:function(a,b){this.impl.observe(i(a),b)},disconnect:function(){this.impl.disconnect()},takeRecords:function(){return d(this.impl.takeRecords())}},a.wrappers.MutationObserver=e,a.wrappers.MutationRecord=b}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b),a.wrappers.Range=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}a.isWrapperFor;var c={a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"};Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(this.ShadowDOMPolyfill),function(){var a=window.ShadowDOMPolyfill;a.wrap,Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim","")),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b),this.insertPolyfillDirectives(g.rootStyles),this.insertPolyfillRules(g.rootStyles);var h=this.stylesToShimmedCssText(g.scopeStyles,b,e);h+=this.extractPolyfillUnscopedRules(g.rootStyles),g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},stylesToShimmedCssText:function(a,b,c){return this.shimAtHost(a,b,c)+this.shimScoping(a,b,c)},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),new RegExp("^"+c+u,"m")))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n	"})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return f=this.scopeRules(g,c,e)},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(t,function(a,b,c,d){return c?y+c+d+", "+c+" "+b+d:b+d})},convertCombinators:function(a){return a.replace("^^"," ").replace("^"," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n	",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=c?b:"\\[is="+b+"\\]",e=new RegExp("^("+d+")"+u,"m");return!a.match(e)},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(v,x).replace(w,x)
+},propertiesFromRule:function(a){var b=a.style.cssText;return a.style.content&&!a.style.content.match(/['"]+/)&&(b="content: '"+a.style.content+"';\n"+a.style.cssText.replace(/content:[^;]*;/g,"")),b}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t=/(-host)(?:\(([^)]*)\))?([^,{]*)/gim,u="([>\\s~+[.,{:][\\s\\S]*)?$",v=/@host/gim,w=/\:host/gim,x="-host",y="-host-no-combinator",z=/-host/gim;if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=document.querySelector("head");A.insertBefore(g(),A.childNodes[0])}a.ShadowCSS=i}(window.Platform)}
\ No newline at end of file
diff --git a/pkg/stack_trace/lib/src/frame.dart b/pkg/stack_trace/lib/src/frame.dart
index 0b4f577..b15f651 100644
--- a/pkg/stack_trace/lib/src/frame.dart
+++ b/pkg/stack_trace/lib/src/frame.dart
@@ -19,6 +19,10 @@
     r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? '
     r'\((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$');
 
+/// foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28
+/// http://pub.dartlang.org/stuff.dart.js:560:28
+final _safariFrame = new RegExp(r"^(?:([0-9A-Za-z_$]*)@)?(.*):(\d*):(\d*)$");
+
 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560
 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560
 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560
@@ -169,11 +173,27 @@
     return new Frame(uri, int.parse(match[4]), null, member);
   }
 
-  /// Parses a string representation of a Safari stack frame.
+  /// Parses a string representation of a Safari 6.0 stack frame.
   ///
-  /// Safari 6+ frames look just like Firefox frames. Prior to Safari 6, stack
-  /// traces can't be retrieved.
-  factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame);
+  /// Safari 6.0 frames look just like Firefox frames. Prior to Safari 6.0,
+  /// stack traces can't be retrieved.
+  factory Frame.parseSafari6_0(String frame) => new Frame.parseFirefox(frame);
+
+  /// Parses a string representation of a Safari 6.1+ stack frame.
+  factory Frame.parseSafari6_1(String frame) {
+    var match = _safariFrame.firstMatch(frame);
+    if (match == null) {
+      throw new FormatException(
+          "Couldn't parse Safari stack trace line '$frame'.");
+    }
+
+    var uri = Uri.parse(match[2]);
+    var member = match[1];
+    if (member == null) member = '<fn>';
+    var line = match[3] == '' ? null : int.parse(match[3]);
+    var column = match[4] == '' ? null : int.parse(match[4]);
+    return new Frame(uri, line, column, member);
+  }
 
   /// Parses this package's string representation of a stack frame.
   factory Frame.parseFriendly(String frame) {
diff --git a/pkg/stack_trace/lib/src/trace.dart b/pkg/stack_trace/lib/src/trace.dart
index 95d41ad..c3db43e 100644
--- a/pkg/stack_trace/lib/src/trace.dart
+++ b/pkg/stack_trace/lib/src/trace.dart
@@ -28,6 +28,19 @@
 /// though it is possible for the message to match this as well.
 final _v8TraceLine = new RegExp(r"    ?at ");
 
+/// A RegExp to match Safari's stack traces.
+///
+/// Prior to version 6, Safari's stack traces were uncapturable. In v6 they were
+/// almost identical to Firefox traces, and so are handled by the Firefox code.
+/// In v6.1+, they have their own format that's similar to Firefox but distinct
+/// enough to warrant handling separately.
+///
+/// Most notably, Safari traces occasionally don't include the initial method
+/// name followed by "@", and they always have both the line and column number
+/// (or just a trailing colon if no column number is available).
+final _safariTrace = new RegExp(r"^([0-9A-Za-z_$]*@)?.*:\d*:\d*$",
+    multiLine: true);
+
 /// A RegExp to match Firefox's stack traces.
 ///
 /// Firefox's trace frames start with the name of the function in which the
@@ -36,7 +49,8 @@
 final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]|\(.*\))*@");
 
 /// A RegExp to match this package's stack traces.
-final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?\s+[^\s]+($|\n)");
+final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?[ \t]+[^\s]+$",
+    multiLine: true);
 
 /// A stack trace, comprised of a list of stack frames.
 class Trace implements StackTrace {
@@ -89,9 +103,15 @@
     try {
       if (trace.isEmpty) return new Trace(<Frame>[]);
       if (trace.contains(_v8Trace)) return new Trace.parseV8(trace);
-      // Valid Safari traces are a superset of valid Firefox traces.
-      if (trace.contains(_firefoxTrace)) return new Trace.parseSafari(trace);
-      if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace);
+      // Safari 6.1+ traces could be misinterpreted as Firefox traces, so we
+      // check for them first.
+      if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace);
+      // Safari 6.0 traces are a superset of Firefox traces, so we parse those
+      // two together.
+      if (trace.contains(_firefoxTrace)) return new Trace.parseSafari6_0(trace);
+      if (trace.contains(_friendlyTrace)) {
+        return new Trace.parseFriendly(trace);
+      }
 
       // Default to parsing the stack trace as a VM trace. This is also hit on
       // IE and Safari, where the stack trace is just an empty string (issue
@@ -129,11 +149,25 @@
 
   /// Parses a string representation of a Safari stack trace.
   ///
-  /// Safari 6+ stack traces look just like Firefox traces, except that they
+  /// This will automatically decide between [parseSafari6_0] and
+  /// [parseSafari6_1] based on the contents of [trace].
+  factory Trace.parseSafari(String trace) {
+    if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace);
+    return new Trace.parseSafari6_0(trace);
+  }
+
+  /// Parses a string representation of a Safari 6.1+ stack trace.
+  Trace.parseSafari6_1(String trace)
+      : this(trace.trim().split("\n")
+          .map((line) => new Frame.parseSafari6_1(line)));
+
+  /// Parses a string representation of a Safari 6.0 stack trace.
+  ///
+  /// Safari 6.0 stack traces look just like Firefox traces, except that they
   /// sometimes (e.g. in isolates) have a "[native code]" frame. We just ignore
   /// this frame to make the stack format more consistent between browsers.
-  /// Prior to Safari 6, stack traces can't be retrieved.
-  Trace.parseSafari(String trace)
+  /// Prior to Safari 6.0, stack traces can't be retrieved.
+  Trace.parseSafari6_0(String trace)
       : this(trace.trim().split("\n")
           .where((line) => line != '[native code]')
           .map((line) => new Frame.parseFirefox(line)));
diff --git a/pkg/stack_trace/test/frame_test.dart b/pkg/stack_trace/test/frame_test.dart
index ab7c401..97cf48a 100644
--- a/pkg/stack_trace/test/frame_test.dart
+++ b/pkg/stack_trace/test/frame_test.dart
@@ -226,6 +226,53 @@
     });
   });
 
+  group('.parseSafari6_1', () {
+    test('parses a simple stack frame correctly', () {
+      var frame = new Frame.parseSafari6_1(
+          "foo\$bar@http://dartlang.org/foo/bar.dart:10:11");
+      expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+      expect(frame.line, equals(10));
+      expect(frame.column, equals(11));
+      expect(frame.member, equals('foo\$bar'));
+    });
+
+    test('parses an anonymous stack frame correctly', () {
+      var frame = new Frame.parseSafari6_1(
+          "http://dartlang.org/foo/bar.dart:10:11");
+      expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+      expect(frame.line, equals(10));
+      expect(frame.column, equals(11));
+      expect(frame.member, equals('<fn>'));
+    });
+
+    test('parses a stack frame with no line correctly', () {
+      var frame = new Frame.parseSafari6_1(
+          "foo\$bar@http://dartlang.org/foo/bar.dart::11");
+      expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+      expect(frame.line, isNull);
+      expect(frame.column, equals(11));
+      expect(frame.member, equals('foo\$bar'));
+    });
+
+    test('parses a stack frame with no column correctly', () {
+      var frame = new Frame.parseSafari6_1(
+          "foo\$bar@http://dartlang.org/foo/bar.dart:10:");
+      expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+      expect(frame.line, equals(10));
+      expect(frame.column, isNull);
+      expect(frame.member, equals('foo\$bar'));
+    });
+
+    test('parses a stack frame with no line or column correctly', () {
+      var frame = new Frame.parseSafari6_1(
+          "foo\$bar@http://dartlang.org/foo/bar.dart:10:11");
+      expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+      expect(frame.line, equals(10));
+      expect(frame.column, equals(11));
+      expect(frame.member, equals('foo\$bar'));
+    });
+  });
+
   group('.parseFriendly', () {
     test('parses a simple stack frame correctly', () {
       var frame = new Frame.parseFriendly(
diff --git a/pkg/stack_trace/test/trace_test.dart b/pkg/stack_trace/test/trace_test.dart
index c3ce039..ad916f1 100644
--- a/pkg/stack_trace/test/trace_test.dart
+++ b/pkg/stack_trace/test/trace_test.dart
@@ -130,7 +130,7 @@
           equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
     });
 
-    test('.parseSafari', () {
+    test('parses a Safari 6.0 stack trace correctly', () {
       var trace = new Trace.parse(
           'Foo._bar@http://pub.dartlang.org/stuff.js:42\n'
           'zip/<@http://pub.dartlang.org/stuff.js:0\n'
@@ -146,6 +146,20 @@
       expect(trace.frames.length, equals(3));
     });
 
+    test('parses a Safari 6.1 stack trace correctly', () {
+      var trace = new Trace.parse(
+          'http://pub.dartlang.org/stuff.js:42:43\n'
+          'zip@http://pub.dartlang.org/stuff.js:0:1\n'
+          'zip\$zap@http://pub.dartlang.org/thing.js:1:2');
+
+      expect(trace.frames[0].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[1].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[2].uri,
+          equals(Uri.parse("http://pub.dartlang.org/thing.js")));
+    });
+
     test('parses a package:stack_trace stack trace correctly', () {
       var trace = new Trace.parse(
           'http://dartlang.org/foo/bar.dart 10:11  Foo.<fn>.bar\n'
diff --git a/pkg/template_binding/lib/src/binding_delegate.dart b/pkg/template_binding/lib/src/binding_delegate.dart
new file mode 100644
index 0000000..0a9cb51
--- /dev/null
+++ b/pkg/template_binding/lib/src/binding_delegate.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2013, 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.
+
+library template_binding.src.binding_delegate;
+
+import 'dart:html';
+import 'package:template_binding/template_binding.dart' show TemplateInstance;
+
+/**
+ * Template Bindings native features enables a wide-range of use cases,
+ * but (by design) don't attempt to implement a wide array of specialized
+ * behaviors.
+ *
+ * Enabling these features is a matter of implementing and registering a
+ * BindingDelegate. A binding delegate is an object which contains one or more
+ * delegation functions which implement specialized behavior. This object is
+ * registered via [TemplateBindExtension.bindingDelegate]:
+ *
+ * HTML:
+ *     <template bind>
+ *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
+ *     </template>
+ *
+ * Dart:
+ *     class MySyntax extends BindingDelegate {
+ *       prepareBinding(path, name, node) {
+ *         // The magic happens here!
+ *       }
+ *     }
+ *     ...
+ *     templateBind(query('template'))
+ *         ..bindingDelegate = new MySyntax()
+ *         ..model = new MyModel();
+ *
+ *
+ * See
+ * <http://www.polymer-project.org/platform/template.html#binding-delegate-api>
+ * for more information about the binding delegate.
+ */
+// TODO(jmesserly): need better api docs here. The link above seems out of date.
+abstract class BindingDelegate {
+  /**
+   * Prepares a binding. This is called immediately after parsing a mustache
+   * token with `{{ path }}` in the context of the [node] and the property named
+   * [name]. This should return a function that will be passed the actual
+   * node and model, and either returns null or an object with a `value`
+   * property. This allows the syntax to reinterpret the model for each binding.
+   */
+  PrepareBindingFunction prepareBinding(String path, String name, Node node)
+      => null;
+
+  /**
+   * Returns a function that can optionally replace the model that will be
+   * passed to [TemplateBindExtension.createInstance]. This can be used to
+   * implement syntax such as `<template repeat="{{ item in items }}">` by
+   * ensuring that the returned model has the "item" name available.
+   */
+  PrepareInstanceModelFunction prepareInstanceModel(Element template) => null;
+
+  /**
+   * Returns a function that will be called whenever the position of an item
+   * inside this template changes.
+   */
+  PrepareInstancePositionChangedFunction prepareInstancePositionChanged(
+      Element template) => null;
+}
+
+typedef PrepareBindingFunction(model, Node node);
+
+typedef PrepareInstanceModelFunction(model);
+
+typedef PrepareInstancePositionChangedFunction(TemplateInstance instance,
+    int index);
diff --git a/pkg/template_binding/lib/src/element.dart b/pkg/template_binding/lib/src/element.dart
index c3c4992..1ee43f9 100644
--- a/pkg/template_binding/lib/src/element.dart
+++ b/pkg/template_binding/lib/src/element.dart
@@ -15,7 +15,7 @@
     if (_node is OptionElement && name == 'value') {
       // Note: because <option> can be a semantic template, <option> will be
       // a TemplateBindExtension sometimes. So we need to handle it here.
-      _node.attributes.remove(name);
+      (_node as OptionElement).attributes.remove(name);
       binding = new _OptionValueBinding(_node, model, path);
     } else {
       binding = new _AttributeBinding(_node, name, model, path);
diff --git a/pkg/template_binding/lib/src/input_bindings.dart b/pkg/template_binding/lib/src/input_bindings.dart
index fc89dc5..8e5b3b0 100644
--- a/pkg/template_binding/lib/src/input_bindings.dart
+++ b/pkg/template_binding/lib/src/input_bindings.dart
@@ -148,11 +148,12 @@
     // Instead we use scheduleMicrotask. Each <template repeat> needs a delay of
     // 2:
     //   * once to happen after the child _TemplateIterator is created
-    //   * once to be after _TemplateIterator.inputs CompoundBinding resolve
+    //   * once to be after _TemplateIterator's CompoundPathObserver resolve
     // And then we need to do this delay sequence twice:
     //   * once for OPTGROUP
     //   * once for OPTION.
     // The resulting 2 * 2 is our maxRetries.
+    //
     // TODO(jmesserly): a much better approach would be to find the nested
     // <template> and wait on some future that completes when it has expanded.
     var maxRetries = 4;
diff --git a/pkg/template_binding/lib/src/instance_binding_map.dart b/pkg/template_binding/lib/src/instance_binding_map.dart
new file mode 100644
index 0000000..3868343
--- /dev/null
+++ b/pkg/template_binding/lib/src/instance_binding_map.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, 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.
+
+part of template_binding;
+
+class _InstanceBindingMap {
+  final List bindings;
+  final List<_InstanceBindingMap> children;
+  final Node templateRef;
+  final bool hasSubTemplate;
+
+  _InstanceBindingMap._(this.bindings, this.children, this.templateRef,
+      this.hasSubTemplate);
+
+  factory _InstanceBindingMap(Node node, BindingDelegate delegate) {
+    var bindings = _getBindings(node, delegate);
+
+    bool hasSubTemplate = false;
+    Node templateRef = null;
+
+    if (isSemanticTemplate(node)) {
+      templateRef = node;
+      hasSubTemplate = true;
+    }
+
+    List children = null;
+    for (var c = node.firstChild, i = 0; c != null; c = c.nextNode, i++) {
+      var childMap = new _InstanceBindingMap(c, delegate);
+      if (childMap == null) continue;
+
+      if (children == null) children = new List(node.nodes.length);
+      children[i] = childMap;
+      if (childMap.hasSubTemplate) {
+        hasSubTemplate = true;
+      }
+    }
+
+    return new _InstanceBindingMap._(bindings, children, templateRef,
+        hasSubTemplate);
+  }
+}
+
+
+void _addMapBindings(Node node, _InstanceBindingMap map, model,
+    BindingDelegate delegate, List bound) {
+  if (map == null) return;
+
+  if (map.templateRef != null) {
+    TemplateBindExtension.decorate(node, map.templateRef);
+    if (delegate != null) {
+      templateBindFallback(node)._bindingDelegate = delegate;
+    }
+  }
+
+  if (map.bindings != null) {
+    _processBindings(map.bindings, node, model, bound);
+  }
+
+  if (map.children == null) return;
+
+  int i = 0;
+  for (var c = node.firstChild; c != null; c = c.nextNode) {
+    _addMapBindings(c, map.children[i++], model, delegate, bound);
+  }
+}
diff --git a/pkg/template_binding/lib/src/list_diff.dart b/pkg/template_binding/lib/src/list_diff.dart
index ba96d15..fc7430d 100644
--- a/pkg/template_binding/lib/src/list_diff.dart
+++ b/pkg/template_binding/lib/src/list_diff.dart
@@ -39,7 +39,7 @@
   int get removedCount => _removed.length;
 
   /** Returns true if the provided index was changed by this operation. */
-  bool changes(key) {
+  bool indexChanged(key) {
     // If key isn't an int, or before the index, then it wasn't changed.
     if (key is! int || key < index) return false;
 
diff --git a/pkg/template_binding/lib/src/node.dart b/pkg/template_binding/lib/src/node.dart
index 791214b..a5fb835 100644
--- a/pkg/template_binding/lib/src/node.dart
+++ b/pkg/template_binding/lib/src/node.dart
@@ -31,7 +31,7 @@
   /** Unbinds all bound attributes. */
   void unbindAll() {
     if (_bindings == null) return;
-    for (var binding in bindings.values) {
+    for (var binding in bindings.values.toList()) {
       if (binding != null) binding.close();
     }
     _bindings = null;
@@ -56,7 +56,7 @@
   /** Gets the template instance that instantiated this node, if any. */
   TemplateInstance get templateInstance =>
       _templateInstance != null ? _templateInstance :
-      (_node.parent != null ? _node.parent.templateInstance : null);
+      (_node.parent != null ? nodeBind(_node.parent).templateInstance : null);
 }
 
 
@@ -80,160 +80,3 @@
 
   TemplateInstance(this.firstNode, this.lastNode, this.model);
 }
-
-
-/**
- * Template Bindings native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features is a matter of implementing and registering a
- * BindingDelegate. A binding delegate is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered via [TemplateBindExtension.bindingDelegate]:
- *
- * HTML:
- *     <template bind>
- *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- *     </template>
- *
- * Dart:
- *     class MySyntax extends BindingDelegate {
- *       getBinding(model, path, name, node) {
- *         // The magic happens here!
- *       }
- *     }
- *     ...
- *     templateBind(query('template'))
- *         ..bindingDelegate = new MySyntax()
- *         ..model = new MyModel();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
- * more information about Custom Syntax.
- */
-abstract class BindingDelegate {
-  /**
-   * This syntax method allows for a custom interpretation of the contents of
-   * mustaches (`{{` ... `}}`).
-   *
-   * When a template is inserting an instance, it will invoke this method for
-   * each mustache which is encountered. The function is invoked with four
-   * arguments:
-   *
-   * - [model]: The data context for which this instance is being created.
-   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
-   * - [name]: The context in which the mustache occurs. Within element
-   *   attributes, this will be the name of the attribute. Within text,
-   *   this will be 'text'.
-   * - [node]: A reference to the node to which this binding will be created.
-   *
-   * If the method wishes to handle binding, it is required to return an object
-   * which has at least a `value` property that can be observed. If it does,
-   * then MDV will call [NodeBindExtension.bind] on the node:
-   *
-   *     nodeBind(node).bind(name, retval, 'value');
-   *
-   * If the 'getBinding' does not wish to override the binding, it should return
-   * null.
-   */
-  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
-  // Normally they are String and Node respectively. But sometimes it will pass
-  // (int name, CompoundBinding node). That seems very confusing; we may want
-  // to change this API.
-  getBinding(model, String path, name, node) => null;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate model than the
-   * one the template would otherwise use when producing an instance.
-   *
-   * When a template is about to create an instance, it will invoke this method
-   * The function is invoked with two arguments:
-   *
-   * - [template]: The template element which is about to create and insert an
-   *   instance.
-   * - [model]: The data context for which this instance is being created.
-   *
-   * The template element will always use the return value of `getInstanceModel`
-   * as the model for the new instance. If the syntax does not wish to override
-   * the value, it should simply return the `model` value it was passed.
-   */
-  getInstanceModel(Element template, model) => model;
-}
-
-/**
- * A data binding on a [Node].
- * See [NodeBindExtension.bindings] and [NodeBindExtension.bind].
- */
-abstract class NodeBinding {
-  Node _node;
-  var _model;
-  PathObserver _observer;
-  StreamSubscription _pathSub;
-
-  /** The property of [node] which will be data bound. */
-  final String property;
-
-  /** The property of [node] which will be data bound. */
-  final String path;
-
-  /** The node that has [property] which will be data bound. */
-  Node get node => _node;
-
-  /**
-   * The bound data model.
-   */
-  get model => _model;
-
-  /** True if this binding has been [closed]. */
-  bool get closed => _node == null;
-
-  /** The value at the [path] on [model]. */
-  get value => _observer.value;
-
-  set value(newValue) {
-    _observer.value = newValue;
-  }
-
-  NodeBinding(this._node, this.property, this._model, [String path])
-      : path = path != null ? path : '' {
-    _observePath();
-  }
-
-  _observePath() {
-    // Fast path if we're observing PathObserver.value
-    if (model is PathObserver && path == 'value') {
-      _observer = model;
-    } else {
-      // Create the path observer
-      _observer = new PathObserver(model, path);
-    }
-    _pathSub = _observer.bindSync(valueChanged);
-  }
-
-  /** Called when [value] changes to update the [node]. */
-  // TODO(jmesserly): the impl in template_binding uses reflection to set the
-  // property, but that isn't used except for specific known fields like
-  // "textContent", so I'm overridding this in the subclasses instead.
-  void valueChanged(newValue);
-
-  /** Called to sanitize the value before it is assigned into the property. */
-  sanitizeBoundValue(value) => value == null ? '' : '$value';
-
-  /**
-   * Called by [NodeBindExtension.unbind] to close this binding and unobserve
-   * the [path].
-   *
-   * This can be overridden in subclasses, but they must call `super.close()`
-   * to free associated resources. They must also check [closed] and return
-   * immediately if already closed.
-   */
-  void close() {
-    if (closed) return;
-
-    if (_pathSub != null) _pathSub.cancel();
-    _pathSub = null;
-    _observer = null;
-    _node = null;
-    _model = null;
-  }
-}
diff --git a/pkg/template_binding/lib/src/node_binding.dart b/pkg/template_binding/lib/src/node_binding.dart
new file mode 100644
index 0000000..95c5e00
--- /dev/null
+++ b/pkg/template_binding/lib/src/node_binding.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2013, 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.
+
+library template_binding.src.node_binding;
+
+import 'dart:async' show StreamSubscription;
+import 'dart:html' show Node;
+import 'package:observe/observe.dart' show PathObserver, CompoundPathObserver;
+
+/** Test only method. Not re-exported. */
+getObserverForTest(NodeBinding binding) => binding._observer;
+
+/**
+ * A data binding on a [Node].
+ * See [NodeBindExtension.bindings] and [NodeBindExtension.bind].
+ */
+abstract class NodeBinding {
+  Node _node;
+  var _model;
+
+  // TODO(jmesserly): need common interface for PathObserver,
+  // CompoundPathObserver.
+  var _observer;
+  StreamSubscription _pathSub;
+
+  /** The property of [node] which will be data bound. */
+  final String property;
+
+  /** The property of [node] which will be data bound. */
+  final String path;
+
+  /** The node that has [property] which will be data bound. */
+  Node get node => _node;
+
+  /** The bound data model. */
+  get model => _model;
+
+  /** True if this binding has been [closed]. */
+  bool get closed => _node == null;
+
+  /** The value at the [path] on [model]. */
+  get value => _observer.value;
+
+  set value(newValue) {
+    _observer.value = newValue;
+  }
+
+  NodeBinding(this._node, this.property, this._model, [String path])
+      : path = path != null ? path : '' {
+
+    // Fast path if we're observing "value"
+    if ((model is PathObserver || model is CompoundPathObserver) &&
+        path == 'value') {
+
+      _observer = model;
+    } else {
+      // Create the path observer
+      _observer = new PathObserver(model, this.path);
+    }
+
+    _pathSub = _observer.changes.listen((r) => valueChanged(value));
+    valueChanged(value);
+  }
+
+  /** Called when [value] changes to update the [node]. */
+  // TODO(jmesserly): the impl in template_binding uses reflection to set the
+  // property, but that isn't used except for specific known fields like
+  // "textContent", so I'm overridding this in the subclasses instead.
+  void valueChanged(newValue);
+
+  /** Called to sanitize the value before it is assigned into the property. */
+  sanitizeBoundValue(value) => value == null ? '' : '$value';
+
+  /**
+   * Called by [NodeBindExtension.unbind] to close this binding and unobserve
+   * the [path].
+   *
+   * This can be overridden in subclasses, but they must call `super.close()`
+   * to free associated resources. They must also check [closed] and return
+   * immediately if already closed.
+   */
+  void close() {
+    if (closed) return;
+
+    if (_pathSub != null) _pathSub.cancel();
+    _pathSub = null;
+    _observer = null;
+    _node = null;
+    _model = null;
+  }
+}
diff --git a/pkg/template_binding/lib/src/template.dart b/pkg/template_binding/lib/src/template.dart
index be6a6fd..ad35eb8 100644
--- a/pkg/template_binding/lib/src/template.dart
+++ b/pkg/template_binding/lib/src/template.dart
@@ -8,7 +8,7 @@
 class TemplateBindExtension extends _ElementExtension {
   var _model;
   BindingDelegate _bindingDelegate;
-  _TemplateIterator _templateIterator;
+  _TemplateIterator _iterator;
   bool _scheduled = false;
 
   Element _templateInstanceRef;
@@ -17,34 +17,115 @@
   DocumentFragment _content;
   bool _templateIsDecorated;
 
+  var _bindingMap;
+
   TemplateBindExtension._(Element node) : super(node);
 
   Element get _node => super._node;
 
+  TemplateBindExtension get _self => super._node is TemplateBindExtension
+      ? _node : this;
+
   NodeBinding bind(String name, model, [String path]) {
+    path = path != null ? path : '';
+
+    if (_iterator == null) {
+      // TODO(jmesserly): since there's only one iterator, we could just
+      // inline it into this object.
+      _iterator = new _TemplateIterator(this);
+    }
+
+    // Dart note: we return _TemplateBinding instead of _iterator.
+    // See comment on _TemplateBinding class.
     switch (name) {
       case 'bind':
+        _iterator..hasBind = true
+            ..bindModel = model
+            ..bindPath = path;
+        _scheduleIterator();
+        return bindings[name] = new _TemplateBinding(this, name, model, path);
       case 'repeat':
+        _iterator..hasRepeat = true
+            ..repeatModel = model
+            ..repeatPath = path;
+        _scheduleIterator();
+        return bindings[name] = new _TemplateBinding(this, name, model, path);
       case 'if':
-        _self.unbind(name);
-        if (_templateIterator == null) {
-          _templateIterator = new _TemplateIterator(_node);
-        }
+        _iterator..hasIf = true
+            ..ifModel = model
+            ..ifPath = path;
+        _scheduleIterator();
         return bindings[name] = new _TemplateBinding(this, name, model, path);
       default:
         return super.bind(name, model, path);
     }
   }
 
+  void unbind(String name) {
+    switch (name) {
+      case 'bind':
+        if (_iterator == null) return;
+        _iterator..hasBind = false
+            ..bindModel = null
+            ..bindPath = null;
+        _scheduleIterator();
+        bindings.remove(name);
+        return;
+      case 'repeat':
+        if (_iterator == null) return;
+        _iterator..hasRepeat = false
+            ..repeatModel = null
+            ..repeatPath = null;
+        _scheduleIterator();
+        bindings.remove(name);
+        return;
+      case 'if':
+        if (_iterator == null) return;
+        _iterator..hasIf = false
+            ..ifModel = null
+            ..ifPath = null;
+        _scheduleIterator();
+        bindings.remove(name);
+        return;
+      default:
+        super.unbind(name);
+        return;
+    }
+  }
+
+  void _scheduleIterator() {
+    if (!_iterator.depsChanging) {
+      _iterator.depsChanging = true;
+      scheduleMicrotask(_iterator.resolve);
+    }
+  }
+
   /**
    * Creates an instance of the template, using the provided model and optional
    * binding delegate.
    */
-  DocumentFragment createInstance([model, BindingDelegate delegate]) {
-    var instance = _createDeepCloneAndDecorateTemplates(
-        templateBind(ref).content, delegate);
+  DocumentFragment createInstance([model, BindingDelegate delegate,
+      List<NodeBinding> bound]) {
+    var ref = templateBind(this.ref);
+    var content = ref.content;
+    // Dart note: we store _bindingMap on the TemplateBindExtension instead of
+    // the "content" because we already have an expando for it.
+    var map = ref._bindingMap;
+    if (map == null) {
+      // TODO(rafaelw): Setup a MutationObserver on content to detect
+      // when the instanceMap is invalid.
+      map = new _InstanceBindingMap(content, delegate);
+      ref._bindingMap = map;
+    }
 
-    _addBindings(instance, model, delegate);
+    var instance = map.hasSubTemplate
+        ? _deepCloneIgnoreTemplateContent(content)
+        : content.clone(true);
+
+    _addMapBindings(instance, map, model, delegate, bound);
+    // TODO(rafaelw): We can do this more lazily, but setting a sentinel
+    // in the parent of the template element, and creating it when it's
+    // asked for by walking back to find the iterating template.
     _addTemplateInstanceRecord(instance, model);
     return instance;
   }
@@ -57,6 +138,16 @@
     _ensureSetModelScheduled();
   }
 
+  static Node _deepCloneIgnoreTemplateContent(Node node) {
+    var clone = node.clone(false); // Shallow clone.
+    if (isSemanticTemplate(clone)) return clone;
+
+    for (var c = node.firstChild; c != null; c = c.nextNode) {
+      clone.append(_deepCloneIgnoreTemplateContent(c));
+    }
+    return clone;
+  }
+
   /**
    * The binding delegate which is inherited through the tree. It can be used
    * to configure custom syntax for `{{bindings}}` inside this template.
@@ -138,7 +229,7 @@
 
     if (!isNative && _isAttributeTemplate(_node)) {
       if (instanceRef != null) {
-        // TODO(jmesserly): this is just an assert in MDV.
+        // TODO(jmesserly): this is just an assert in TemplateBinding.
         throw new ArgumentError('instanceRef should not be supplied for '
             'attribute templates.');
       }
@@ -269,48 +360,64 @@
 
   static bool _initStyles;
 
+  // This is to replicate template_element.css
+  // TODO(jmesserly): move this to an opt-in CSS file?
   static void _injectStylesheet() {
     if (_initStyles == true) return;
     _initStyles = true;
 
-    var style = new StyleElement();
-    style.text = r'''
-template,
-thead[template],
-tbody[template],
-tfoot[template],
-th[template],
-tr[template],
-td[template],
-caption[template],
-colgroup[template],
-col[template],
-option[template] {
-  display: none;
-}''';
+    var style = new StyleElement()
+        ..text = '$_allTemplatesSelectors { display: none; }';
     document.head.append(style);
   }
 }
 
-class _TemplateBinding extends NodeBinding {
+// TODO(jmesserly): https://github.com/polymer/templatebinding uses
+// TemplateIterator as the binding. This is a nice performance optimization,
+// however it means it doesn't share any of the reflective APIs with
+// NodeBinding: https://github.com/Polymer/TemplateBinding/issues/147
+class _TemplateBinding implements NodeBinding {
   TemplateBindExtension _ext;
+  Object _model;
+  final String property;
+  final String path;
 
-  // TODO(jmesserly): MDV uses TemplateIterator as the node, see:
-  // https://github.com/Polymer/mdv/issues/127
-  _TemplateBinding(ext, name, model, path)
-      : _ext = ext, super(ext._node, name, model, path) {
-    _ext._templateIterator.inputs.bind(property, model, this.path);
+  Node get node => _ext._node;
+
+  get model => _model;
+
+  bool get closed => _ext == null;
+
+  get value => _observer.value;
+
+  set value(newValue) {
+    _observer.value = newValue;
   }
 
-  // These are no-ops because we don't use the underlying PathObserver.
-  void _observePath() {}
+  // No need to cache this since we only have it to support get/set value.
+  get _observer {
+    if ((_model is PathObserver || _model is CompoundPathObserver) &&
+        path == 'value') {
+      return _model;
+    }
+    return new PathObserver(_model, path);
+  }
+
+  _TemplateBinding(this._ext, this.property, this._model, this.path);
+
   void valueChanged(newValue) {}
 
+  sanitizeBoundValue(value) => value == null ? '' : '$value';
+
   void close() {
     if (closed) return;
-    var templateIterator = _ext._templateIterator;
-    if (templateIterator != null) templateIterator.inputs.unbind(property);
-    super.close();
+
+    // TODO(jmesserly): unlike normal NodeBinding.close methods this will remove
+    // the binding from _node.bindings. Is that okay?
+    _ext.unbind(property);
+
+    _model = null;
+    _ext = null;
   }
 }
 
diff --git a/pkg/template_binding/lib/src/template_iterator.dart b/pkg/template_binding/lib/src/template_iterator.dart
index 981adf5..878e2e7 100644
--- a/pkg/template_binding/lib/src/template_iterator.dart
+++ b/pkg/template_binding/lib/src/template_iterator.dart
@@ -17,32 +17,23 @@
 // See: https://github.com/polymer/TemplateBinding/issues/59
 bool _toBoolean(value) => null != value && false != value;
 
-Node _createDeepCloneAndDecorateTemplates(Node node, BindingDelegate delegate) {
-  var clone = node.clone(false); // Shallow clone.
-  if (isSemanticTemplate(clone)) {
-    TemplateBindExtension.decorate(clone, node);
-    if (delegate != null) {
-      templateBindFallback(clone)._bindingDelegate = delegate;
-    }
+List _getBindings(Node node, BindingDelegate delegate) {
+  if (node is Element) {
+    return _parseAttributeBindings(node, delegate);
   }
 
-  for (var c = node.firstChild; c != null; c = c.nextNode) {
-    clone.append(_createDeepCloneAndDecorateTemplates(c, delegate));
+  if (node is Text) {
+    var tokens = _parseMustaches(node.text, 'text', node, delegate);
+    if (tokens != null) return ['text', tokens];
   }
-  return clone;
+
+  return null;
 }
 
 void _addBindings(Node node, model, [BindingDelegate delegate]) {
-  List bindings = null;
-  if (node is Element) {
-    bindings = _parseAttributeBindings(node);
-  } else if (node is Text) {
-    var tokens = _parseMustacheTokens(node.text);
-    if (tokens != null) bindings = ['text', tokens];
-  }
-
+  var bindings = _getBindings(node, delegate);
   if (bindings != null) {
-    _processBindings(bindings, node, model, delegate);
+    _processBindings(bindings, node, model);
   }
 
   for (var c = node.firstChild; c != null; c = c.nextNode) {
@@ -50,23 +41,34 @@
   }
 }
 
-List _parseAttributeBindings(Element element) {
+
+List _parseAttributeBindings(Element element, BindingDelegate delegate) {
   var bindings = null;
   var ifFound = false;
   var bindFound = false;
   var isTemplateNode = isSemanticTemplate(element);
 
   element.attributes.forEach((name, value) {
+    // Allow bindings expressed in attributes to be prefixed with underbars.
+    // We do this to allow correct semantics for browsers that don't implement
+    // <template> where certain attributes might trigger side-effects -- and
+    // for IE which sanitizes certain attributes, disallowing mustache
+    // replacements in their text.
+    while (name[0] == '_') {
+      name = name.substring(1);
+    }
+
     if (isTemplateNode) {
       if (name == 'if') {
         ifFound = true;
+        if (value == '') value = '{{}}'; // Accept 'naked' if.
       } else if (name == 'bind' || name == 'repeat') {
         bindFound = true;
-        if (value == '') value = '{{}}';
+        if (value == '') value = '{{}}'; // Accept 'naked' bind & repeat.
       }
     }
 
-    var tokens = _parseMustacheTokens(value);
+    var tokens = _parseMustaches(value, name, element, delegate);
     if (tokens != null) {
       if (bindings == null) bindings = [];
       bindings..add(name)..add(tokens);
@@ -76,90 +78,70 @@
   // Treat <template if> as <template bind if>
   if (ifFound && !bindFound) {
     if (bindings == null) bindings = [];
-    bindings..add('bind')..add(_parseMustacheTokens('{{}}'));
+    bindings..add('bind')
+        ..add(_parseMustaches('{{}}', 'bind', element, delegate));
   }
 
   return bindings;
 }
 
 void _processBindings(List bindings, Node node, model,
-    BindingDelegate delegate) {
+    [List<NodeBinding> bound]) {
 
   for (var i = 0; i < bindings.length; i += 2) {
-    _setupBinding(node, bindings[i], bindings[i + 1], model, delegate);
-  }
-}
-
-void _setupBinding(Node node, String name, List tokens, model,
-    BindingDelegate delegate) {
-
-  if (_isSimpleBinding(tokens)) {
-    _bindOrDelegate(node, name, model, tokens[1], delegate);
-    return;
-  }
-
-  // TODO(jmesserly): MDV caches the closure on the tokens, but I'm not sure
-  // why they do that instead of just caching the entire CompoundBinding object
-  // and unbindAll then bind to the new model.
-  var replacementBinding = new CompoundBinding()
-      ..scheduled = true
-      ..combinator = (values) {
-    var newValue = new StringBuffer();
-
-    for (var i = 0, text = true; i < tokens.length; i++, text = !text) {
-      if (text) {
-        newValue.write(tokens[i]);
-      } else {
-        var value = values[i];
-        if (value != null) {
-          newValue.write(value);
+    var name = bindings[i];
+    var tokens = bindings[i + 1];
+    var bindingModel = model;
+    var bindingPath = tokens.tokens[1];
+    if (tokens.hasOnePath) {
+      var delegateFn = tokens.tokens[2];
+      if (delegateFn != null) {
+        var delegateBinding = delegateFn(model, node);
+        if (delegateBinding != null) {
+          bindingModel = delegateBinding;
+          bindingPath = 'value';
         }
       }
+
+      if (!tokens.isSimplePath) {
+        bindingModel = new PathObserver(bindingModel, bindingPath,
+            computeValue: tokens.combinator);
+        bindingPath = 'value';
+      }
+    } else {
+      var observer = new CompoundPathObserver(computeValue: tokens.combinator);
+      for (var j = 1; j < tokens.tokens.length; j += 3) {
+        var subModel = model;
+        var subPath = tokens.tokens[j];
+        var delegateFn = tokens.tokens[j + 1];
+        var delegateBinding = delegateFn != null ?
+            delegateFn(subModel, node) : null;
+
+        if (delegateBinding != null) {
+          subModel = delegateBinding;
+          subPath = 'value';
+        }
+
+        observer.addPath(subModel, subPath);
+      }
+
+      observer.start();
+      bindingModel = observer;
+      bindingPath = 'value';
     }
 
-    return newValue.toString();
-  };
-
-  for (var i = 1; i < tokens.length; i += 2) {
-    // TODO(jmesserly): not sure if this index is correct. See my comment here:
-    // https://github.com/Polymer/mdv/commit/f1af6fe683fd06eed2a7a7849f01c227db12cda3#L0L1035
-    _bindOrDelegate(replacementBinding, i, model, tokens[i], delegate);
-  }
-
-  replacementBinding.resolve();
-
-  nodeBind(node).bind(name, replacementBinding, 'value');
-}
-
-void _bindOrDelegate(node, name, model, String path,
-    BindingDelegate delegate) {
-
-  if (delegate != null) {
-    var delegateBinding = delegate.getBinding(model, path, name, node);
-    if (delegateBinding != null) {
-      model = delegateBinding;
-      path = 'value';
-    }
-  }
-
-  if (node is CompoundBinding) {
-    node.bind(name, model, path);
-  } else {
-    nodeBind(node).bind(name, model, path);
+    var binding = nodeBind(node).bind(name, bindingModel, bindingPath);
+    if (bound != null) bound.add(binding);
   }
 }
 
-/** True if and only if [tokens] is of the form `['', path, '']`. */
-bool _isSimpleBinding(List<String> tokens) =>
-    tokens.length == 3 && tokens[0].isEmpty && tokens[2].isEmpty;
-
 /**
  * Parses {{ mustache }} bindings.
  *
- * Returns null if there are no matches. Otherwise returns
- * [TEXT, (PATH, TEXT)+] if there is at least one mustache.
+ * Returns null if there are no matches. Otherwise returns the parsed tokens.
  */
-List<String> _parseMustacheTokens(String s) {
+_MustacheTokens _parseMustaches(String s, String name, Node node,
+    BindingDelegate delegate) {
   if (s.isEmpty) return null;
 
   var tokens = null;
@@ -172,18 +154,63 @@
     if (endIndex < 0) {
       if (tokens == null) return null;
 
-      tokens.add(s.substring(lastIndex));
+      tokens.add(s.substring(lastIndex)); // TEXT
       break;
     }
 
-    if (tokens == null) tokens = <String>[];
+    if (tokens == null) tokens = [];
     tokens.add(s.substring(lastIndex, startIndex)); // TEXT
-    tokens.add(s.substring(startIndex + 2, endIndex).trim()); // PATH
+    var pathString = s.substring(startIndex + 2, endIndex).trim();
+    tokens.add(pathString); // PATH
+    var delegateFn = delegate == null ? null :
+        delegate.prepareBinding(pathString, name, node);
+    tokens.add(delegateFn);
+
     lastIndex = endIndex + 2;
   }
 
   if (lastIndex == length) tokens.add('');
-  return tokens;
+
+  return new _MustacheTokens(tokens);
+}
+
+class _MustacheTokens {
+  bool get hasOnePath => tokens.length == 4;
+  bool get isSimplePath => hasOnePath && tokens[0] == '' && tokens[3] == '';
+
+  /** [TEXT, (PATH, TEXT, DELEGATE_FN)+] if there is at least one mustache. */
+  // TODO(jmesserly): clean up the type here?
+  final List tokens;
+
+  // Dart note: I think this is cached in JavaScript to avoid an extra
+  // allocation per template instance. Seems reasonable, so we do the same.
+  Function _combinator;
+  Function get combinator => _combinator;
+
+  _MustacheTokens(this.tokens) {
+    // Should be: [TEXT, (PATH, TEXT, DELEGATE_FN)+].
+    assert((tokens.length + 2) % 3 == 0);
+
+    _combinator = hasOnePath ? _singleCombinator : _listCombinator;
+  }
+
+  // Dart note: split "combinator" into the single/list variants, so the
+  // argument can be typed.
+  String _singleCombinator(Object value) {
+    if (value == null) value = '';
+    return '${tokens[0]}$value${tokens[3]}';
+  }
+
+  String _listCombinator(List<Object> values) {
+    var newValue = new StringBuffer(tokens[0]);
+    for (var i = 1; i < tokens.length; i += 3) {
+      var value = values[(i - 1) ~/ 3];
+      if (value != null) newValue.write(value);
+      newValue.write(tokens[i + 2]);
+    }
+
+    return newValue.toString();
+  }
 }
 
 void _addTemplateInstanceRecord(fragment, model) {
@@ -201,106 +228,150 @@
   }
 }
 
-
 class _TemplateIterator {
-  final Element _templateElement;
-  final List<Node> terminators = [];
-  CompoundBinding inputs;
+  final TemplateBindExtension _templateExt;
+
+  /**
+   * Flattened array of tuples:
+   * <instanceTerminatorNode, [bindingsSetupByInstance]>
+   */
+  final List terminators = [];
   List iteratedValue;
   bool closed = false;
+  bool depsChanging = false;
 
-  StreamSubscription _sub;
+  bool hasRepeat = false, hasBind = false, hasIf = false;
+  Object repeatModel, bindModel, ifModel;
+  String repeatPath, bindPath, ifPath;
 
-  _TemplateIterator(this._templateElement) {
-    inputs = new CompoundBinding(resolveInputs);
-  }
+  StreamSubscription _valueSub, _arraySub;
 
-  resolveInputs(Map values) {
-    if (closed) return;
+  bool _initPrepareFunctions = false;
+  PrepareInstanceModelFunction _instanceModelFn;
+  PrepareInstancePositionChangedFunction _instancePositionChangedFn;
 
-    if (values.containsKey('if') && !_toBoolean(values['if'])) {
-      valueChanged(null);
-    } else if (values.containsKey('repeat')) {
-      valueChanged(values['repeat']);
-    } else if (values.containsKey('bind') || values.containsKey('if')) {
-      valueChanged([values['bind']]);
-    } else {
-      valueChanged(null);
+  _TemplateIterator(this._templateExt);
+
+  Element get _templateElement => _templateExt._node;
+
+  resolve() {
+    depsChanging = false;
+
+    if (_valueSub != null) {
+      _valueSub.cancel();
+      _valueSub = null;
     }
-    // We don't return a value to the CompoundBinding; instead we skip a hop and
-    // call valueChanged directly.
-    return null;
+
+    if (!hasRepeat && !hasBind) {
+      _valueChanged(null);
+      return;
+    }
+
+    final model = hasRepeat ? repeatModel : bindModel;
+    final path = hasRepeat ? repeatPath : bindPath;
+
+    var valueObserver;
+    if (!hasIf) {
+      valueObserver = new PathObserver(model, path,
+          computeValue: hasRepeat ? null : (x) => [x]);
+    } else {
+      // TODO(jmesserly): I'm not sure if closing over this is necessary for
+      // correctness. It does seem useful if the valueObserver gets fired after
+      // hasRepeat has changed, due to async nature of things.
+      final isRepeat = hasRepeat;
+
+      valueFn(List values) {
+        var modelValue = values[0];
+        var ifValue = values[1];
+        if (!_toBoolean(ifValue)) return null;
+        return isRepeat ? modelValue : [ modelValue ];
+      }
+
+      valueObserver = new CompoundPathObserver(computeValue: valueFn)
+          ..addPath(model, path)
+          ..addPath(ifModel, ifPath)
+          ..start();
+    }
+
+    _valueSub = valueObserver.changes.listen(
+        (r) => _valueChanged(r.last.newValue));
+    _valueChanged(valueObserver.value);
   }
 
-  void valueChanged(value) {
-    if (value is! List) value = null;
-
+  void _valueChanged(newValue) {
     var oldValue = iteratedValue;
     unobserve();
-    iteratedValue = value;
 
-    if (iteratedValue is Observable) {
-      _sub = (iteratedValue as Observable).changes.listen(_handleChanges);
+    if (newValue is List) {
+      iteratedValue = newValue;
+    } else if (newValue is Iterable) {
+      // Dart note: we support Iterable by calling toList.
+      // But we need to be careful to observe the original iterator if it
+      // supports that.
+      iteratedValue = (newValue as Iterable).toList();
+    } else {
+      iteratedValue = null;
+    }
+
+    if (iteratedValue != null && newValue is Observable) {
+      _arraySub = (newValue as Observable).changes.listen(
+          _handleSplices);
     }
 
     var splices = calculateSplices(
         iteratedValue != null ? iteratedValue : [],
         oldValue != null ? oldValue : []);
 
-    if (splices.length > 0) _handleChanges(splices);
-
-    if (inputs.length == 0) {
-      close();
-      templateBindFallback(_templateElement)._templateIterator = null;
-    }
+    if (splices.isNotEmpty) _handleSplices(splices);
   }
 
   Node getTerminatorAt(int index) {
     if (index == -1) return _templateElement;
-    var terminator = terminators[index];
-    if (isSemanticTemplate(terminator) &&
-        !identical(terminator, _templateElement)) {
-      var subIterator = templateBindFallback(terminator)._templateIterator;
-      if (subIterator != null) {
-        return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
-      }
+    var terminator = terminators[index * 2];
+    if (!isSemanticTemplate(terminator) ||
+        identical(terminator, _templateElement)) {
+      return terminator;
     }
 
-    return terminator;
+    var subIter = templateBindFallback(terminator)._iterator;
+    if (subIter == null) return terminator;
+
+    return subIter.getTerminatorAt(subIter.terminators.length ~/ 2 - 1);
   }
 
+  // TODO(rafaelw): If we inserting sequences of instances we can probably
+  // avoid lots of calls to getTerminatorAt(), or cache its result.
   void insertInstanceAt(int index, DocumentFragment fragment,
-        List<Node> instanceNodes) {
+        List<Node> instanceNodes, List<NodeBinding> bound) {
 
     var previousTerminator = getTerminatorAt(index - 1);
     var terminator = null;
     if (fragment != null) {
       terminator = fragment.lastChild;
-    } else if (instanceNodes.length > 0) {
+    } else if (instanceNodes != null && instanceNodes.isNotEmpty) {
       terminator = instanceNodes.last;
     }
     if (terminator == null) terminator = previousTerminator;
 
-    terminators.insert(index, terminator);
-
+    terminators.insertAll(index * 2, [terminator, bound]);
     var parent = _templateElement.parentNode;
     var insertBeforeNode = previousTerminator.nextNode;
 
     if (fragment != null) {
       parent.insertBefore(fragment, insertBeforeNode);
-      return;
-    }
-
-    for (var node in instanceNodes) {
-      parent.insertBefore(node, insertBeforeNode);
+    } else if (instanceNodes != null) {
+      for (var node in instanceNodes) {
+        parent.insertBefore(node, insertBeforeNode);
+      }
     }
   }
 
-  List<Node> extractInstanceAt(int index) {
+  _BoundNodes extractInstanceAt(int index) {
     var instanceNodes = <Node>[];
     var previousTerminator = getTerminatorAt(index - 1);
     var terminator = getTerminatorAt(index);
-    terminators.removeAt(index);
+    var bound = terminators[index * 2 + 1];
+    terminators.removeRange(index * 2, index * 2 + 2);
 
     var parent = _templateElement.parentNode;
     while (terminator != previousTerminator) {
@@ -309,45 +380,41 @@
       node.remove();
       instanceNodes.add(node);
     }
-    return instanceNodes;
+    return new _BoundNodes(instanceNodes, bound);
   }
 
-  getInstanceModel(model, BindingDelegate delegate) {
-    if (delegate != null) {
-      return delegate.getInstanceModel(_templateElement, model);
-    }
-    return model;
-  }
-
-  DocumentFragment getInstanceFragment(model, BindingDelegate delegate) {
-    return templateBind(_templateElement).createInstance(model, delegate);
-  }
-
-  void _handleChanges(Iterable<ChangeRecord> splices) {
+  void _handleSplices(Iterable<ChangeRecord> splices) {
     if (closed) return;
 
     splices = splices.where((s) => s is ListChangeRecord);
 
-    var template = _templateElement;
-    var delegate = templateBind(template).bindingDelegate;
+    final template = _templateElement;
+    final delegate = _templateExt._self.bindingDelegate;
 
     if (template.parentNode == null || template.ownerDocument.window == null) {
       close();
-      // TODO(jmesserly): MDV calls templateIteratorTable.delete(this) here,
-      // but I think that's a no-op because only nodes are used as keys.
-      // See https://github.com/Polymer/mdv/pull/114.
       return;
     }
 
-    var instanceCache = new HashMap(equals: identical);
+    // Dart note: the JavaScript code relies on the distinction between null
+    // and undefined to track whether the functions are prepared. We use a bool.
+    if (!_initPrepareFunctions) {
+      _initPrepareFunctions = true;
+      if (delegate != null) {
+        _instanceModelFn = delegate.prepareInstanceModel(template);
+        _instancePositionChangedFn =
+            delegate.prepareInstancePositionChanged(template);
+      }
+    }
+
+    var instanceCache = new HashMap<Object, _BoundNodes>(equals: identical);
     var removeDelta = 0;
     for (var splice in splices) {
       for (int i = 0; i < splice.removedCount; i++) {
-        var instanceNodes = extractInstanceAt(splice.index + removeDelta);
-        if (instanceNodes.length == 0) continue;
-        var model = nodeBindFallback(instanceNodes.first)
-            ._templateInstance.model;
-        instanceCache[model] = instanceNodes;
+        var instance = extractInstanceAt(splice.index + removeDelta);
+        if (instance.nodes.length == 0) continue;
+        var model = nodeBind(instance.nodes.first).templateInstance.model;
+        instanceCache[model] = instance;
       }
 
       removeDelta -= splice.addedCount;
@@ -360,51 +427,109 @@
 
         var model = iteratedValue[addIndex];
         var fragment = null;
-        var instanceNodes = instanceCache.remove(model);
-        if (instanceNodes == null) {
-          var actualModel = getInstanceModel(model, delegate);
-          fragment = getInstanceFragment(actualModel, delegate);
+        var instance = instanceCache.remove(model);
+        List bound;
+        List instanceNodes = null;
+        if (instance != null && instance.nodes.isNotEmpty) {
+          bound = instance.bound;
+          instanceNodes = instance.nodes;
+        } else {
+          bound = [];
+          if (_instanceModelFn != null) {
+            model = _instanceModelFn(model);
+          }
+          if (model != null) {
+            fragment = _templateExt.createInstance(model, delegate, bound);
+          }
         }
 
-        insertInstanceAt(addIndex, fragment, instanceNodes);
+        insertInstanceAt(addIndex, fragment, instanceNodes, bound);
       }
     }
 
-    for (var instanceNodes in instanceCache.values) {
-      instanceNodes.forEach(_unbindAllRecursively);
+    for (var instance in instanceCache.values) {
+      closeInstanceBindings(instance.bound);
+    }
+
+    if (_instancePositionChangedFn != null) reportInstancesMoved(splices);
+  }
+
+  void reportInstanceMoved(int index) {
+    var previousTerminator = getTerminatorAt(index - 1);
+    var terminator = getTerminatorAt(index);
+    if (identical(previousTerminator, terminator)) {
+      return; // instance has zero nodes.
+    }
+
+    // We must use the first node of the instance, because any subsequent
+    // nodes may have been generated by sub-templates.
+    // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the
+    // first node was removed by script.
+    var instance = nodeBind(previousTerminator.nextNode).templateInstance;
+    _instancePositionChangedFn(instance, index);
+  }
+
+  void reportInstancesMoved(Iterable<ChangeRecord> splices) {
+    var index = 0;
+    var offset = 0;
+    for (ListChangeRecord splice in splices) {
+      if (offset != 0) {
+        while (index < splice.index) {
+          reportInstanceMoved(index);
+          index++;
+        }
+      } else {
+        index = splice.index;
+      }
+
+      while (index < splice.index + splice.addedCount) {
+        reportInstanceMoved(index);
+        index++;
+      }
+
+      offset += splice.addedCount - splice.removedCount;
+    }
+
+    if (offset == 0) return;
+
+    var length = terminators.length ~/ 2;
+    while (index < length) {
+      reportInstanceMoved(index);
+      index++;
     }
   }
 
+  void closeInstanceBindings(List<NodeBinding> bound) {
+    for (var binding in bound) binding.close();
+  }
+
   void unobserve() {
-    if (_sub == null) return;
-    _sub.cancel();
-    _sub = null;
+    if (_arraySub == null) return;
+    _arraySub.cancel();
+    _arraySub = null;
   }
 
   void close() {
     if (closed) return;
 
     unobserve();
-    inputs.close();
+    for (var i = 1; i < terminators.length; i += 2) {
+      closeInstanceBindings(terminators[i]);
+    }
+
     terminators.clear();
+    if (_valueSub != null) {
+      _valueSub.cancel();
+      _valueSub = null;
+    }
+    _templateExt._iterator = null;
     closed = true;
   }
+}
 
-  static void _unbindAllRecursively(Node node) {
-    var nodeExt = nodeBindFallback(node);
-    nodeExt._templateInstance = null;
-    if (isSemanticTemplate(node)) {
-      // Make sure we stop observing when we remove an element.
-      var templateIterator = nodeExt._templateIterator;
-      if (templateIterator != null) {
-        templateIterator.close();
-        nodeExt._templateIterator = null;
-      }
-    }
-
-    nodeBind(node).unbindAll();
-    for (var c = node.firstChild; c != null; c = c.nextNode) {
-      _unbindAllRecursively(c);
-    }
-  }
+// Dart note: the JavaScript version just puts an expando on the array.
+class _BoundNodes {
+  final List<Node> nodes;
+  final List<NodeBinding> bound;
+  _BoundNodes(this.nodes, this.bound);
 }
diff --git a/pkg/template_binding/lib/template_binding.dart b/pkg/template_binding/lib/template_binding.dart
index c8bd3b6..b1ef7b5 100644
--- a/pkg/template_binding/lib/template_binding.dart
+++ b/pkg/template_binding/lib/template_binding.dart
@@ -24,11 +24,17 @@
 import 'dart:svg' show SvgSvgElement;
 import 'package:observe/observe.dart';
 
+import 'src/binding_delegate.dart';
+import 'src/node_binding.dart';
 import 'src/list_diff.dart' show calculateSplices, ListChangeDelta;
 
+export 'src/binding_delegate.dart';
+export 'src/node_binding.dart' show NodeBinding;
+
 part 'src/element.dart';
 part 'src/input_bindings.dart';
 part 'src/input_element.dart';
+part 'src/instance_binding_map.dart';
 part 'src/node.dart';
 part 'src/select_element.dart';
 part 'src/template.dart';
@@ -141,7 +147,7 @@
  * and COL), OPTION, and OPTGROUP.
  */
 bool isSemanticTemplate(Node n) => n is Element &&
-    ((n as Element).localName == 'template' || _isAttributeTemplate(n));
+    (n.localName == 'template' || _isAttributeTemplate(n));
 
 // TODO(jmesserly): const set would be better
 const _SEMANTIC_TEMPLATE_TAGS = const {
diff --git a/pkg/template_binding/test/analyzer_test.dart b/pkg/template_binding/test/analyzer_test.dart
deleted file mode 100644
index 5b47d43..0000000
--- a/pkg/template_binding/test/analyzer_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013, 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.
-
-library template_binding.test.analyzer_test;
-
-import 'dart:html';
-import 'package:template_binding/template_binding.dart';
-
-// @static-clean
-
-// This test ensures template_binding compiles without errors.
-void main() {
-  // To make analyzer happy about unused imports.
-  nodeBind(document);
-}
diff --git a/pkg/template_binding/test/binding_syntax.dart b/pkg/template_binding/test/binding_syntax.dart
new file mode 100644
index 0000000..384dbf9
--- /dev/null
+++ b/pkg/template_binding/test/binding_syntax.dart
@@ -0,0 +1,206 @@
+// Copyright (c) 2013, 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.
+
+library template_binding.test.binding_syntax;
+
+import 'dart:collection';
+import 'dart:html';
+import 'package:template_binding/template_binding.dart';
+import 'package:observe/observe.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/unittest.dart';
+import 'utils.dart';
+
+// Note: this test is executed by template_element_test.dart
+
+syntaxTests(FooBarModel fooModel([foo, bar])) {
+  observeTest('prepareBinding', () {
+    var model = fooModel('bar');
+    var testSyntax = new TestBindingSyntax();
+    var div = createTestHtml(
+        '<template bind>{{ foo }}'
+          '<template bind>{{ foo }}</template>'
+        '</template>');
+    recursivelySetTemplateModel(div, model, testSyntax);
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 4);
+    expect(div.nodes.last.text, 'bar');
+    expect(div.nodes[2].tagName, 'TEMPLATE');
+    expect(testSyntax.log, [
+      ['prepare', '', 'bind', 'TEMPLATE'],
+      ['bindFn', model, 'TEMPLATE', 0],
+      ['prepare', 'foo', 'text', 'TEXT'],
+      ['prepare', '', 'bind', 'TEMPLATE'],
+      ['bindFn', model, 'TEXT', 2],
+      ['bindFn', model, 'TEMPLATE', 3],
+      ['prepare', 'foo', 'text', 'TEXT'],
+      ['bindFn', model, 'TEXT', 6],
+    ]);
+  });
+
+  observeTest('prepareInstanceModel', () {
+    var model = toObservable([fooModel(1), fooModel(2), fooModel(3)]);
+
+    var testSyntax = new TestModelSyntax();
+    testSyntax.altModels.addAll([fooModel('a'), fooModel('b'), fooModel('c')]);
+
+    var div = createTestHtml('<template repeat>{{ foo }}</template>');
+
+    var template = div.nodes[0];
+    recursivelySetTemplateModel(div, model, testSyntax);
+    performMicrotaskCheckpoint();
+
+    expect(div.nodes.length, 4);
+    expect(div.nodes[0].tagName, 'TEMPLATE');
+    expect(div.nodes[1].text, 'a');
+    expect(div.nodes[2].text, 'b');
+    expect(div.nodes[3].text, 'c');
+
+    expect(testSyntax.log, [
+      ['prepare', template],
+      ['bindFn', model[0]],
+      ['bindFn', model[1]],
+      ['bindFn', model[2]],
+    ]);
+  });
+
+  observeTest('prepareInstanceModel - reorder instances', () {
+    var model = toObservable([0, 1, 2]);
+
+    var div = createTestHtml('<template repeat>{{}}</template>');
+    var template = div.firstChild;
+    var delegate = new TestInstanceModelSyntax();
+
+    recursivelySetTemplateModel(div, model, delegate);
+    performMicrotaskCheckpoint();
+    expect(delegate.prepareCount, 1);
+    expect(delegate.callCount, 3);
+
+    // Note: intentionally mutate in place.
+    model.replaceRange(0, model.length, model.reversed.toList());
+    performMicrotaskCheckpoint();
+    expect(delegate.prepareCount, 1);
+    expect(delegate.callCount, 3);
+  });
+
+  observeTest('prepareInstancePositionChanged', () {
+    var model = toObservable(['a', 'b', 'c']);
+
+    var div = createTestHtml('<template repeat>{{}}</template>');
+    var delegate = new TestPositionChangedSyntax();
+
+    var template = div.nodes[0];
+    recursivelySetTemplateModel(div, model, delegate);
+    performMicrotaskCheckpoint();
+
+    expect(div.nodes.length, 4);
+    expect(div.nodes[0].tagName, 'TEMPLATE');
+    expect(div.nodes[1].text, 'a');
+    expect(div.nodes[2].text, 'b');
+    expect(div.nodes[3].text, 'c');
+
+    expect(delegate.log, [
+      ['prepare', template],
+      ['bindFn', model[0], 0],
+      ['bindFn', model[1], 1],
+      ['bindFn', model[2], 2],
+    ]);
+
+    delegate.log.clear();
+
+    model.removeAt(1);
+    performMicrotaskCheckpoint();
+
+    expect(delegate.log, [['bindFn', 'c', 1]], reason: 'removed item');
+
+    expect(div.nodes.skip(1).map((n) => n.text), ['a', 'c']);
+  });
+
+  observeTest('Basic', () {
+    var model = fooModel(2, 4);
+    var div = createTestHtml(
+        '<template bind>'
+        '{{ foo }} + {{ 2x: bar }} + {{ 4x: bar }}</template>');
+    recursivelySetTemplateModel(div, model, new TimesTwoSyntax());
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 2);
+    expect(div.nodes.last.text, '2 + 8 + ');
+
+    model.foo = 4;
+    model.bar = 8;
+    performMicrotaskCheckpoint();
+    expect(div.nodes.last.text, '4 + 16 + ');
+  });
+
+  // Note: issue-141 test not included here as it's not related to the
+  // BindingDelegate
+}
+
+// TODO(jmesserly): mocks would be cleaner here.
+
+class TestBindingSyntax extends BindingDelegate {
+  var log = [];
+
+  prepareBinding(String path, String name, Node node) {
+    var tagName = node is Element ? node.tagName : 'TEXT';
+    int id = log.length;
+    log.add(['prepare', path, name, tagName]);
+    final outerNode = node;
+    return (model, node) {
+      var tagName = node is Element ? node.tagName : 'TEXT';
+      log.add(['bindFn', model, tagName, id]);
+    };
+  }
+}
+
+class TestModelSyntax extends BindingDelegate {
+  var log = [];
+  var altModels = new ListQueue();
+
+  prepareInstanceModel(template) {
+    log.add(['prepare', template]);
+    return (model) {
+      log.add(['bindFn', model]);
+      return altModels.removeFirst();
+    };
+  }
+}
+
+class TestInstanceModelSyntax extends BindingDelegate {
+  int prepareCount = 0;
+  int callCount = 0;
+  prepareInstanceModel(template) {
+    prepareCount++;
+    return (model) {
+      callCount++;
+      return model;
+    };
+  }
+}
+
+
+class TestPositionChangedSyntax extends BindingDelegate {
+  var log = [];
+
+  prepareInstancePositionChanged(template) {
+    int id = log.length;
+    log.add(['prepare', template]);
+    return (templateInstance, index) {
+      log.add(['bindFn', templateInstance.model, index]);
+    };
+  }
+}
+
+
+class TimesTwoSyntax extends BindingDelegate {
+  prepareBinding(path, name, node) {
+    path = path.trim();
+    if (!path.startsWith('2x:')) return null;
+
+    path = path.substring(3);
+    return (model, _) {
+      return new PathObserver(model, path, computeValue: (x) => 2 * x);
+    };
+  }
+}
diff --git a/pkg/template_binding/test/binding_syntax_test.dart b/pkg/template_binding/test/binding_syntax_test.dart
deleted file mode 100644
index b8b6283..0000000
--- a/pkg/template_binding/test/binding_syntax_test.dart
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2013, 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.
-
-library template_binding.test.binding_syntax_test;
-
-import 'dart:collection';
-import 'dart:html';
-import 'package:template_binding/template_binding.dart';
-import 'package:observe/observe.dart';
-import 'package:unittest/html_config.dart';
-import 'package:unittest/unittest.dart';
-import 'utils.dart';
-
-// Note: this file ported from
-// https://github.com/toolkitchen/mdv/blob/master/tests/syntax.js
-
-main() {
-  useHtmlConfiguration();
-
-  group('Syntax FooBarModel', () {
-    syntaxTests(([f, b]) => new FooBarModel(f, b));
-  });
-  group('Syntax FooBarNotifyModel', () {
-    syntaxTests(([f, b]) => new FooBarNotifyModel(f, b));
-  });
-}
-
-syntaxTests(FooBarModel fooModel([foo, bar])) {
-  setUp(() {
-    document.body.append(testDiv = new DivElement());
-  });
-
-  tearDown(() {
-    testDiv.remove();
-    testDiv = null;
-  });
-
-  observeTest('Registration', () {
-    var model = fooModel('bar');
-    var testSyntax = new TestBindingSyntax();
-    var div = createTestHtml('<template bind>{{ foo }}'
-        '<template bind>{{ foo }}</template></template>');
-    recursivelySetTemplateModel(div, model, testSyntax);
-    performMicrotaskCheckpoint();
-    expect(div.nodes.length, 4);
-    expect(div.nodes.last.text, 'bar');
-    expect(div.nodes[2].tagName, 'TEMPLATE');
-    expect(testSyntax.log, [
-      [model, '', 'bind', 'TEMPLATE'],
-      [model, 'foo', 'text', null],
-      [model, '', 'bind', 'TEMPLATE'],
-      [model, 'foo', 'text', null],
-    ]);
-  });
-
-  observeTest('getInstanceModel', () {
-    var model = toObservable([fooModel(1), fooModel(2), fooModel(3)]);
-
-    var testSyntax = new TestModelSyntax();
-    testSyntax.altModels.addAll([fooModel('a'), fooModel('b'), fooModel('c')]);
-
-    var div = createTestHtml('<template repeat>{{ foo }}</template>');
-
-    var template = div.nodes[0];
-    recursivelySetTemplateModel(div, model, testSyntax);
-    performMicrotaskCheckpoint();
-
-    expect(div.nodes.length, 4);
-    expect(div.nodes[0].tagName, 'TEMPLATE');
-    expect(div.nodes[1].text, 'a');
-    expect(div.nodes[2].text, 'b');
-    expect(div.nodes[3].text, 'c');
-
-    expect(testSyntax.log, [
-      [template, model[0]],
-      [template, model[1]],
-      [template, model[2]],
-    ]);
-  });
-
-  observeTest('getInstanceModel - reorder instances', () {
-    var model = toObservable([0, 1, 2]);
-
-    var div = createTestHtml('<template repeat syntax="Test">{{}}</template>');
-    var template = div.firstChild;
-    var delegate = new TestInstanceModelSyntax();
-
-    recursivelySetTemplateModel(div, model, delegate);
-    performMicrotaskCheckpoint();
-    expect(delegate.count, 3);
-
-    // Note: intentionally mutate in place.
-    model.replaceRange(0, model.length, model.reversed.toList());
-    performMicrotaskCheckpoint();
-    expect(delegate.count, 3);
-  });
-
-  observeTest('Basic', () {
-    var model = fooModel(2, 4);
-    var div = createTestHtml(
-        '<template bind syntax="2x">'
-        '{{ foo }} + {{ 2x: bar }} + {{ 4x: bar }}</template>');
-    recursivelySetTemplateModel(div, model, new TimesTwoSyntax());
-    performMicrotaskCheckpoint();
-    expect(div.nodes.length, 2);
-    expect(div.nodes.last.text, '2 + 8 + ');
-
-    model.foo = 4;
-    model.bar = 8;
-    performMicrotaskCheckpoint();
-    expect(div.nodes.last.text, '4 + 16 + ');
-  });
-}
-
-// TODO(jmesserly): mocks would be cleaner here.
-
-class TestBindingSyntax extends BindingDelegate {
-  var log = [];
-
-  getBinding(model, String path, String name, node) {
-    log.add([model, path, name, node is Element ? node.tagName : null]);
-  }
-}
-
-class TestModelSyntax extends BindingDelegate {
-  var log = [];
-  var altModels = new ListQueue();
-
-  getInstanceModel(template, model) {
-    log.add([template, model]);
-    return altModels.removeFirst();
-  }
-}
-
-class TestInstanceModelSyntax extends BindingDelegate {
-  int count = 0;
-  getInstanceModel(template, model) {
-    count++;
-    return model;
-  }
-}
-
-// Note: this isn't a very smart whitespace handler. A smarter one would only
-// trim indentation, not all whitespace.
-// See "trimOrCompact" in the web_ui Pub package.
-class WhitespaceRemover extends BindingDelegate {
-  int trimmed = 0;
-  int removed = 0;
-
-  DocumentFragment getInstanceFragment(Element template) {
-    var instance = templateBind(template).createInstance();
-    var walker = new TreeWalker(instance, NodeFilter.SHOW_TEXT);
-
-    var toRemove = [];
-    while (walker.nextNode() != null) {
-      var node = walker.currentNode;
-      var text = node.text.replaceAll('\n', '').trim();
-      if (text.length != node.text.length) {
-        if (text.length == 0) {
-          toRemove.add(node);
-        } else {
-          trimmed++;
-          node.text = text;
-        }
-      }
-    }
-
-    for (var node in toRemove) node.remove();
-    removed += toRemove.length;
-
-    return instance;
-  }
-}
-
-class TimesTwoSyntax extends BindingDelegate {
-  getBinding(model, path, name, node) {
-    path = path.trim();
-    if (!path.startsWith('2x:')) return null;
-
-    path = path.substring(3);
-    return new CompoundBinding((values) => values['value'] * 2)
-        ..bind('value', model, path);
-  }
-}
diff --git a/pkg/template_binding/test/custom_element_bindings_test.dart b/pkg/template_binding/test/custom_element_bindings_test.dart
index c9556d5..cc12875 100644
--- a/pkg/template_binding/test/custom_element_bindings_test.dart
+++ b/pkg/template_binding/test/custom_element_bindings_test.dart
@@ -124,7 +124,7 @@
     var element = div.nodes[1];
 
     expect(element is MyCustomElement, true,
-        reason: '${element} should be a MyCustomElement');
+        reason: '$element should be a MyCustomElement');
 
     expect(element.myPoint, model['a']);
     expect(element.scaryMonster, model['b']);
@@ -179,6 +179,7 @@
   unbind(name) => nodeBindFallback(this).unbind(name);
   unbindAll() => nodeBindFallback(this).unbindAll();
   get bindings => nodeBindFallback(this).bindings;
+  get templateInstance => nodeBindFallback(this).templateInstance;
 }
 
 class _MyCustomBinding extends NodeBinding {
diff --git a/pkg/template_binding/test/node_bindings_test.dart b/pkg/template_binding/test/node_bind_test.dart
similarity index 95%
rename from pkg/template_binding/test/node_bindings_test.dart
rename to pkg/template_binding/test/node_bind_test.dart
index 6391b38..fbedcfa 100644
--- a/pkg/template_binding/test/node_bindings_test.dart
+++ b/pkg/template_binding/test/node_bind_test.dart
@@ -2,17 +2,14 @@
 // 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.
 
-library template_binding.test.node_bindings_test;
+library template_binding.test.node_bind_test;
 
 import 'dart:html';
 
-@MirrorsUsed(targets: const [NodeBinding], override:
-    'template_binding.test.node_bindings_test')
-import 'dart:mirrors';
-
 import 'package:observe/observe.dart' show toObservable, PathObserver;
-import 'package:template_binding/template_binding.dart'
-  show nodeBind, NodeBinding;
+import 'package:template_binding/template_binding.dart' show nodeBind;
+import 'package:template_binding/src/node_binding.dart' show getObserverForTest;
+
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 import 'utils.dart';
@@ -72,9 +69,6 @@
   });
 
   observeTest('Observer is Model', () {
-    _observer(x) => reflect(x).getField(
-        privateSymbol(NodeBinding, '_observer')).reflectee;
-
     var text = new Text('');
     var model = toObservable({'a': {'b': {'c': 1}}});
     var observer = new PathObserver(model, 'a.b.c');
@@ -83,7 +77,7 @@
 
     var binding = nodeBind(text).bindings['text'];
     expect(binding, isNotNull);
-    expect(privateField(binding, '_observer'), observer,
+    expect(getObserverForTest(binding), observer,
         reason: 'should reuse observer');
 
     model['a']['b']['c'] = 2;
@@ -654,17 +648,3 @@
     expect(select.value, 'a');
   });
 }
-
-privateField(x, name) => reflect(x).getField(
-    privateSymbol(reflect(x).type, name)).reflectee;
-
-// TODO(jmesserly): fix this when it's easier to get a private symbol.
-privateSymbol(TypeMirror type, String name) {
-  while (type != null) {
-    var symbol = type.variables.keys.firstWhere(
-        (s) => MirrorSystem.getName(s) == name, orElse: () => null);
-    if (symbol != null) return symbol;
-    type = type.superclass;
-  }
-  return null;
-}
diff --git a/pkg/template_binding/test/template_element_test.dart b/pkg/template_binding/test/template_binding_test.dart
similarity index 89%
rename from pkg/template_binding/test/template_element_test.dart
rename to pkg/template_binding/test/template_binding_test.dart
index a878090..2e5c327 100644
--- a/pkg/template_binding/test/template_element_test.dart
+++ b/pkg/template_binding/test/template_binding_test.dart
@@ -2,7 +2,7 @@
 // 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.
 
-library template_binding.test.template_element_test;
+library template_binding.test.template_binding_test;
 
 import 'dart:async';
 import 'dart:collection';
@@ -12,20 +12,21 @@
 import 'package:template_binding/template_binding.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
+
+// TODO(jmesserly): merge this file?
+import 'binding_syntax.dart' show syntaxTests;
 import 'utils.dart';
 
 // Note: this file ported from
-// https://github.com/toolkitchen/mdv/blob/master/tests/template_element.js
+// https://github.com/Polymer/TemplateBinding/blob/ed3266266e751b5ab1f75f8e0509d0d5f0ef35d8/tests/tests.js
+
 // TODO(jmesserly): submit a small cleanup patch to original. I fixed some
 // cases where "div" and "t" were unintentionally using the JS global scope;
 // look for "assertNodesAre".
 
 main() {
   useHtmlConfiguration();
-  group('Template Element', templateElementTests);
-}
 
-templateElementTests() {
   setUp(() {
     document.body.append(testDiv = new DivElement());
   });
@@ -35,36 +36,57 @@
     testDiv = null;
   });
 
-  var expando = new Expando('observeTest');
-  void addExpandos(node) {
-    while (node != null) {
-      expando[node] = node.text;
-      node = node.nextNode;
-    }
-  }
+  group('Template Instantiation', templateInstantiationTests);
 
-  void checkExpandos(node) {
-    expect(node, isNotNull);
-    while (node != null) {
-      expect(expando[node], node.text);
-      node = node.nextNode;
-    }
+  group('Binding Delegate API', () {
+    group('with Observable', () {
+      syntaxTests(([f, b]) => new FooBarModel(f, b));
+    });
+
+    group('with ChangeNotifier', () {
+      syntaxTests(([f, b]) => new FooBarNotifyModel(f, b));
+    });
+  });
+
+  group('Compat', compatTests);
+}
+
+var expando = new Expando('test');
+void addExpandos(node) {
+  while (node != null) {
+    expando[node] = node.text;
+    node = node.nextNode;
   }
+}
+
+void checkExpandos(node) {
+  expect(node, isNotNull);
+  while (node != null) {
+    expect(expando[node], node.text);
+    node = node.nextNode;
+  }
+}
+
+templateInstantiationTests() {
 
   observeTest('Template', () {
     var div = createTestHtml('<template bind={{}}>text</template>');
-    recursivelySetTemplateModel(div, null);
+    templateBind(div.firstChild).model = {};
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
     expect(div.nodes.last.text, 'text');
+
+    templateBind(div.firstChild).model = null;
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 1);
   });
 
   observeTest('Template bind, no parent', () {
     var div = createTestHtml('<template bind>text</template>');
-    var template = div.nodes[0];
+    var template = div.firstChild;
     template.remove();
 
-    recursivelySetTemplateModel(template, toObservable({}));
+    templateBind(template).model = {};
     performMicrotaskCheckpoint();
     expect(template.nodes.length, 0);
     expect(template.nextNode, null);
@@ -72,17 +94,18 @@
 
   observeTest('Template bind, no defaultView', () {
     var div = createTestHtml('<template bind>text</template>');
-    var template = div.nodes[0];
+    var template = div.firstChild;
     var doc = document.implementation.createHtmlDocument('');
     doc.adoptNode(div);
-    recursivelySetTemplateModel(template, toObservable({}));
+    recursivelySetTemplateModel(template, {});
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
   });
 
   observeTest('Template-Empty Bind', () {
     var div = createTestHtml('<template bind>text</template>');
-    recursivelySetTemplateModel(div, null);
+    var template = div.firstChild;
+    templateBind(template).model = {};
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
     expect(div.nodes.last.text, 'text');
@@ -93,7 +116,8 @@
     // Note: changed this value from 0->null because zero is not falsey in Dart.
     // See https://code.google.com/p/dart/issues/detail?id=11956
     var m = toObservable({ 'foo': null });
-    recursivelySetTemplateModel(div, m);
+    var template = div.firstChild;
+    templateBind(template).model = m;
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
 
@@ -101,6 +125,10 @@
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
     expect(div.lastChild.text, 'text');
+
+    templateBind(template).model = null;
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 1);
   });
 
   observeTest('Template Bind If, 2', () {
@@ -119,10 +147,11 @@
 
   observeTest('Template If', () {
     var div = createTestHtml('<template if="{{ foo }}">{{ value }}</template>');
-    // Note: changed this value from 0->null because zero is not falsey in Dart.
-    // See https://code.google.com/p/dart/issues/detail?id=11956
+    // Note: changed this value from 0->null because zero is not falsey in
+    // Dart. See https://code.google.com/p/dart/issues/detail?id=11956
     var m = toObservable({ 'foo': null, 'value': 'foo' });
-    recursivelySetTemplateModel(div, m);
+    var template = div.firstChild;
+    templateBind(template).model = m;
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
 
@@ -130,6 +159,23 @@
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
     expect(div.lastChild.text, 'foo');
+
+    templateBind(template).model = null;
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 1);
+  });
+
+  observeTest('Template Empty-If', () {
+    var div = createTestHtml('<template if>{{ value }}</template>');
+    var m = toObservable({ 'value': 'foo' });
+    recursivelySetTemplateModel(div, null);
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 1);
+
+    recursivelySetTemplateModel(div, m);
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 2);
+    expect(div.lastChild.text, 'foo');
   });
 
   observeTest('Template Repeat If', () {
@@ -138,7 +184,8 @@
     // Note: changed this value from 0->null because zero is not falsey in Dart.
     // See https://code.google.com/p/dart/issues/detail?id=11956
     var m = toObservable({ 'bar': null, 'foo': [1, 2, 3] });
-    recursivelySetTemplateModel(div, m);
+    var template = div.firstChild;
+    templateBind(template).model = m;
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 1);
 
@@ -148,6 +195,10 @@
     expect(div.nodes[1].text, '1');
     expect(div.nodes[2].text, '2');
     expect(div.nodes[3].text, '3');
+
+    templateBind(template).model = null;
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 1);
   });
 
   observeTest('TextTemplateWithNullStringBinding', () {
@@ -177,7 +228,8 @@
     var div = createTestHtml(
         '<template bind="{{ data }}">a{{b}}c</template>');
     var model = toObservable({ 'data': {'b': 'B'} });
-    recursivelySetTemplateModel(div, model);
+    var template = div.firstChild;
+    templateBind(template).model = model;
 
     performMicrotaskCheckpoint();
     expect(div.nodes.length, 2);
@@ -191,9 +243,14 @@
     performMicrotaskCheckpoint();
     expect(div.nodes.last.text, 'aXc');
 
-    model['data'] = null;
+    // Dart note: changed from `null` since our null means don't render a model.
+    model['data'] = toObservable({});
     performMicrotaskCheckpoint();
     expect(div.nodes.last.text, 'ac');
+
+    model['data'] = null;
+    performMicrotaskCheckpoint();
+    expect(div.nodes.length, 1);
   });
 
   observeTest('TextTemplateWithBindingAndConditional', () {
@@ -599,7 +656,7 @@
   });
 
   observeTest('BindWithRef', () {
-    var id = 't${new math.Random().nextDouble()}';
+    var id = 't${new math.Random().nextInt(100)}';
     var div = createTestHtml(
         '<template id="$id">'
           'Hi {{ name }}'
@@ -618,6 +675,23 @@
     expect(t2.nextNode.text, 'Hi Fry');
   });
 
+  observeTest('BindWithDynamicRef', () {
+    var id = 't${new math.Random().nextInt(100)}';
+    var div = createTestHtml(
+        '<template id="$id">'
+          'Hi {{ name }}'
+        '</template>'
+        '<template ref="{{ id }}" bind="{{}}"></template>');
+
+    var t1 = div.firstChild;
+    var t2 = div.nodes[1];
+    var model = toObservable({'name': 'Fry', 'id': id });
+    recursivelySetTemplateModel(div, model);
+
+    performMicrotaskCheckpoint();
+    expect(t2.nextNode.text, 'Hi Fry');
+  });
+
   observeTest('BindChanged', () {
     var model = toObservable({
       'XX': {'name': 'Leela', 'title': 'Captain'},
@@ -1548,6 +1622,7 @@
     }
   });
 
+  // Dart note: this test seems gone from JS. Keeping for posterity sake.
   observeTest('BindShadowDOM createInstance', () {
     if (ShadowRoot.supported) {
       var model = toObservable({'name': 'Leela'});
@@ -1674,11 +1749,100 @@
     expect(template3.content.nodes.length, 1);
     expect(template3.content.nodes.first.text, 'Hello');
   });
+
+  observeTest('issue-285', () {
+    var div = createTestHtml(
+        '<template>'
+          '<template bind if="{{show}}">'
+            '<template id=del repeat="{{items}}">'
+              '{{}}'
+            '</template>'
+          '</template>'
+        '</template>');
+
+    var template = div.firstChild;
+
+    var model = toObservable({
+      'show': true,
+      'items': [1]
+    });
+
+    div.append(templateBind(template).createInstance(model,
+        new Issue285Syntax()));
+
+    performMicrotaskCheckpoint();
+    expect(template.nextNode.nextNode.nextNode.text, '2');
+    model['show'] = false;
+    performMicrotaskCheckpoint();
+    model['show'] = true;
+    performMicrotaskCheckpoint();
+    expect(template.nextNode.nextNode.nextNode.text, '2');
+  });
+
+  observeTest('issue-141', () {
+    var div = createTestHtml(
+        '<template bind>' +
+          '<div foo="{{foo1}} {{foo2}}" bar="{{bar}}"></div>' +
+        '</template>');
+
+    var model = toObservable({
+      'foo1': 'foo1Value',
+      'foo2': 'foo2Value',
+      'bar': 'barValue'
+    });
+
+    recursivelySetTemplateModel(div, model);
+    performMicrotaskCheckpoint();
+
+    expect(div.lastChild.attributes['bar'], 'barValue');
+  });
+}
+
+compatTests() {
+  observeTest('underbar bindings', () {
+    var div = createTestHtml(
+        '<template bind>'
+          '<div _style="color: {{ color }};"></div>'
+          '<img _src="{{ url }}">'
+          '<a _href="{{ url2 }}">Link</a>'
+          '<input type="number" _value="{{ number }}">'
+        '</template>');
+
+    var model = toObservable({
+      'color': 'red',
+      'url': 'pic.jpg',
+      'url2': 'link.html',
+      'number': 4
+    });
+
+    recursivelySetTemplateModel(div, model);
+    performMicrotaskCheckpoint();
+
+    var subDiv = div.firstChild.nextNode;
+    expect(subDiv.attributes['style'], 'color: red;');
+
+    var img = subDiv.nextNode;
+    expect(img.attributes['src'], 'pic.jpg');
+
+    var a = img.nextNode;
+    expect(a.attributes['href'], 'link.html');
+
+    var input = a.nextNode;
+    expect(input.value, '4');
+  });
+}
+
+class Issue285Syntax extends BindingDelegate {
+  prepareInstanceModel(template) {
+    if (template.id == 'del') return (val) => val * 2;
+  }
 }
 
 class TestBindingSyntax extends BindingDelegate {
-  getBinding(model, String path, name, node) {
-    if (path.trim() == 'replaceme') return new ObservableBox('replaced');
+  prepareBinding(String path, name, node) {
+    if (path.trim() == 'replaceme') {
+      return (x, y) => new ObservableBox('replaced');
+    }
     return null;
   }
 }
@@ -1687,11 +1851,13 @@
   int expectedAge = 42;
   int count = 0;
 
-  getBinding(model, path, name, node) {
-    if (name != 'text' || path != 'age')
-      return;
+  prepareBinding(path, name, node) {
+    if (name != 'text' || path != 'age') return null;
 
-    expect(model['age'], expectedAge);
-    count++;
+    return (model, node) {
+      expect(model['age'], expectedAge);
+      count++;
+      return model;
+    };
   }
 }
diff --git a/pkg/unittest/lib/matcher.dart b/pkg/unittest/lib/matcher.dart
index 4830b8f..5cbbed48 100644
--- a/pkg/unittest/lib/matcher.dart
+++ b/pkg/unittest/lib/matcher.dart
@@ -21,7 +21,6 @@
 library matcher;
 
 import 'dart:async';
-import 'package:meta/meta.dart';
 
 import 'src/pretty_print.dart';
 import 'src/utils.dart';
diff --git a/pkg/unittest/lib/src/configuration.dart b/pkg/unittest/lib/src/configuration.dart
index d8d6c81..2a2ea0c 100644
--- a/pkg/unittest/lib/src/configuration.dart
+++ b/pkg/unittest/lib/src/configuration.dart
@@ -30,7 +30,7 @@
 
   /// How long a [TestCase] can run before it is considered an error.
   /// A [timeout] value of [:null:] means that the limit is infinite.
-  Duration get timeout => const Duration(seconds: 20);
+  Duration get timeout => const Duration(minutes: 2);
 
   /**
    * Called as soon as the unittest framework becomes initialized. This is done
diff --git a/pkg/unittest/lib/src/numeric_matchers.dart b/pkg/unittest/lib/src/numeric_matchers.dart
index d040efb..2a725ff 100644
--- a/pkg/unittest/lib/src/numeric_matchers.dart
+++ b/pkg/unittest/lib/src/numeric_matchers.dart
@@ -74,7 +74,7 @@
       'a non-negative value', false);
 
 bool _isNumeric(value) {
-  return value is int || value is double;
+  return value is num;
 }
 
 class _OrderingComparison extends Matcher {
diff --git a/pkg/unittest/lib/src/simple_configuration.dart b/pkg/unittest/lib/src/simple_configuration.dart
index 267fd62..78c303e 100644
--- a/pkg/unittest/lib/src/simple_configuration.dart
+++ b/pkg/unittest/lib/src/simple_configuration.dart
@@ -54,7 +54,7 @@
 
   /// How long a [TestCase] can run before it is considered an error.
   /// A [timeout] value of [:null:] means that the limit is infinite.
-  Duration timeout = const Duration(seconds: 20);
+  Duration timeout = const Duration(minutes: 2);
 
   /**
    * The constructor sets up a failure handler for [expect] that redirects
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 047cd84..7546f40 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -236,6 +236,7 @@
     // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
     //
     // Drop the leading / before the drive letter.
+    // TODO(14577): Handle paths like \\server\share\dir\file.
     path = path.substring(1);
     _logResolution('# Path: Removed leading / -> $path');
   }
@@ -310,27 +311,3 @@
   _logResolution('# Path: $uri -> $uri');
   return uri.toString();
 }
-
-
-class _PlatformHook {
-  // TODO(whesse):  Replace uses of Platform with uses of internal _Platform
-  //   class, to prepare for removal of (deprecated) Platform class.
-  //   Also merge _Platform and _PlatformHook class into _Platform class
-  //   at that time, since _PlatformHook is the only user of _Platform.
-  int get numberOfProcessors => Platform.numberOfProcessors;
-  String get pathSeparator => Platform.pathSeparator;
-  String get operatingSystem => Platform.operatingSystem;
-  String get localHostname => Platform.localHostname;
-  String get version => Platform.version;
-  Map<String, String> get environment => Platform.environment;
-  Uri get script => new Uri.file(Platform.script);
-  String get executable => Platform.executable;
-  List<String>  get executableArguments => Platform.executableArguments;
-  String get packageRoot => Platform.packageRoot;
-}
-
-
-_getPlatform() => new _PlatformHook();
-
-
-
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index a3a2f69..657a457 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -29,7 +29,6 @@
 const char* DartUtils::kIOLibURL = "dart:io";
 const char* DartUtils::kIOLibPatchURL = "dart:io-patch";
 const char* DartUtils::kUriLibURL = "dart:uri";
-const char* DartUtils::kPlatformLibURL = "dart:platform";
 const char* DartUtils::kHttpScheme = "http:";
 
 const char* DartUtils::kIdFieldName = "_id";
@@ -712,29 +711,17 @@
 
   // Set up package root if specified.
   if (package_root != NULL) {
-    Dart_Handle package_root_string = NewString(package_root);
-    if (Dart_IsError(package_root_string)) {
-      return package_root_string;
-    }
-    const int kNumArgs = 1;
-    Dart_Handle dart_args[kNumArgs];
-    dart_args[0] = package_root_string;
-    result = Dart_Invoke(builtin_lib,
+    result = NewString(package_root);
+    if (!Dart_IsError(result)) {
+      const int kNumArgs = 1;
+      Dart_Handle dart_args[kNumArgs];
+      dart_args[0] = result;
+      return Dart_Invoke(builtin_lib,
                          NewString("_setPackageRoot"),
                          kNumArgs,
                          dart_args);
-    if (Dart_IsError(result)) {
-      return result;
     }
   }
-
-  // Setup the platform library's _platform object.
-  internal_lib = Dart_LookupLibrary(NewString(kPlatformLibURL));
-  DART_CHECK_VALID(internal_lib);
-  Dart_Handle platform =
-      Dart_Invoke(builtin_lib, NewString("_getPlatform"), 0, NULL);
-  result = Dart_SetField(internal_lib, NewString("_platform"), platform);
-  DART_CHECK_VALID(result);
   return result;
 }
 
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index ca8fa06..375a9bc 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -204,7 +204,6 @@
   static const char* kIOLibURL;
   static const char* kIOLibPatchURL;
   static const char* kUriLibURL;
-  static const char* kPlatformLibURL;
   static const char* kHttpScheme;
 
   static const char* kIdFieldName;
@@ -251,6 +250,7 @@
     return type() == Dart_CObject_kTypedData &&
            byte_array_type() == Dart_TypedData_kUint8;
   }
+  bool IsSendPort() { return type() == Dart_CObject_kSendPort; }
 
   bool IsTrue() {
     return type() == Dart_CObject_kBool && cobject_->value.as_bool;
@@ -468,6 +468,17 @@
 };
 
 
+class CObjectSendPort : public CObject {
+ public:
+  DECLARE_COBJECT_CONSTRUCTORS(SendPort)
+
+  Dart_Port Value() const { return cobject_->value.as_send_port; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(CObjectSendPort);
+};
+
+
 class CObjectTypedData : public CObject {
  public:
   explicit CObjectTypedData(Dart_CObject *cobject) : CObject(cobject) {
diff --git a/runtime/bin/dbg_connection.cc b/runtime/bin/dbg_connection.cc
index e5abc5e..45edc0c7 100644
--- a/runtime/bin/dbg_connection.cc
+++ b/runtime/bin/dbg_connection.cc
@@ -21,6 +21,8 @@
 namespace dart {
 namespace bin {
 
+extern bool trace_debug_protocol;
+
 int DebuggerConnectionHandler::listener_fd_ = -1;
 dart::Monitor* DebuggerConnectionHandler::handler_lock_ = new dart::Monitor();
 
@@ -29,6 +31,9 @@
 // handler in a static variable.
 static DebuggerConnectionHandler* singleton_handler = NULL;
 
+// The maximum message length to print when --trace_debug_protocol is
+// specified.
+static const int kMaxPrintMessageLen = 1024;
 
 class MessageBuffer {
  public:
@@ -196,6 +201,19 @@
       return;
     }
 
+    if (trace_debug_protocol) {
+      dart::JSONReader r(msgbuf_->buf());
+      const char* msg_end = r.EndOfObject();
+      if (msg_end != NULL) {
+        intptr_t msg_len = msg_end - msgbuf_->buf();
+        int print_len = ((msg_len > kMaxPrintMessageLen)
+                         ? kMaxPrintMessageLen : msg_len);
+        Log::Print("[<<<] Receiving message from debug fd %d:\n%.*s%s\n",
+                   debug_fd_, print_len, msgbuf_->buf(),
+                   ((msg_len > print_len) ? "..." : ""));
+      }
+    }
+
     // Parse out the command portion from the message.
     dart::JSONReader r(msgbuf_->buf());
     bool found = r.Seek("command");
@@ -344,6 +362,15 @@
                                               dart::TextBuffer* msg) {
   ASSERT(debug_fd >= 0);
   ASSERT(IsValidJSON(msg->buf()));
+
+  if (trace_debug_protocol) {
+    int print_len = ((msg->length() > kMaxPrintMessageLen)
+                     ? kMaxPrintMessageLen : msg->length());
+    Log::Print("[>>>] Sending message to debug fd %d:\n%.*s%s\n",
+               debug_fd, print_len, msg->buf(),
+               ((msg->length() > print_len) ? "..." : ""));
+  }
+
   // Sending messages in short pieces can be used to stress test the
   // debugger front-end's message handling code.
   const bool send_in_pieces = false;
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 058d638..01f9f75 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -262,6 +262,9 @@
     CObjectIntptr ptr(request[0]);
     AsyncDirectoryListing* dir_listing =
         reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
+    if (dir_listing->IsEmpty()) {
+      return new CObjectArray(CObject::NewArray(0));
+    }
     const int kArraySize = 128;
     CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize));
     dir_listing->SetArray(response, kArraySize);
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index fd78e80..1417c23 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -65,9 +65,7 @@
   explicit DirectoryListingEntry(DirectoryListingEntry* parent)
     : parent_(parent), lister_(0), done_(false), link_(NULL) {}
 
-  ~DirectoryListingEntry() {
-    ResetLink();
-  }
+  ~DirectoryListingEntry();
 
   ListType Next(DirectoryListing* listing);
 
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index 7dd450a..02f841d 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -187,14 +187,18 @@
     return kListError;
   }
 
-  if (closedir(reinterpret_cast<DIR*>(lister_)) == -1) {
-    return kListError;
-  }
-
   return kListDone;
 }
 
 
+DirectoryListingEntry::~DirectoryListingEntry() {
+  ResetLink();
+  if (lister_ != 0) {
+    closedir(reinterpret_cast<DIR*>(lister_));
+  }
+}
+
+
 void DirectoryListingEntry::ResetLink() {
   if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
     delete link_;
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index c26289c..0bb07e7 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -105,8 +105,8 @@
   dirent entry;
   dirent* result;
   if ((status = TEMP_FAILURE_RETRY(readdir_r(reinterpret_cast<DIR*>(lister_),
-                                    &entry,
-                                    &result))) == 0 &&
+                                   &entry,
+                                   &result))) == 0 &&
       result != NULL) {
     if (!listing->path_buffer().Add(entry.d_name)) {
       done_ = true;
@@ -188,14 +188,18 @@
     return kListError;
   }
 
-  if (closedir(reinterpret_cast<DIR*>(lister_)) == -1) {
-    return kListError;
-  }
-
   return kListDone;
 }
 
 
+DirectoryListingEntry::~DirectoryListingEntry() {
+  ResetLink();
+  if (lister_ != 0) {
+    closedir(reinterpret_cast<DIR*>(lister_));
+  }
+}
+
+
 void DirectoryListingEntry::ResetLink() {
   if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
     delete link_;
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index 074647f..feb9a9c 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -187,14 +187,18 @@
     return kListError;
   }
 
-  if (closedir(reinterpret_cast<DIR*>(lister_)) == -1) {
-    return kListError;
-  }
-
   return kListDone;
 }
 
 
+DirectoryListingEntry::~DirectoryListingEntry() {
+  ResetLink();
+  if (lister_ != 0) {
+    closedir(reinterpret_cast<DIR*>(lister_));
+  }
+}
+
+
 void DirectoryListingEntry::ResetLink() {
   if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
     delete link_;
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index e3e390f..3733a71 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -206,14 +206,18 @@
     return kListError;
   }
 
-  if (FindClose(reinterpret_cast<HANDLE>(lister_)) == 0) {
-    return kListError;
-  }
-
   return kListDone;
 }
 
 
+DirectoryListingEntry::~DirectoryListingEntry() {
+  ResetLink();
+  if (lister_ != 0) {
+    FindClose(reinterpret_cast<HANDLE>(lister_));
+  }
+}
+
+
 void DirectoryListingEntry::ResetLink() {
   if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
     delete link_;
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 96a5d16..4b5e5e6 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -70,10 +70,10 @@
     try {
       socketId = _watchPath(_path, _events, identical(true, _recursive));
     } catch (e) {
-      throw new FileSystemException(
-          "Failed to watch path",
-          _path,
-          e);
+      _controller.addError(new FileSystemException(
+          "Failed to watch path", _path, e));
+      _controller.close();
+      return;
     }
     var socket = new _RawSocket(new _NativeSocket.watch(socketId));
     _subscription = socket.expand((event) {
@@ -89,48 +89,63 @@
           }
           return path;
         }
+        bool getIsDir(event) {
+          if (Platform.isWindows) {
+            // Windows does not get 'isDir' as part of the event.
+            return FileSystemEntity.isDirectorySync(getPath(event));
+          }
+          return (event[0] & FileSystemEvent._IS_DIR) != 0;
+        }
         void add(event) {
           if ((event.type & _events) == 0) return;
           events.add(event);
         }
+        void rewriteMove(event, isDir) {
+          if (event[3]) {
+            add(new FileSystemCreateEvent._(getPath(event), isDir));
+          } else {
+            add(new FileSystemDeleteEvent._(getPath(event), isDir));
+          }
+        }
         while (socket.available() > 0) {
           for (var event in _readEvents()) {
             if (event == null) continue;
+            bool isDir = getIsDir(event);
             var path = getPath(event);
             if ((event[0] & FileSystemEvent.CREATE) != 0) {
-              add(new FileSystemCreateEvent._(path));
+              add(new FileSystemCreateEvent._(path, isDir));
             }
             if ((event[0] & FileSystemEvent.MODIFY) != 0) {
-              add(new FileSystemModifyEvent._(path, true));
+              add(new FileSystemModifyEvent._(path, isDir, true));
             }
             if ((event[0] & FileSystemEvent._MODIFY_ATTRIBUTES) != 0) {
-              add(new FileSystemModifyEvent._(path, false));
+              add(new FileSystemModifyEvent._(path, isDir, false));
             }
             if ((event[0] & FileSystemEvent.MOVE) != 0) {
               int link = event[1];
               if (link > 0) {
                 if (pair.containsKey(link)) {
-                  events.add(
-                      new FileSystemMoveEvent._(getPath(pair[link]), path));
+                  events.add(new FileSystemMoveEvent._(
+                      getPath(pair[link]), isDir, path));
                   pair.remove(link);
                 } else {
                   pair[link] = event;
                 }
               } else {
-                add(new FileSystemMoveEvent._(path, null));
+                rewriteMove(event, isDir);
               }
             }
             if ((event[0] & FileSystemEvent.DELETE) != 0) {
-              add(new FileSystemDeleteEvent._(path));
+              add(new FileSystemDeleteEvent._(path, isDir));
             }
             if ((event[0] & FileSystemEvent._DELETE_SELF) != 0) {
-              add(new FileSystemDeleteEvent._(path));
+              add(new FileSystemDeleteEvent._(path, isDir));
               stop = true;
             }
           }
         }
         for (var event in pair.values) {
-          events.add(new FileSystemMoveEvent._(getPath(event), null));
+          rewriteMove(event, getIsDir(event));
         }
       } else if (event == RawSocketEvent.CLOSED) {
       } else if (event == RawSocketEvent.READ_CLOSED) {
diff --git a/runtime/bin/file_system_watcher.h b/runtime/bin/file_system_watcher.h
index 9434674..21c334f 100644
--- a/runtime/bin/file_system_watcher.h
+++ b/runtime/bin/file_system_watcher.h
@@ -25,7 +25,8 @@
     kDelete = 1 << 2,
     kMove = 1 << 3,
     kModefyAttribute = 1 << 4,
-    kDeleteSelf = 1 << 5
+    kDeleteSelf = 1 << 5,
+    kIsDir = 1 << 6
   };
 
   struct Event {
diff --git a/runtime/bin/file_system_watcher_android.cc b/runtime/bin/file_system_watcher_android.cc
index 63a244a..333bc86 100644
--- a/runtime/bin/file_system_watcher_android.cc
+++ b/runtime/bin/file_system_watcher_android.cc
@@ -67,7 +67,7 @@
   while (offset < bytes) {
     struct inotify_event* e =
         reinterpret_cast<struct inotify_event*>(buffer + offset);
-    Dart_Handle event = Dart_NewList(3);
+    Dart_Handle event = Dart_NewList(4);
     int mask = 0;
     if (e->mask & IN_MODIFY) mask |= kModifyContent;
     if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
@@ -82,6 +82,7 @@
     } else {
       Dart_ListSetAt(event, 2, Dart_Null());
     }
+    Dart_ListSetAt(event, 3, Dart_NewBoolean(e->mask & IN_MOVED_TO));
     Dart_ListSetAt(events, i, event);
     i++;
     offset += kEventSize + e->len;
diff --git a/runtime/bin/file_system_watcher_linux.cc b/runtime/bin/file_system_watcher_linux.cc
index da5dee1..43fe4e1 100644
--- a/runtime/bin/file_system_watcher_linux.cc
+++ b/runtime/bin/file_system_watcher_linux.cc
@@ -26,7 +26,7 @@
   if (fd < 0) return -1;
   int list_events = IN_DELETE_SELF;
   if (events & kCreate) list_events |= IN_CREATE;
-  if (events & kModifyContent) list_events |= IN_MODIFY | IN_ATTRIB;
+  if (events & kModifyContent) list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
   if (events & kDelete) list_events |= IN_DELETE;
   if (events & kMove) list_events |= IN_MOVE;
   int path_fd = TEMP_FAILURE_RETRY(inotify_add_watch(fd, path, list_events));
@@ -63,14 +63,15 @@
   while (offset < bytes) {
     struct inotify_event* e =
         reinterpret_cast<struct inotify_event*>(buffer + offset);
-    Dart_Handle event = Dart_NewList(3);
+    Dart_Handle event = Dart_NewList(4);
     int mask = 0;
-    if (e->mask & IN_MODIFY) mask |= kModifyContent;
+    if (e->mask & IN_CLOSE_WRITE) mask |= kModifyContent;
     if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
     if (e->mask & IN_CREATE) mask |= kCreate;
     if (e->mask & IN_MOVE) mask |= kMove;
     if (e->mask & IN_DELETE) mask |= kDelete;
     if (e->mask & IN_DELETE_SELF) mask |= kDeleteSelf;
+    if (e->mask & IN_ISDIR) mask |= kIsDir;
     Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
     Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
     if (e->len > 0) {
@@ -79,6 +80,7 @@
     } else {
       Dart_ListSetAt(event, 2, Dart_Null());
     }
+    Dart_ListSetAt(event, 3, Dart_NewBoolean(e->mask & IN_MOVED_TO));
     Dart_ListSetAt(events, i, event);
     i++;
     offset += kEventSize + e->len;
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 4aed2e3..65ad6e9 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -264,13 +264,14 @@
       return DartUtils::NewDartOSError();
     }
     size_t path_len = strlen(e.data.path);
-    Dart_Handle event = Dart_NewList(3);
+    Dart_Handle event = Dart_NewList(4);
     int flags = e.data.flags;
     int mask = 0;
     if (flags & kFSEventStreamEventFlagItemModified) mask |= kModifyContent;
     if (flags & kFSEventStreamEventFlagItemRenamed) mask |= kMove;
     if (flags & kFSEventStreamEventFlagItemXattrMod) mask |= kModefyAttribute;
     if (flags & kFSEventStreamEventFlagItemCreated) mask |= kCreate;
+    if (flags & kFSEventStreamEventFlagItemIsDir) mask |= kIsDir;
     if (flags & kFSEventStreamEventFlagItemRemoved) {
       if (path_len == 0) {
         // The removed path is the path being watched.
@@ -283,6 +284,7 @@
     Dart_ListSetAt(event, 1, Dart_NewInteger(1));
     Dart_ListSetAt(event, 2, Dart_NewStringFromUTF8(
         reinterpret_cast<uint8_t*>(e.data.path), path_len));
+    Dart_ListSetAt(event, 3, Dart_NewBoolean(true));
     Dart_ListSetAt(events, i, event);
   }
   return events;
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index e08c28d..9731009 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -83,7 +83,7 @@
     FILE_NOTIFY_INFORMATION* e =
         reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer + offset);
 
-    Dart_Handle event = Dart_NewList(3);
+    Dart_Handle event = Dart_NewList(4);
     int mask = 0;
     if (e->Action == FILE_ACTION_ADDED) mask |= kCreate;
     if (e->Action == FILE_ACTION_REMOVED) mask |= kDelete;
@@ -95,7 +95,7 @@
     Dart_ListSetAt(event, 1, Dart_NewInteger(1));
     Dart_ListSetAt(event, 2, Dart_NewStringFromUTF16(
         reinterpret_cast<uint16_t*>(e->FileName), e->FileNameLength / 2));
-
+    Dart_ListSetAt(event, 3, Dart_NewBoolean(true));
     Dart_ListSetAt(events, i, event);
     i++;
     if (e->NextEntryOffset == 0) break;
diff --git a/runtime/bin/io_service.cc b/runtime/bin/io_service.cc
index 922b98c..c58931c 100644
--- a/runtime/bin/io_service.cc
+++ b/runtime/bin/io_service.cc
@@ -28,18 +28,21 @@
     break;
 
 void IOServiceCallback(Dart_Port dest_port_id,
-                       Dart_Port reply_port_id,
                        Dart_CObject* message) {
+  Dart_Port reply_port_id = ILLEGAL_PORT;
   CObject* response = CObject::IllegalArgumentError();
   CObjectArray request(message);
   if (message->type == Dart_CObject_kArray &&
-      request.Length() == 3 &&
+      request.Length() == 4 &&
       request[0]->IsInt32() &&
-      request[1]->IsInt32() &&
-      request[2]->IsArray()) {
+      request[1]->IsSendPort() &&
+      request[2]->IsInt32() &&
+      request[3]->IsArray()) {
     CObjectInt32 message_id(request[0]);
-    CObjectInt32 request_id(request[1]);
-    CObjectArray data(request[2]);
+    CObjectSendPort reply_port(request[1]);
+    CObjectInt32 request_id(request[2]);
+    CObjectArray data(request[3]);
+    reply_port_id = reply_port.Value();
     switch (request_id.Value()) {
   IO_SERVICE_REQUEST_LIST(CASE_REQUEST);
       default:
@@ -75,4 +78,3 @@
 
 }  // namespace bin
 }  // namespace dart
-
diff --git a/runtime/bin/io_service_patch.dart b/runtime/bin/io_service_patch.dart
index 85f5124..612703e 100644
--- a/runtime/bin/io_service_patch.dart
+++ b/runtime/bin/io_service_patch.dart
@@ -20,7 +20,7 @@
     _initialize(index);
     var completer = new Completer();
     _messageMap[id] = completer;
-    _servicePort[index].send([id, request, data], _replyToPort);
+    _servicePort[index].send([id, _replyToPort, request, data]);
     return completer.future;
   }
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index b6e8ee9..59501a9 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -225,6 +225,16 @@
   return true;
 }
 
+bool trace_debug_protocol = false;
+static bool ProcessTraceDebugProtocolOption(const char* arg) {
+  if (*arg != '\0') {
+    return false;
+  }
+  trace_debug_protocol = true;
+  return true;
+}
+
+
 static struct {
   const char* option_name;
   bool (*process)(const char* option);
@@ -244,6 +254,7 @@
   { "--print-script", ProcessPrintScriptOption },
   { "--check-function-fingerprints", ProcessFingerprintedFunctions },
   { "--enable-vm-service", ProcessEnableVmServiceOption },
+  { "--trace-debug-protocol", ProcessTraceDebugProtocolOption },
   { NULL, NULL }
 };
 
@@ -495,9 +506,7 @@
       Dart_SetField(platform_type, script_name_name, dart_script);
   CHECK_RESULT(set_script_name);
 
-  Dart_Handle debug_name = Dart_DebugName();
-  CHECK_RESULT(debug_name);
-  VmService::SendIsolateStartupMessage(Dart_GetMainPortId(), debug_name);
+  VmService::SendIsolateStartupMessage();
 
   // Make the isolate runnable so that it is ready to handle messages.
   Dart_ExitScope();
diff --git a/runtime/bin/vmservice/running_isolate.dart b/runtime/bin/vmservice/running_isolate.dart
index 13b358a..cf726c8 100644
--- a/runtime/bin/vmservice/running_isolate.dart
+++ b/runtime/bin/vmservice/running_isolate.dart
@@ -5,10 +5,11 @@
 part of vmservice;
 
 class RunningIsolate implements ServiceRequestRouter {
+  final int portId;
   final SendPort sendPort;
   final String name;
 
-  RunningIsolate(this.sendPort, this.name);
+  RunningIsolate(this.portId, this.sendPort, this.name);
 
   Future sendMessage(List request) {
     final completer = new Completer.sync();
diff --git a/runtime/bin/vmservice/running_isolates.dart b/runtime/bin/vmservice/running_isolates.dart
index 5b38223..0cfa02f 100644
--- a/runtime/bin/vmservice/running_isolates.dart
+++ b/runtime/bin/vmservice/running_isolates.dart
@@ -9,28 +9,28 @@
 
   RunningIsolates();
 
-  void isolateStartup(SendPort sp, String name) {
-    if (isolates[sp.hashCode] != null) {
+  void isolateStartup(int portId, SendPort sp, String name) {
+    if (isolates[portId] != null) {
       throw new StateError('Duplicate isolate startup.');
     }
-    var ri = new RunningIsolate(sp, name);
-    isolates[sp.hashCode] = ri;
+    var ri = new RunningIsolate(portId, sp, name);
+    isolates[portId] = ri;
   }
 
-  void isolateShutdown(SendPort sp) {
-    if (isolates[sp.hashCode] == null) {
+  void isolateShutdown(int portId, SendPort sp) {
+    if (isolates[portId] == null) {
       throw new StateError('Unknown isolate.');
     }
-    isolates.remove(sp.hashCode);
+    isolates.remove(portId);
   }
 
   void _isolateCollectionRequest(ServiceRequest request) {
     var members = [];
     var result = {};
-    isolates.forEach((sp, ri) {
+    isolates.forEach((portId, runningIsolate) {
       members.add({
-        'id': sp,
-        'name': ri.name
+        'id': portId,
+        'name': runningIsolate.name
         });
     });
     result['type'] = 'IsolateList';
diff --git a/runtime/bin/vmservice/vmservice.dart b/runtime/bin/vmservice/vmservice.dart
index 83c2168..9c58842fe 100644
--- a/runtime/bin/vmservice/vmservice.dart
+++ b/runtime/bin/vmservice/vmservice.dart
@@ -5,7 +5,7 @@
 library vmservice;
 
 import 'dart:async';
-import "dart:convert";
+import 'dart:convert';
 import 'dart:isolate';
 import 'dart:typed_data';
 
@@ -19,26 +19,29 @@
 class VMService {
   static VMService _instance;
   RunningIsolates runningIsolates = new RunningIsolates();
+  final RawReceivePort receivePort;
 
-  void controlMessageHandler(int code, SendPort sp, String name) {
+  void controlMessageHandler(int code, int port_id, SendPort sp, String name) {
     switch (code) {
       case Constants.ISOLATE_STARTUP_MESSAGE_ID:
-        runningIsolates.isolateStartup(sp, name);
+        runningIsolates.isolateStartup(port_id, sp, name);
       break;
       case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID:
-        runningIsolates.isolateShutdown(sp);
+        runningIsolates.isolateShutdown(port_id, sp);
       break;
     }
   }
 
   void messageHandler(message) {
-    if (message is List && message.length == 3) {
-      controlMessageHandler(message[0], message[1], message[2]);
+    assert(message is List);
+    assert(message.length == 4);
+    if (message is List && message.length == 4) {
+      controlMessageHandler(message[0], message[1], message[2], message[3]);
     }
   }
 
-  VMService._internal() {
-    port.listen(messageHandler);
+  VMService._internal() : receivePort = new RawReceivePort() {
+    receivePort.handler = messageHandler;
   }
 
   factory VMService() {
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index ee4ffb2..d4590ce 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -9,11 +9,16 @@
 
 part 'server.dart';
 
-var _port;
+// The TCP port that the HTTP server listens on.
+int _port;
+
+// The receive port that isolate startup / shutdown messages are delivered on.
+RawReceivePort _receivePort;
 
 main() {
   // Create VmService.
   var service = new VMService();
+  _receivePort = service.receivePort;
   // Start HTTP server.
   var server = new Server(service, _port);
   server.startServer();
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 7da20cc..36130fa 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -143,20 +143,42 @@
 
 
   Dart_Handle library = Dart_RootLibrary();
-  // Set requested port.
+  // Set requested TCP port.
   DartUtils::SetIntegerField(library, "_port", server_port);
   result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL);
   SHUTDOWN_ON_ERROR(result);
 
+  // Retrieve the ReceivePort that the service is waiting on. The _receivePort
+  // variable is setup in the call to main.
+  Dart_Handle receivePort = Dart_GetField(library,
+                                          DartUtils::NewString("_receivePort"));
+  SHUTDOWN_ON_ERROR(receivePort);
+
+  {
+    // Extract the Dart_Port from the receive port.
+    HANDLESCOPE(Isolate::Current());
+    const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort));
+    const Instance& rp = Instance::Cast(unwrapped_rp);
+    // Extract ReceivePort port id.
+    const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp));
+    if (rp_id_obj.IsError()) {
+      const Error& error = Error::Cast(rp_id_obj);
+      error_msg_ = strdup(error.ToErrorCString());
+      Dart_ExitScope();
+      Dart_ShutdownIsolate();
+      return false;
+    }
+    ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint());
+    Integer& id = Integer::Handle();
+    id ^= rp_id_obj.raw();
+    port_ = static_cast<Dart_Port>(id.AsInt64Value());
+  }
+
   Dart_Handle library_name = Dart_NewStringFromCString(kVMServiceLibraryName);
   library = Dart_LookupLibrary(library_name);
   SHUTDOWN_ON_ERROR(library);
   result = LoadResources(library);
   SHUTDOWN_ON_ERROR(result);
-  result = Dart_CompileAll();
-  SHUTDOWN_ON_ERROR(result);
-
-  port_ = Dart_GetMainPortId();
 
   Dart_ExitScope();
   Dart_ExitIsolate();
@@ -392,47 +414,58 @@
 }
 
 
-static Dart_Handle MakeServiceControlMessage(Dart_Port port, intptr_t code) {
+static Dart_Handle MakeServiceControlMessage(Dart_Port port_id, intptr_t code,
+                                             Dart_Handle name) {
   Dart_Handle result;
-  Dart_Handle list = Dart_NewList(3);
+  Dart_Handle list = Dart_NewList(4);
   ASSERT(!Dart_IsError(list));
-  Dart_Handle codeHandle = Dart_NewInteger(code);
-  ASSERT(!Dart_IsError(codeHandle));
-  result = Dart_ListSetAt(list, 0, codeHandle);
+  Dart_Handle code_handle = Dart_NewInteger(code);
+  ASSERT(!Dart_IsError(code_handle));
+  result = Dart_ListSetAt(list, 0, code_handle);
   ASSERT(!Dart_IsError(result));
-  Dart_Handle sendPort = Dart_NewSendPort(port);
+  Dart_Handle port_id_handle = Dart_NewInteger(port_id);
+  ASSERT(!Dart_IsError(port_id_handle));
+  result = Dart_ListSetAt(list, 1, port_id_handle);
+  ASSERT(!Dart_IsError(result));
+  Dart_Handle sendPort = Dart_NewSendPort(port_id);
   ASSERT(!Dart_IsError(sendPort));
-  result = Dart_ListSetAt(list, 1, sendPort);
+  result = Dart_ListSetAt(list, 2, sendPort);
+  ASSERT(!Dart_IsError(result));
+  result = Dart_ListSetAt(list, 3, name);
   ASSERT(!Dart_IsError(result));
   return list;
 }
 
 
-bool VmService::SendIsolateStartupMessage(Dart_Port port, Dart_Handle name) {
+bool VmService::SendIsolateStartupMessage() {
   if (!IsRunning()) {
     return false;
   }
-  Dart_Isolate isolate = Dart_CurrentIsolate();
+  Isolate* isolate = Isolate::Current();
   ASSERT(isolate != NULL);
-  ASSERT(Dart_GetMainPortId() == port);
+  HANDLESCOPE(isolate);
+  Dart_Handle name = Api::NewHandle(isolate, String::New(isolate->name()));
+  ASSERT(!Dart_IsError(name));
   Dart_Handle list =
-      MakeServiceControlMessage(port, VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID);
+      MakeServiceControlMessage(Dart_GetMainPortId(),
+                                VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID,
+                                name);
   ASSERT(!Dart_IsError(list));
-  Dart_Handle result = Dart_ListSetAt(list, 2, name);
-  ASSERT(!Dart_IsError(result));
   return Dart_Post(port_, list);
 }
 
 
-bool VmService::SendIsolateShutdownMessage(Dart_Port port) {
+bool VmService::SendIsolateShutdownMessage() {
   if (!IsRunning()) {
     return false;
   }
-  Dart_Isolate isolate = Dart_CurrentIsolate();
+  Isolate* isolate = Isolate::Current();
   ASSERT(isolate != NULL);
-  ASSERT(Dart_GetMainPortId() == port);
+  HANDLESCOPE(isolate);
   Dart_Handle list =
-      MakeServiceControlMessage(port, VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID);
+      MakeServiceControlMessage(Dart_GetMainPortId(),
+                                VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID,
+                                Dart_Null());
   ASSERT(!Dart_IsError(list));
   return Dart_Post(port_, list);
 }
@@ -441,7 +474,7 @@
 void VmService::VmServiceShutdownCallback(void* callback_data) {
   ASSERT(Dart_CurrentIsolate() != NULL);
   Dart_EnterScope();
-  VmService::SendIsolateShutdownMessage(Dart_GetMainPortId());
+  VmService::SendIsolateShutdownMessage();
   Dart_ExitScope();
 }
 
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 6a64560..0a19ebe 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -23,8 +23,8 @@
 
   static bool IsRunning();
 
-  static bool SendIsolateStartupMessage(Dart_Port port, Dart_Handle name);
-  static bool SendIsolateShutdownMessage(Dart_Port port);
+  static bool SendIsolateStartupMessage();
+  static bool SendIsolateShutdownMessage();
 
   static void VmServiceShutdownCallback(void* callback_data);
 
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_debugger_api.h
index 12433b9..0c9c404 100755
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_debugger_api.h
@@ -600,6 +600,15 @@
 
 
 /**
+ * Returns in \library_id the library id of the given \library.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
+                                       intptr_t* library_id);
+
+
+/**
  * Returns an array containing all variable names and values of
  * the given library \library_id.
  *
diff --git a/runtime/include/dart_mirrors_api.h b/runtime/include/dart_mirrors_api.h
index be50e49..3a4c9ce 100644
--- a/runtime/include/dart_mirrors_api.h
+++ b/runtime/include/dart_mirrors_api.h
@@ -122,14 +122,6 @@
 DART_EXPORT Dart_Handle Dart_LibraryName(Dart_Handle library);
 
 /**
- * Returns in \library_id the library id of the given \library.
- *
- * \return A valid handle if no error occurs during the operation.
- */
-DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
-                                       intptr_t* library_id);
-
-/**
  * Returns a list of the names of all classes and interfaces declared
  * in a library.
  *
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index cdfc5df..ffadba8 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -39,6 +39,7 @@
   Dart_CObject_kArray,
   Dart_CObject_kTypedData,
   Dart_CObject_kExternalTypedData,
+  Dart_CObject_kSendPort,
   Dart_CObject_kUnsupported,
   Dart_CObject_kNumberOfTypes
 } Dart_CObject_Type;
@@ -52,6 +53,7 @@
     double as_double;
     char* as_string;
     char* as_bigint;
+    Dart_Port as_send_port;
     struct {
       intptr_t length;
       struct _Dart_CObject** values;
@@ -101,8 +103,7 @@
  */
 
 typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
-Dart_Port reply_port_id,
-Dart_CObject* message);
+                                          Dart_CObject* message);
 
 /**
  * Creates a new native port.  When messages are received on this
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 8e4ecbe..4545715 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -110,6 +110,11 @@
   final String _msg;
 }
 
+patch class CyclicInitializationError {
+  static _throwNew(String variableName) {
+    throw new CyclicInitializationError(variableName);
+  }
+}
 
 patch class AbstractClassInstantiationError {
   AbstractClassInstantiationError._create(
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 28ff352..c11ea61 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -1425,11 +1425,9 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 3) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
-  ASSERT(!closure.IsNull() && closure.IsCallable(NULL, NULL));
-  GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1));
-  GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(2));
+DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(1));
 
   const Array& args_descriptor =
       Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
@@ -1530,9 +1528,10 @@
 
   Function& function = Function::Handle();
   bool callable = closure.IsCallable(&function, NULL);
-  ASSERT(callable);
-
-  return CreateMethodMirror(function, Instance::null_instance());
+  if (callable) {
+    return CreateMethodMirror(function, Instance::null_instance());
+  }
+  return Instance::null();
 }
 
 
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 5bb24ac..cdcf3e3 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -401,7 +401,7 @@
 
   InstanceMirror apply(List<Object> positionalArguments,
                        [Map<Symbol, Object> namedArguments]) {
-    // TODO(iposva): When closures get an ordinary call method, this can be
+    // TODO(12602): When closures get an ordinary call method, this can be
     // replaced with
     //   return this.invoke(#call, positionalArguments, namedArguments);
     // and the native ClosureMirror_apply can be removed.
@@ -423,7 +423,7 @@
 
     // It is tempting to implement this in terms of Function.apply, but then
     // lazy compilation errors would be fatal.
-    return reflect(_apply(_reflectee, arguments, names));
+    return reflect(_apply(arguments, names));
   }
 
   Future<InstanceMirror> applyAsync(List positionalArguments,
@@ -448,7 +448,7 @@
 
   String toString() => "ClosureMirror on '${Error.safeToString(_reflectee)}'";
 
-  static _apply(reflectee, arguments, argumentNames)
+  static _apply(arguments, argumentNames)
       native 'ClosureMirror_apply';
 
   static _computeFunction(reflectee)
diff --git a/runtime/lib/mirrors_patch.dart b/runtime/lib/mirrors_patch.dart
index 364b0ab..4af60c6 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/runtime/lib/mirrors_patch.dart
@@ -17,7 +17,7 @@
  * Creates a [MirrorSystem] for the isolate which is listening on
  * the [SendPort].
  */
-patch Future<MirrorSystem> mirrorSystemOf(SendPort port) {
+Future<MirrorSystem> mirrorSystemOf(SendPort port) {
   return _Mirrors.mirrorSystemOf(port);
 }
 
diff --git a/runtime/lib/platform_patch.dart b/runtime/lib/platform_patch.dart
deleted file mode 100644
index 80dfef9..0000000
--- a/runtime/lib/platform_patch.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2013, 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.
-
-patch int get numberOfProcessors => _platform.numberOfProcessors;
-
-patch String get pathSeparator => _platform.pathSeparator;
-
-patch String get operatingSystem => _platform.operatingSystem;
-
-patch String get localHostname => _platform.localHostname;
-
-patch String get version => _platform.version;
-
-patch Map<String, String> get environment => _platform.environment;
-
-patch String get executable => _platform.executable;
-
-patch Uri get script => _platform.script;
-
-patch List<String> get executableArguments => _platform.executableArguments;
-
-patch String get packageRoot => _platform.packageRoot;
-
-class _Platform {
-  int get numberOfProcessors;
-  String get pathSeparator;
-  String get operatingSystem;
-  String get localHostname;
-  String get version;
-  Map get environment;
-  Uri get script;
-  String get executable;
-  List<String>  get executableArguments;
-  String get packageRoot;
-}
-
-// A non-default _Platform, with real values, is stored here by the embedder.
-_Platform _platform = new _DefaultPlatform();
-
-class _DefaultPlatform implements _Platform {
-  int get numberOfProcessors {
-    return null;
-  }
-
-  String get pathSeparator {
-    return null;
-  }
-
-  String get operatingSystem {
-    return null;
-  }
-
-  String get localHostname {
-    return null;
-  }
-
-  String get version {
-    return null;
-  }
-
-  Map get environment {
-    return null;
-  }
-
-  Uri get script {
-    return null;
-  }
-
-  String get executable {
-    return null;
-  }
-
-  List<String>  get executableArguments {
-    return new List<String>(0);
-  }
-
-  String get packageRoot {
-    return null;
-  }
-}
diff --git a/runtime/lib/platform_sources.gypi b/runtime/lib/platform_sources.gypi
deleted file mode 100644
index dd1b34f..0000000
--- a/runtime/lib/platform_sources.gypi
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2013, 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.
-
-# This file contains all sources for the dart:platform library.
-{
-  'sources': [
-    'platform_patch.dart',
-  ],
-}
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index bab0aba..6b45135 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -210,7 +210,7 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Strings_concatAll, 3) {
+DEFINE_NATIVE_ENTRY(String_concatRange, 3) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, argument, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, end, arguments->NativeArgAt(2));
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
index 72ec095..5d8b9b4 100644
--- a/runtime/lib/string_buffer_patch.dart
+++ b/runtime/lib/string_buffer_patch.dart
@@ -102,7 +102,7 @@
     _consumeBuffer();
     return (_partsCodeUnits == 0) ?
         "" :
-        _StringBase._concatAllNative(_parts, 0, _parts.length);
+        _StringBase._concatRange(_parts, 0, _parts.length);
   }
 
   /** Ensures that the buffer has enough capacity to add n code units. */
@@ -153,7 +153,7 @@
    */
   void _compact() {
     if (_partsCodeUnitsSinceCompaction < _PARTS_TO_COMPACT_SIZE_LIMIT) {
-      String compacted = _StringBase._concatAllNative(
+      String compacted = _StringBase._concatRange(
           _parts,
           _partsCompactionIndex,                     // Start
           _partsCompactionIndex + _PARTS_TO_COMPACT  // End
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index f19b305..93726b2 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -84,9 +84,8 @@
     if (identical(this, other)) {
       return true;
     }
-    if ((other is !String) ||
+    if ((other is! String) ||
         (this.length != other.length)) {
-      // TODO(5413632): Compare hash codes when both are present.
       return false;
     }
     final len = this.length;
@@ -120,7 +119,7 @@
 
   bool _substringMatches(int start, String other) {
     if (other.isEmpty) return true;
-    final int len = other.length;
+    final len = other.length;
     if ((start < 0) || (start + len > this.length)) {
       return false;
     }
@@ -265,7 +264,7 @@
   }
 
   String trim() {
-    final int len = this.length;
+    final len = this.length;
     int first = 0;
     for (; first < len; first++) {
       if (!_isWhitespace(this.codeUnitAt(first))) {
@@ -405,7 +404,7 @@
    * into a result string.
    */
   static String _interpolate(List<String> values) {
-    final int numValues = values.length;
+    final numValues = values.length;
     _List stringList = new List<String>(numValues);
     bool isOneByteString = true;
     int totalLength = 0;
@@ -424,7 +423,7 @@
     if (isOneByteString) {
       return _OneByteString._concatAll(stringList, totalLength);
     }
-    return _concatAllNative(stringList, 0, stringList.length);
+    return _concatRangeNative(stringList, 0, stringList.length);
   }
 
   Iterable<Match> allMatches(String str) {
@@ -509,10 +508,31 @@
 
   String toLowerCase() native "String_toLowerCase";
 
+  // Concatenate ['start', 'end'[ elements of 'strings'. 'strings' must contain
+  // String elements. Optimized for OneByteStrings.
+  static String _concatRange(List<String> strings, int start, int end) {
+    if ((end - start) == 1) {
+      return strings[start];
+    }
+    final numValues = strings.length;
+    if ((start == 0) && (end == numValues)) {
+      int totalLength = 0;
+      for (int i = 0; i < numValues; i++) {
+        String s = strings[i];
+        if (s._cid != _OneByteString._classId) {
+          return _concatRangeNative(strings, start, end);
+        }
+        totalLength += s.length;
+      }
+      return _OneByteString._concatAll(strings, totalLength);
+    }
+    return _concatRangeNative(strings, start, end);
+  }
+
   // Call this method if not all list elements are known to be OneByteString(s).
   // 'strings' must be an _List or _GrowableList.
-  static String _concatAllNative(List<String> strings, int start, int end)
-      native "Strings_concatAll";
+  static String _concatRangeNative(List<String> strings, int start, int end)
+      native "String_concatRange";
 }
 
 
@@ -548,11 +568,11 @@
   }
 
   // All element of 'strings' must be OneByteStrings.
-  static _concatAll(_List<String> strings, int totalLength) {
+  static _concatAll(List<String> strings, int totalLength) {
     // TODO(srdjan): Improve code below and raise or eliminate the limit.
     if (totalLength > 128) {
       // Native is quicker.
-      return _StringBase._concatAllNative(strings, 0, strings.length);
+      return _StringBase._concatRangeNative(strings, 0, strings.length);
     }
     var res = _OneByteString._allocate(totalLength);
     final stringsLength = strings.length;
@@ -567,6 +587,24 @@
     return res;
   }
 
+  int indexOf(Pattern pattern, [int start = 0]) {
+    final len = this.length;
+    // Specialize for single character pattern.
+    // TODO(srdjan): Implement for other string classes.
+    if ((pattern._cid == _OneByteString._classId) &&
+        (pattern.length == 1) &&
+        (start >= 0) && (start < len)) {
+      final patternCu0 = pattern.codeUnitAt(0);
+      for (int i = start; i < len; i++) {
+        if (this.codeUnitAt(i) == patternCu0) {
+          return i;
+        }
+      }
+      return -1;
+    }
+    return super.indexOf(pattern, start);
+  }
+
   // Allocates a string of given length, expecting its content to be
   // set using _setAt.
   static _OneByteString _allocate(int length) native "OneByteString_allocate";
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index be2665c..704bfec 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -68,3 +68,10 @@
 dart/isolate_mirror_remote_test: Fail # Issue 13921
 dart/isolate_unhandled_exception_test: Fail # Issue 13921
 dart/mirrored_compilation_error_test: Skip # Can't pass needed VM flag
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+dart/optimized_stacktrace_test: StaticWarning
+
+dart/isolate_mirror_local_test: Fail, OK # API being removed.
+dart/isolate_mirror_remote_test: Fail, OK # API being removed.
+dart/mirrored_compilation_error_test: CompileTimeError, OK # This test intentionally includes invalid method bodies.
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 0ee04fc..9fca435 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -62,10 +62,6 @@
                mirrors,
                Bootstrap::mirrors_source_paths_,
                Bootstrap::mirrors_patch_paths_),
-  INIT_LIBRARY(ObjectStore::kPlatform,
-               platform,
-               Bootstrap::platform_source_paths_,
-               Bootstrap::platform_patch_paths_),
   INIT_LIBRARY(ObjectStore::kTypedData,
                typed_data,
                Bootstrap::typed_data_source_paths_,
diff --git a/runtime/vm/bootstrap.h b/runtime/vm/bootstrap.h
index dd525d8..6ebc812 100644
--- a/runtime/vm/bootstrap.h
+++ b/runtime/vm/bootstrap.h
@@ -29,7 +29,6 @@
   static const char* json_source_paths_[];
   static const char* math_source_paths_[];
   static const char* mirrors_source_paths_[];
-  static const char* platform_source_paths_[];
   static const char* typed_data_source_paths_[];
   static const char* utf_source_paths_[];
 
@@ -42,7 +41,6 @@
   static const char* isolate_patch_paths_[];
   static const char* math_patch_paths_[];
   static const char* mirrors_patch_paths_[];
-  static const char* platform_patch_paths_[];
   static const char* typed_data_patch_paths_[];
 };
 
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index 70c27e5..a072563 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -76,10 +76,6 @@
   ASSERT(!library.IsNull());
   library.set_native_entry_resolver(resolver);
 
-  library = Library::PlatformLibrary();
-  ASSERT(!library.IsNull());
-  library.set_native_entry_resolver(resolver);
-
   library = Library::TypedDataLibrary();
   ASSERT(!library.IsNull());
   library.set_native_entry_resolver(resolver);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 8aed894..1c3ea31 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -101,7 +101,7 @@
   V(String_concat, 2)                                                          \
   V(String_toLowerCase, 1)                                                     \
   V(String_toUpperCase, 1)                                                     \
-  V(Strings_concatAll, 3)                                                      \
+  V(String_concatRange, 3)                                                     \
   V(Math_sqrt, 1)                                                              \
   V(Math_sin, 1)                                                               \
   V(Math_cos, 1)                                                               \
@@ -264,7 +264,7 @@
   V(InstanceMirror_computeType, 1)                                             \
   V(ClosureMirror_find_in_context, 2)                                          \
   V(ClosureMirror_function, 1)                                                 \
-  V(ClosureMirror_apply, 3)                                                    \
+  V(ClosureMirror_apply, 2)                                                    \
   V(ClassMirror_library, 1)                                                    \
   V(ClassMirror_supertype, 1)                                                  \
   V(ClassMirror_supertype_instantiated, 1)                                     \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index a141dc3..789489f 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -584,12 +584,12 @@
       // Such legal self-references occur with F-bounded quantification.
       // Example 1: class Derived extends Base<Derived>.
       // The type 'Derived' forms a cycle by pointing to itself via its
-      // flattened type argument vector: Derived[Base[Derived[Base[...]]]]
-      // We break the cycle as follows: Derived[Base[Derived[dynamic]]]
+      // flattened type argument vector: Derived[Derived[...]]
+      // We break the cycle as follows: Derived[Derived[dynamic]]
       // Example 2: class Derived extends Base<Middle<Derived>> results in
-      // Derived[Base[Middle[Derived[dynamic]]]]
+      // Derived[Middle[Derived[dynamic]]]
       // Example 3: class Derived<T> extends Base<Derived<T>> results in
-      // Derived[Base[Derived[dynamic]], T].
+      // Derived[Derived[dynamic], T].
       ASSERT(super_type_args.IsNull());  // Same as a vector of dynamic.
     } else {
       super_type ^= FinalizeType(cls, super_type, finalization);
@@ -2127,7 +2127,7 @@
 
 
 // Helper function called by IsAliasCycleFree.
-bool ClassFinalizer::IsParameterTypeCycleFree(
+bool ClassFinalizer::IsTypeCycleFree(
     const Class& cls,
     const AbstractType& type,
     GrowableArray<intptr_t>* visited) {
@@ -2146,7 +2146,7 @@
       AbstractType& type_arg = AbstractType::Handle();
       for (intptr_t i = 0; i < type_args.Length(); i++) {
         type_arg = type_args.TypeAt(i);
-        if (!IsParameterTypeCycleFree(cls, type_arg, visited)) {
+        if (!IsTypeCycleFree(cls, type_arg, visited)) {
           return false;
         }
       }
@@ -2170,19 +2170,35 @@
     }
   }
 
-  // Visit the result type and parameter types of this signature type.
+  // Visit the bounds, result type, and parameter types of this signature type.
   visited->Add(cls.id());
+  AbstractType& type = AbstractType::Handle();
+
+  // Check the bounds of this signature type.
+  const intptr_t num_type_params = cls.NumTypeParameters();
+  TypeParameter& type_param = TypeParameter::Handle();
+  const AbstractTypeArguments& type_params =
+      AbstractTypeArguments::Handle(cls.type_parameters());
+  ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
+         (type_params.Length() == num_type_params));
+  for (intptr_t i = 0; i < num_type_params; i++) {
+    type_param ^= type_params.TypeAt(i);
+    type = type_param.bound();
+    if (!IsTypeCycleFree(cls, type, visited)) {
+      return false;
+    }
+  }
+  // Check the result type of the function of this signature type.
   const Function& function = Function::Handle(cls.signature_function());
-  // Check class of result type.
-  AbstractType& type = AbstractType::Handle(function.result_type());
-  if (!IsParameterTypeCycleFree(cls, type, visited)) {
+  type = function.result_type();
+  if (!IsTypeCycleFree(cls, type, visited)) {
     return false;
   }
-  // Check classes of formal parameter types.
+  // Check the formal parameter types of the function of this signature type.
   const intptr_t num_parameters = function.NumParameters();
   for (intptr_t i = 0; i < num_parameters; i++) {
     type = function.ParameterTypeAt(i);
-    if (!IsParameterTypeCycleFree(cls, type, visited)) {
+    if (!IsTypeCycleFree(cls, type, visited)) {
       return false;
     }
   }
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index 793674b..197e1d6 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -98,9 +98,9 @@
 
  private:
   static bool IsSuperCycleFree(const Class& cls);
-  static bool IsParameterTypeCycleFree(const Class& cls,
-                                       const AbstractType& type,
-                                       GrowableArray<intptr_t>* visited);
+  static bool IsTypeCycleFree(const Class& cls,
+                              const AbstractType& type,
+                              GrowableArray<intptr_t>* visited);
   static bool IsAliasCycleFree(const Class& cls,
                                GrowableArray<intptr_t>* visited);
   static bool IsMixinCycleFree(const Class& cls,
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index a5f45bf..d4893a4 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1383,6 +1383,7 @@
 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) {
   const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
   ASSERT(!function.IsNull());
+  ASSERT(function.HasCode());
 
   if (CanOptimizeFunction(function, isolate)) {
     const Error& error =
@@ -1441,6 +1442,7 @@
         target_code.EntryPoint());
   }
   arguments.SetReturn(target_code);
+  ASSERT(target_function.HasCode());
 }
 
 
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 63ea3a1..fefdd51 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -5775,34 +5775,35 @@
 
 
 void NewNativePort_send123(Dart_Port dest_port_id,
-                           Dart_Port reply_port_id,
                            Dart_CObject *message) {
-  // Gets a null message.
+  // Gets a send port message.
   EXPECT_NOTNULL(message);
-  EXPECT_EQ(Dart_CObject_kNull, message->type);
+  EXPECT_EQ(Dart_CObject_kArray, message->type);
+  EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
 
   // Post integer value.
   Dart_CObject* response =
       reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
   response->type = Dart_CObject_kInt32;
   response->value.as_int32 = 123;
-  Dart_PostCObject(reply_port_id, response);
+  Dart_PostCObject(
+      message->value.as_array.values[0]->value.as_send_port, response);
 }
 
 
 void NewNativePort_send321(Dart_Port dest_port_id,
-                           Dart_Port reply_port_id,
                            Dart_CObject* message) {
   // Gets a null message.
   EXPECT_NOTNULL(message);
-  EXPECT_EQ(Dart_CObject_kNull, message->type);
+  EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
 
   // Post integer value.
   Dart_CObject* response =
       reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
   response->type = Dart_CObject_kInt32;
   response->value.as_int32 = 321;
-  Dart_PostCObject(reply_port_id, response);
+  Dart_PostCObject(
+      message->value.as_array.values[0]->value.as_send_port, response);
 }
 
 
@@ -5820,7 +5821,8 @@
       "import 'dart:isolate';\n"
       "void callPort(SendPort port) {\n"
       "  var receivePort = new RawReceivePort();\n"
-      "  port.send(null, receivePort.sendPort);\n"
+      "  var replyPort = receivePort.sendPort;\n"
+      "  port.send([replyPort]);\n"
       "  receivePort.handler = (message) {\n"
       "    receivePort.close();\n"
       "    throw new Exception(message);\n"
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index c8484f9..0208c40 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -221,7 +221,8 @@
 
 
 static Dart_TypedData_Type GetTypedDataTypeFromView(
-    Dart_CObject_Internal* object) {
+    Dart_CObject_Internal* object,
+    char* class_name) {
   struct {
     const char* name;
     Dart_TypedData_Type type;
@@ -241,13 +242,6 @@
     { NULL, Dart_TypedData_kInvalid },
   };
 
-  char* library_url =
-      object->cls->internal.as_class.library_url->value.as_string;
-  char* class_name =
-      object->cls->internal.as_class.class_name->value.as_string;
-  if (strcmp("dart:typed_data", library_url) != 0) {
-    return Dart_TypedData_kInvalid;
-  }
   int i = 0;
   while (view_class_names[i].name != NULL) {
     if (strncmp(view_class_names[i].name,
@@ -286,31 +280,54 @@
            static_cast<Dart_CObject_Type>(
                Dart_CObject_Internal::kUninitialized));
 
+    char* library_uri =
+        object->cls->internal.as_class.library_url->value.as_string;
+    char* class_name =
+        object->cls->internal.as_class.class_name->value.as_string;
+
     // Handle typed data views.
-    Dart_TypedData_Type type = GetTypedDataTypeFromView(object);
-    if (type != Dart_TypedData_kInvalid) {
-      object->type =
-          static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);
+    if (strcmp("dart:typed_data", library_uri) == 0) {
+      Dart_TypedData_Type type = GetTypedDataTypeFromView(object, class_name);
+      if (type != Dart_TypedData_kInvalid) {
+        object->type =
+            static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);
+        ReadObjectImpl();  // Skip type arguments.
+        object->internal.as_view.buffer = ReadObjectImpl();
+        object->internal.as_view.offset_in_bytes = ReadSmiValue();
+        object->internal.as_view.length = ReadSmiValue();
+        ReadObjectImpl();  // Skip last field.
+
+        // The buffer is fully read now as typed data objects are
+        // serialized in-line.
+        Dart_CObject* buffer = object->internal.as_view.buffer;
+        ASSERT(buffer->type == Dart_CObject_kTypedData);
+
+        // Now turn the view into a byte array.
+        object->type = Dart_CObject_kTypedData;
+        object->value.as_typed_data.type = type;
+        object->value.as_typed_data.length =
+            object->internal.as_view.length *
+            GetTypedDataSizeInBytes(type);
+        object->value.as_typed_data.values =
+            buffer->value.as_typed_data.values +
+            object->internal.as_view.offset_in_bytes;
+      } else {
+        // TODO(sgjesse): Handle other instances. Currently this will
+        // skew the reading as the fields of the instance is not read.
+      }
+    } else if (strcmp("dart:isolate", library_uri) == 0 &&
+               strncmp("_SendPortImpl@", class_name, 14) == 0) {
       ReadObjectImpl();  // Skip type arguments.
-      object->internal.as_view.buffer = ReadObjectImpl();
-      object->internal.as_view.offset_in_bytes = ReadSmiValue();
-      object->internal.as_view.length = ReadSmiValue();
+      // Read the port id.
+      Dart_CObject* port = ReadObjectImpl();
+      if (port->type == Dart_CObject_kInt32) {
+        object->type = Dart_CObject_kSendPort;
+        object->value.as_send_port = port->value.as_int32;
+      } else if (port->type == Dart_CObject_kInt64) {
+        object->type = Dart_CObject_kSendPort;
+        object->value.as_send_port = port->value.as_int64;
+      }
       ReadObjectImpl();  // Skip last field.
-
-      // The buffer is fully read now as typed data objects are
-      // serialized in-line.
-      Dart_CObject* buffer = object->internal.as_view.buffer;
-      ASSERT(buffer->type == Dart_CObject_kTypedData);
-
-      // Now turn the view into a byte array.
-      object->type = Dart_CObject_kTypedData;
-      object->value.as_typed_data.type = type;
-      object->value.as_typed_data.length =
-          object->internal.as_view.length *
-          GetTypedDataSizeInBytes(type);
-      object->value.as_typed_data.values =
-          buffer->value.as_typed_data.values +
-          object->internal.as_view.offset_in_bytes;
     } else {
       // TODO(sgjesse): Handle other instances. Currently this will
       // skew the reading as the fields of the instance is not read.
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 3ffff4a..c20bf67 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -796,6 +796,22 @@
 }
 
 
+DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
+                                       intptr_t* library_id) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+  if (lib.IsNull()) {
+    RETURN_TYPE_ERROR(isolate, library, Library);
+  }
+  if (library_id == NULL) {
+    RETURN_NULL_ERROR(library_id);
+  }
+  *library_id = lib.index();
+  return Api::Success();
+}
+
+
 DART_EXPORT Dart_Handle Dart_GetLibraryImports(intptr_t library_id) {
   Isolate* isolate = Isolate::Current();
   ASSERT(isolate != NULL);
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 474b313..c5266d1 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -1168,7 +1168,11 @@
   // TODO(vegorov): verify after deoptimization targets as well.
 #ifdef DEBUG
   const Code& code = Code::Handle(function.unoptimized_code());
-  ASSERT(Isolate::IsDeoptAfter(deopt_id) ||
+  // The inlined function's code pointer may be null if there is a GC during
+  // compilation.
+  // TODO(zra): See if we can avoid this check by ensuring that code is not
+  //            removed during inlining.
+  ASSERT(code.IsNull() || Isolate::IsDeoptAfter(deopt_id) ||
       (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0));
 #endif
   const intptr_t object_table_index = FindOrAddObjectInTable(function);
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index eac4aa7..bf34043 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -1164,13 +1164,23 @@
   FlowGraphOptimizer optimizer(owner_->caller_graph());
   TargetEntryInstr* entry;
   Definition* last;
+  // Replace the receiver argument with a redefinition to prevent code from
+  // the inlined body from being hoisted above the inlined entry.
+  GrowableArray<Definition*> arguments(call_->ArgumentCount());
+  Definition* receiver = call_->ArgumentAt(0);
+    RedefinitionInstr* redefinition =
+        new RedefinitionInstr(new Value(receiver));
+    redefinition->set_ssa_temp_index(
+        owner_->caller_graph()->alloc_ssa_temp_index());
   if (optimizer.TryInlineRecognizedMethod(receiver_cid,
                                           target,
                                           call_,
+                                          redefinition,
                                           call_->instance_call()->token_pos(),
                                           *call_->instance_call()->ic_data(),
                                           &entry, &last)) {
     // Create a graph fragment.
+    redefinition->InsertAfter(entry);
     InlineExitCollector* exit_collector =
         new InlineExitCollector(owner_->caller_graph(), call_);
 
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 87e4c88..da6de7b 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -832,6 +832,7 @@
   if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
                                  target,
                                  call,
+                                 call->ArgumentAt(0),
                                  call->token_pos(),
                                  *call->ic_data(),
                                  &entry, &last)) {
@@ -865,6 +866,7 @@
     MethodRecognizer::Kind kind,
     const Function& target,
     Instruction* call,
+    Definition* receiver,
     intptr_t token_pos,
     const ICData* ic_data,
     const ICData& value_check,
@@ -873,7 +875,7 @@
   intptr_t array_cid = MethodKindToCid(kind);
   ASSERT(array_cid != kIllegalCid);
 
-  Definition* array = call->ArgumentAt(0);
+  Definition* array = receiver;
   Definition* index = call->ArgumentAt(1);
   Definition* stored_value = call->ArgumentAt(2);
 
@@ -999,6 +1001,7 @@
 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
                                                    const Function& target,
                                                    Instruction* call,
+                                                   Definition* receiver,
                                                    intptr_t token_pos,
                                                    const ICData& ic_data,
                                                    TargetEntryInstr** entry,
@@ -1019,14 +1022,14 @@
     case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
     case MethodRecognizer::kInt16ArrayGetIndexed:
     case MethodRecognizer::kUint16ArrayGetIndexed:
-      return InlineGetIndexed(kind, call, ic_data, entry, last);
+      return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
     case MethodRecognizer::kFloat32x4ArrayGetIndexed:
       if (!ShouldInlineSimd()) return false;
-      return InlineGetIndexed(kind, call, ic_data, entry, last);
+      return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
     case MethodRecognizer::kInt32ArrayGetIndexed:
     case MethodRecognizer::kUint32ArrayGetIndexed:
       if (!CanUnboxInt32()) return false;
-      return InlineGetIndexed(kind, call, ic_data, entry, last);
+      return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
 
     // Recognized []= operators.
     case MethodRecognizer::kObjectArraySetIndexed:
@@ -1034,7 +1037,7 @@
       if (ArgIsAlways(kSmiCid, ic_data, 2)) {
         value_check = ic_data.AsUnaryClassChecksForArgNr(2);
       }
-      return InlineSetIndexed(kind, target, call, token_pos,
+      return InlineSetIndexed(kind, target, call, receiver, token_pos,
                               &ic_data, value_check, entry, last);
     case MethodRecognizer::kInt8ArraySetIndexed:
     case MethodRecognizer::kUint8ArraySetIndexed:
@@ -1045,7 +1048,7 @@
     case MethodRecognizer::kUint16ArraySetIndexed:
       if (!ArgIsAlways(kSmiCid, ic_data, 2)) return false;
       value_check = ic_data.AsUnaryClassChecksForArgNr(2);
-      return InlineSetIndexed(kind, target, call, token_pos,
+      return InlineSetIndexed(kind, target, call, receiver, token_pos,
                               &ic_data, value_check, entry, last);
     case MethodRecognizer::kInt32ArraySetIndexed:
     case MethodRecognizer::kUint32ArraySetIndexed:
@@ -1060,59 +1063,59 @@
       } else if (!HasOnlyOneSmi(value_check)) {
         return false;
       }
-      return InlineSetIndexed(kind, target, call, token_pos,
+      return InlineSetIndexed(kind, target, call, receiver, token_pos,
                               &ic_data, value_check, entry, last);
     case MethodRecognizer::kFloat32ArraySetIndexed:
     case MethodRecognizer::kFloat64ArraySetIndexed:
       // Check that value is always double.
       if (!ArgIsAlways(kDoubleCid, ic_data, 2)) return false;
       value_check = ic_data.AsUnaryClassChecksForArgNr(2);
-      return InlineSetIndexed(kind, target, call, token_pos,
+      return InlineSetIndexed(kind, target, call, receiver, token_pos,
                               &ic_data, value_check, entry, last);
     case MethodRecognizer::kFloat32x4ArraySetIndexed:
       if (!ShouldInlineSimd()) return false;
       // Check that value is always a Float32x4.
       if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) return false;
       value_check = ic_data.AsUnaryClassChecksForArgNr(2);
-      return InlineSetIndexed(kind, target, call, token_pos,
+      return InlineSetIndexed(kind, target, call, receiver, token_pos,
                               &ic_data, value_check, entry, last);
     case MethodRecognizer::kByteArrayBaseGetInt8:
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataInt8ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetUint8:
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataUint8ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetInt16:
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataInt16ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetUint16:
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataUint16ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetInt32:
       if (!CanUnboxInt32()) return false;
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataInt32ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetUint32:
       if (!CanUnboxInt32()) return false;
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataUint32ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetFloat32:
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataFloat32ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetFloat64:
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataFloat64ArrayCid,
                                      ic_data, entry, last);
     case MethodRecognizer::kByteArrayBaseGetFloat32x4:
       if (!ShouldInlineSimd()) return false;
-      return InlineByteArrayViewLoad(call, receiver_cid,
+      return InlineByteArrayViewLoad(call, receiver, receiver_cid,
                                      kTypedDataFloat32x4ArrayCid,
                                      ic_data, entry, last);
     default:
@@ -1186,13 +1189,14 @@
 
 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind,
                                           Instruction* call,
+                                          Definition* receiver,
                                           const ICData& ic_data,
                                           TargetEntryInstr** entry,
                                           Definition** last) {
   intptr_t array_cid = MethodKindToCid(kind);
   ASSERT(array_cid != kIllegalCid);
 
-  Definition* array = call->ArgumentAt(0);
+  Definition* array = receiver;
   Definition* index = call->ArgumentAt(1);
   *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
                                 call->GetBlock()->try_index());
@@ -1242,6 +1246,7 @@
   if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
                                  target,
                                  call,
+                                 call->ArgumentAt(0),
                                  call->token_pos(),
                                  *call->ic_data(),
                                  &entry, &last)) {
@@ -2483,13 +2488,14 @@
 
 
 bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call,
+                                                 Definition* receiver,
                                                  intptr_t array_cid,
                                                  intptr_t view_cid,
                                                  const ICData& ic_data,
                                                  TargetEntryInstr** entry,
                                                  Definition** last) {
   ASSERT(array_cid != kIllegalCid);
-  Definition* array = call->ArgumentAt(0);
+  Definition* array = receiver;
   Definition* index = call->ArgumentAt(1);
   *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
                                 call->GetBlock()->try_index());
@@ -2625,6 +2631,7 @@
   if (!TryInlineRecognizedMethod(receiver_cid,
                                  target,
                                  call,
+                                 call->ArgumentAt(0),
                                  call->token_pos(),
                                  *call->ic_data(),
                                  &entry, &last)) {
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 17fd3cf..2940c6b 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -47,6 +47,7 @@
   bool TryInlineRecognizedMethod(intptr_t receiver_cid,
                                  const Function& target,
                                  Instruction* call,
+                                 Definition* receiver,
                                  intptr_t token_pos,
                                  const ICData& ic_data,
                                  TargetEntryInstr** entry,
@@ -77,6 +78,7 @@
   bool InlineSetIndexed(MethodRecognizer::Kind kind,
                         const Function& target,
                         Instruction* call,
+                        Definition* receiver,
                         intptr_t token_pos,
                         const ICData* ic_data,
                         const ICData& value_check,
@@ -85,6 +87,7 @@
   bool TryReplaceWithLoadIndexed(InstanceCallInstr* call);
   bool InlineGetIndexed(MethodRecognizer::Kind kind,
                         Instruction* call,
+                        Definition* receiver,
                         const ICData& ic_data,
                         TargetEntryInstr** entry,
                         Definition** last);
@@ -120,6 +123,7 @@
                                           intptr_t cid);
 
   bool InlineByteArrayViewLoad(Instruction* call,
+                               Definition* receiver,
                                intptr_t array_cid,
                                intptr_t view_cid,
                                const ICData& ic_data,
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index deebded..0c6c274 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -70,7 +70,7 @@
   V(_StringBase, get:isEmpty, StringBaseIsEmpty, 879849436)                    \
   V(_StringBase, codeUnitAt, StringBaseCodeUnitAt, 1958436584)                 \
   V(_StringBase, [], StringBaseCharAt, 990046076)                              \
-  V(_StringBase, _interpolate, StringBaseInterpolate, 908021574)               \
+  V(_StringBase, _interpolate, StringBaseInterpolate, 1824308855)              \
   V(_OneByteString, _setAt, OneByteStringSetAt, 308408714)                     \
   V(_IntegerImplementation, toDouble, IntegerToDouble, 2011998508)             \
   V(_IntegerImplementation, _leftShiftWithMask32, IntegerLeftShiftWithMask32,  \
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index af7c096..1ab2323 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -323,20 +323,6 @@
   return Api::NewHandle(isolate, name.raw());
 }
 
-DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
-                                       intptr_t* library_id) {
-  Isolate* isolate = Isolate::Current();
-  DARTSCOPE(isolate);
-  const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
-  if (lib.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, library, Library);
-  }
-  if (library_id != NULL) {
-    *library_id = lib.index();
-  }
-  return Api::Success();
-}
-
 DART_EXPORT Dart_Handle Dart_LibraryGetClassNames(Dart_Handle library) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
diff --git a/runtime/vm/native_message_handler.cc b/runtime/vm/native_message_handler.cc
index 83bcf5e..7b3d9b9 100644
--- a/runtime/vm/native_message_handler.cc
+++ b/runtime/vm/native_message_handler.cc
@@ -51,7 +51,7 @@
   ApiNativeScope scope;
   ApiMessageReader reader(message->data(), message->len(), zone_allocator);
   Dart_CObject* object = reader.ReadMessage();
-  (*func())(message->dest_port(), message->reply_port(), object);
+  (*func())(message->dest_port(), object);
   delete message;
   return true;
 }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 314f142..b28e24f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2416,29 +2416,46 @@
 
 void Class::PatchSignatureFunction(const Function& signature_function) const {
   ASSERT(!signature_function.IsNull());
+  set_signature_function(signature_function);
   const Class& owner_class = Class::Handle(signature_function.Owner());
   ASSERT(!owner_class.IsNull());
-  TypeArguments& type_parameters = TypeArguments::Handle();
-  // A signature class extends class Instance and is parameterized in the same
-  // way as the owner class of its non-static signature function.
-  // It is not type parameterized if its signature function is static.
-  // In case of a function type alias, the function owner is the alias class
-  // instead of the enclosing class.
-  if (!signature_function.is_static() &&
-      (owner_class.NumTypeParameters() > 0) &&
-      !signature_function.HasInstantiatedSignature()) {
-    type_parameters = owner_class.type_parameters();
-  }
-  set_signature_function(signature_function);
-  set_type_parameters(type_parameters);
+  // A signature class extends class Instance and is either not parameterized or
+  // parameterized with exactly the same list of type parameters as the owner
+  // class of its function.
+  // In case of a function type alias, the function owner is the alias class,
+  // which is also the signature class. The signature class is therefore
+  // parameterized according to the alias class declaration, even if the
+  // function type is not generic.
+  // Otherwise, if the function is static or if its signature type is
+  // non-generic, i.e. it does not depend on any type parameter of the owner
+  // class, then the signature class is not parameterized, although the owner
+  // class may be.
   if (owner_class.raw() == raw()) {
     // This signature class is an alias, which cannot be the canonical
     // signature class for this signature function.
     ASSERT(!IsCanonicalSignatureClass());
-  } else if (signature_function.signature_class() == Object::null()) {
-    // Make this signature class the canonical signature class.
-    signature_function.set_signature_class(*this);
-    ASSERT(IsCanonicalSignatureClass());
+    // Do not modify the declared type parameters of the alias, even if unused.
+  } else {
+    // Copy the type parameters only for an instance function type that is not
+    // instantiated, i.e. that depends on the type parameters of the owner
+    // class.
+    // TODO(regis): Verify that it is not a problem for the copied type
+    // parameters to refer to the owner class rather than to the signature
+    // class. In other words, uninstantiated function types should only get
+    // instantiated by the owner class as instantiator and never by the
+    // signature class itself.
+    TypeArguments& type_parameters = TypeArguments::Handle();
+    if (!signature_function.is_static() &&
+        (owner_class.NumTypeParameters() > 0) &&
+        !signature_function.HasInstantiatedSignature()) {
+      type_parameters = owner_class.type_parameters();
+    }
+    set_type_parameters(type_parameters);
+    if (signature_function.signature_class() == Object::null()) {
+      // Make this signature class the canonical signature class.
+      signature_function.set_signature_class(*this);
+      ASSERT(IsCanonicalSignatureClass());
+    }
   }
   set_is_prefinalized();
 }
@@ -4051,8 +4068,8 @@
 
 
 void Function::ReattachCode(const Code& code) const {
-  set_unoptimized_code(code);
-  SetCode(code);
+  StorePointer(&raw_ptr()->code_, code.raw());
+  StorePointer(&raw_ptr()->unoptimized_code_, code.raw());
   CodePatcher::RestoreEntry(code);
 }
 
@@ -4510,7 +4527,9 @@
 
 
 bool Function::IsInlineable() const {
-  return InlinableBit::decode(raw_ptr()->kind_tag_) && HasCode();
+  return (InlinableBit::decode(raw_ptr()->kind_tag_) &&
+          HasCode() &&
+          !Isolate::Current()->debugger()->HasBreakpoint(*this));
 }
 
 
@@ -7926,10 +7945,6 @@
   return Isolate::Current()->object_store()->native_wrappers_library();
 }
 
-RawLibrary* Library::PlatformLibrary() {
-  return Isolate::Current()->object_store()->platform_library();
-}
-
 
 RawLibrary* Library::TypedDataLibrary() {
   return Isolate::Current()->object_store()->typed_data_library();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index d477a41..1a2e1d2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2543,7 +2543,6 @@
   static RawLibrary* MathLibrary();
   static RawLibrary* MirrorsLibrary();
   static RawLibrary* NativeWrappersLibrary();
-  static RawLibrary* PlatformLibrary();
   static RawLibrary* TypedDataLibrary();
   static RawLibrary* UtfLibrary();
 
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index d131951..37add48 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -29,7 +29,6 @@
     kIsolate,
     kMath,
     kMirrors,
-    kPlatform,
     kTypedData,
     kUtf,
   };
@@ -279,7 +278,6 @@
   RawLibrary* isolate_library() const { return isolate_library_; }
   RawLibrary* math_library() const { return math_library_; }
   RawLibrary* mirrors_library() const { return mirrors_library_; }
-  RawLibrary* platform_library() const { return platform_library_; }
   RawLibrary* typed_data_library() const { return typed_data_library_; }
   RawLibrary* utf_library() const { return utf_library_; }
   void set_bootstrap_library(BootstrapLibraryId index, const Library& value) {
@@ -308,9 +306,6 @@
       case kMirrors:
         mirrors_library_ = value.raw();
         break;
-      case kPlatform:
-        platform_library_ = value.raw();
-        break;
       case kTypedData:
         typed_data_library_ = value.raw();
         break;
@@ -483,7 +478,6 @@
   RawLibrary* math_library_;
   RawLibrary* mirrors_library_;
   RawLibrary* native_wrappers_library_;
-  RawLibrary* platform_library_;
   RawLibrary* root_library_;
   RawLibrary* typed_data_library_;
   RawLibrary* utf_library_;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index cba6d44..70dd982 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -7,6 +7,7 @@
 #include "vm/class_finalizer.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
+#include "vm/debugger.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
@@ -3546,6 +3547,45 @@
 }
 
 
+TEST_CASE(FunctionWithBreakpointNotInlined) {
+  const char* kScriptChars =
+      "class A {\n"
+      "  a() {\n"
+      "  }\n"
+      "  b() {\n"
+      "    a();\n"  // This is line 5.
+      "  }\n"
+      "}\n"
+      "test() {\n"
+      "  new A().b();\n"
+      "}";
+  const int kBreakpointLine = 5;
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  EXPECT_VALID(lib);
+
+  // Run function A.b one time.
+  Dart_Handle result = Dart_Invoke(lib, NewString("test"), 0, NULL);
+  EXPECT_VALID(result);
+
+  // With no breakpoint, function A.b is inlineable.
+  const String& name = String::Handle(String::New(TestCase::url()));
+  const Library& vmlib = Library::Handle(Library::LookupLibrary(name));
+  EXPECT(!vmlib.IsNull());
+  const Class& class_a = Class::Handle(
+      vmlib.LookupClass(String::Handle(Symbols::New("A"))));
+  const Function& func_b =
+      Function::Handle(GetFunction(class_a, "b"));
+  EXPECT(func_b.IsInlineable());
+
+  // After setting a breakpoint in a function A.b, it is no longer inlineable.
+  SourceBreakpoint* bpt =
+      Isolate::Current()->debugger()->SetBreakpointAtLine(name,
+                                                          kBreakpointLine);
+  ASSERT(bpt != NULL);
+  EXPECT(!func_b.IsInlineable());
+}
+
+
 TEST_CASE(SpecialClassesHaveEmptyArrays) {
   ObjectStore* object_store = Isolate::Current()->object_store();
   Class& cls = Class::Handle();
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index c9b1539..9b26bc3 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -23,7 +23,7 @@
             "Print free list statistics before a GC");
 DEFINE_FLAG(bool, print_free_list_after_gc, false,
             "Print free list statistics after a GC");
-DEFINE_FLAG(bool, collect_code, true,
+DEFINE_FLAG(bool, collect_code, false,
             "Attempt to GC infrequently used code.");
 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
             "Time between attempts to collect unused code.");
@@ -384,7 +384,6 @@
 }
 
 
-
 class CodeDetacherVisitor : public ObjectVisitor {
  public:
   explicit CodeDetacherVisitor(Isolate* isolate) : ObjectVisitor(isolate) { }
@@ -392,20 +391,26 @@
   virtual void VisitObject(RawObject* obj);
 
  private:
+  static bool MayDetachCode(const Function& fn);
   DISALLOW_COPY_AND_ASSIGN(CodeDetacherVisitor);
 };
 
 
+bool CodeDetacherVisitor::MayDetachCode(const Function& fn) {
+  return fn.HasCode() &&  // Not already detached.
+         !fn.HasOptimizedCode() &&
+         !fn.HasBreakpoint() &&
+         (fn.usage_counter() > 0);
+}
+
+
 void CodeDetacherVisitor::VisitObject(RawObject* raw_obj) {
   Isolate* isolate = Isolate::Current();
   HANDLESCOPE(isolate);
   const Object& obj = Object::Handle(raw_obj);
   if (obj.GetClassId() == kFunctionCid) {
     const Function& fn = Function::Cast(obj);
-    if (!fn.HasOptimizedCode() &&
-        !fn.HasBreakpoint() &&
-        fn.HasCode() &&  // Not already detached.
-        (fn.usage_counter() > 0)) {
+    if (CodeDetacherVisitor::MayDetachCode(fn)) {
       fn.set_usage_counter(fn.usage_counter() / 2);
       if (fn.usage_counter() == 0) {
         if (FLAG_log_code_drop) {
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 1801810..fea9b98 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -968,13 +968,13 @@
             ident_pos,
             field,
             new LiteralNode(ident_pos, Instance::ZoneHandle())));
-    // TODO(regis, 5802): Exception to throw is not specified by spec.
-    const String& circular_error = String::ZoneHandle(
-        Symbols::New("circular dependency in field initialization"));
+    // Call CyclicInitializationError._throwNew(field_name).
+    ArgumentListNode* error_arguments = new ArgumentListNode(ident_pos);
+    error_arguments->Add(new LiteralNode(ident_pos, field_name));
     report_circular->Add(
-        new ThrowNode(ident_pos,
-                      new LiteralNode(ident_pos, circular_error),
-                      NULL));
+        MakeStaticCall(Symbols::CyclicInitializationError(),
+                       Library::PrivateCoreLibName(Symbols::ThrowNew()),
+                       error_arguments));
     AstNode* circular_check =
         new IfNode(ident_pos, compare_circular, report_circular, NULL);
     current_block_->statements->Add(circular_check);
@@ -3995,7 +3995,7 @@
   bool is_alias_name = false;
   if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
     ConsumeToken();
-    if (TryParseTypeParameter() && (CurrentToken() == Token::kLPAREN)) {
+    if (TryParseTypeParameters() && (CurrentToken() == Token::kLPAREN)) {
       is_alias_name = true;
     }
   }
@@ -4014,7 +4014,7 @@
   bool is_mixin_def = false;
   if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
     ConsumeToken();
-    if (TryParseTypeParameter() && (CurrentToken() == Token::kASSIGN)) {
+    if (TryParseTypeParameters() && (CurrentToken() == Token::kASSIGN)) {
       is_mixin_def = true;
     }
   }
@@ -5587,7 +5587,7 @@
 
 // Returns true if the current and next tokens can be parsed as type
 // parameters. Current token position is not saved and restored.
-bool Parser::TryParseTypeParameter() {
+bool Parser::TryParseTypeParameters() {
   if (CurrentToken() == Token::kLT) {
     // We are possibly looking at type parameters. Find closing ">".
     int nesting_level = 0;
@@ -5672,7 +5672,7 @@
   if (CurrentToken() == Token::kIDENT) {
     QualIdent type_name;
     ParseQualIdent(&type_name);
-    if ((CurrentToken() == Token::kLT) && !TryParseTypeParameter()) {
+    if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) {
       return false;
     }
   }
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 5d8cc9b..5ccaca5 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -534,7 +534,7 @@
   bool IsSimpleLiteral(const AbstractType& type, Instance* value);
   bool IsFunctionTypeAliasName();
   bool IsMixinTypedef();
-  bool TryParseTypeParameter();
+  bool TryParseTypeParameters();
   bool TryParseOptionalType();
   bool TryParseReturnType();
   bool IsVariableDeclaration();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 27b64cf..887a361 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -40,6 +40,7 @@
   V(FallThroughError, "FallThroughError")                                      \
   V(AbstractClassInstantiationError, "AbstractClassInstantiationError")        \
   V(NoSuchMethodError, "NoSuchMethodError")                                    \
+  V(CyclicInitializationError, "CyclicInitializationError")                    \
   V(ThrowNew, "_throwNew")                                                     \
   V(Symbol, "Symbol")                                                          \
   V(SymbolCtor, "Symbol.")                                                     \
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index d8ff0b4..b55ac29 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -23,8 +23,6 @@
     'mirrors_patch_cc_file': '<(gen_source_dir)/mirrors_patch_gen.cc',
     'isolate_cc_file': '<(gen_source_dir)/isolate_gen.cc',
     'isolate_patch_cc_file': '<(gen_source_dir)/isolate_patch_gen.cc',
-    'platform_cc_file': '<(gen_source_dir)/platform_gen.cc',
-    'platform_patch_cc_file': '<(gen_source_dir)/platform_patch_gen.cc',
     'typed_data_cc_file': '<(gen_source_dir)/typed_data_gen.cc',
     'typed_data_patch_cc_file': '<(gen_source_dir)/typed_data_patch_gen.cc',
     'utf_cc_file': '<(gen_source_dir)/utf_gen.cc',
@@ -111,8 +109,6 @@
         'generate_isolate_patch_cc_file#host',
         'generate_mirrors_cc_file#host',
         'generate_mirrors_patch_cc_file#host',
-        'generate_platform_cc_file#host',
-        'generate_platform_patch_cc_file#host',
         'generate_typed_data_cc_file#host',
         'generate_typed_data_patch_cc_file#host',
         'generate_utf_cc_file#host',
@@ -124,7 +120,6 @@
         '../lib/isolate_sources.gypi',
         '../lib/math_sources.gypi',
         '../lib/mirrors_sources.gypi',
-        '../lib/platform_sources.gypi',
         '../lib/typed_data_sources.gypi',
       ],
       'sources': [
@@ -146,8 +141,6 @@
         '<(isolate_patch_cc_file)',
         '<(mirrors_cc_file)',
         '<(mirrors_patch_cc_file)',
-        '<(platform_cc_file)',
-        '<(platform_patch_cc_file)',
         '<(typed_data_cc_file)',
         '<(typed_data_patch_cc_file)',
         '<(utf_cc_file)',
@@ -167,7 +160,6 @@
         '../lib/isolate_sources.gypi',
         '../lib/math_sources.gypi',
         '../lib/mirrors_sources.gypi',
-        '../lib/platform_sources.gypi',
         '../lib/typed_data_sources.gypi',
       ],
       'sources': [
@@ -817,85 +809,6 @@
       ]
     },
     {
-      'target_name': 'generate_platform_cc_file',
-      'type': 'none',
-      'toolsets':['host'],
-      'includes': [
-        '../../sdk/lib/platform/platform_sources.gypi',
-      ],
-      'sources/': [
-        # Exclude all .[cc|h] files.
-        # This is only here for reference. Excludes happen after
-        # variable expansion, so the script has to do its own
-        # exclude processing of the sources being passed.
-        ['exclude', '\\.cc|h$'],
-      ],
-      'actions': [
-        {
-          'action_name': 'generate_platform_cc',
-          'inputs': [
-            '../tools/gen_library_src_paths.py',
-            '<(libgen_in_cc_file)',
-            '<@(_sources)',
-          ],
-          'outputs': [
-            '<(platform_cc_file)',
-          ],
-          'action': [
-            'python',
-            'tools/gen_library_src_paths.py',
-            '--output', '<(platform_cc_file)',
-            '--input_cc', '<(libgen_in_cc_file)',
-            '--include', 'vm/bootstrap.h',
-            '--var_name', 'dart::Bootstrap::platform_source_paths_',
-            '--library_name', 'dart:platform',
-            '<@(_sources)',
-          ],
-          'message': 'Generating ''<(platform_cc_file)'' file.'
-        },
-      ]
-    },
-    {
-      'target_name': 'generate_platform_patch_cc_file',
-      'type': 'none',
-      'toolsets':['host'],
-      'includes': [
-        # Load the runtime implementation sources.
-        '../lib/platform_sources.gypi',
-      ],
-      'sources/': [
-        # Exclude all .[cc|h] files.
-        # This is only here for reference. Excludes happen after
-        # variable expansion, so the script has to do its own
-        # exclude processing of the sources being passed.
-        ['exclude', '\\.cc|h$'],
-      ],
-      'actions': [
-        {
-          'action_name': 'generate_platform_patch_cc',
-          'inputs': [
-            '../tools/gen_library_src_paths.py',
-            '<(libgen_in_cc_file)',
-            '<@(_sources)',
-          ],
-          'outputs': [
-            '<(platform_patch_cc_file)',
-          ],
-          'action': [
-            'python',
-            'tools/gen_library_src_paths.py',
-            '--output', '<(platform_patch_cc_file)',
-            '--input_cc', '<(libgen_in_cc_file)',
-            '--include', 'vm/bootstrap.h',
-            '--var_name', 'dart::Bootstrap::platform_patch_paths_',
-            '--library_name', 'dart:platform',
-            '<@(_sources)',
-          ],
-          'message': 'Generating ''<(platform_patch_cc_file)'' file.'
-        },
-      ]
-    },
-    {
       'target_name': 'generate_typed_data_cc_file',
       'type': 'none',
       'toolsets':['host'],
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 921078b..e1fa84f 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -129,6 +129,7 @@
     'disassembler_x64.cc',
     'double_conversion.cc',
     'double_conversion.h',
+    'double_internals.h',
     'exceptions.cc',
     'exceptions.h',
     'exceptions_test.cc',
diff --git a/sdk/lib/_collection_dev/collection_dev.dart b/sdk/lib/_collection_dev/collection_dev.dart
index d82d903..6e883f6 100644
--- a/sdk/lib/_collection_dev/collection_dev.dart
+++ b/sdk/lib/_collection_dev/collection_dev.dart
@@ -9,7 +9,6 @@
 import 'dart:core' hide Symbol;
 import 'dart:core' as core;
 import 'dart:math' show Random;
-import 'dart:collection' show HashSet;
 
 part 'arrays.dart';
 part 'iterable.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index e30543a..a827bf6 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 import 'dart:io'
-    show exit, File, FileMode, Options, Platform, RandomAccessFile;
+    show exit, File, FileMode, Platform, RandomAccessFile;
 import 'dart:math' as math;
 
 import '../compiler.dart' as api;
@@ -452,11 +452,11 @@
   exit(1);
 }
 
-Future compilerMain(Options options) {
+Future compilerMain(List<String> arguments) {
   var root = uriPathToNative("/$LIBRARY_ROOT");
-  List<String> argv = ['--library-root=${options.script}$root'];
-  argv.addAll(options.arguments);
-  return compile(argv);
+  arguments =
+      <String>['--library-root=${Platform.script}$root']..addAll(arguments);
+  return compile(arguments);
 }
 
 void help() {
@@ -589,8 +589,8 @@
   fail(message);
 }
 
-void mainWithErrorHandler(Options options) {
-  runZoned(() => compilerMain(options), onError: (exception) {
+void main(List<String> arguments) {
+  runZoned(() => compilerMain(arguments), onError: (exception) {
     try {
       print('Internal error: $exception');
     } catch (ignored) {
@@ -607,7 +607,3 @@
     }
   });
 }
-
-void main() {
-  mainWithErrorHandler(new Options());
-}
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 4168c72..836d999 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -595,14 +595,17 @@
   final newTypedefElementCallback;
   final newClassElementCallback;
 
-  ReferencedElementCollector(
-      this.compiler,
-      Element rootElement, this.treeElements,
-      this.newTypedefElementCallback, this.newClassElementCallback)
-      : this.rootElement = (rootElement is VariableElement)
-          ? (rootElement as VariableElement).variables : rootElement;
+  ReferencedElementCollector(this.compiler,
+                             Element rootElement,
+                             this.treeElements,
+                             this.newTypedefElementCallback,
+                             this.newClassElementCallback)
+      : this.rootElement =
+          rootElement is VariableElement ? rootElement.variables : rootElement;
 
-  visitNode(Node node) { node.visitChildren(this); }
+  visitNode(Node node) {
+    node.visitChildren(this);
+  }
 
   visitTypeAnnotation(TypeAnnotation typeAnnotation) {
     // We call [resolveReturnType] to allow having 'void'.
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index ff98bd4..b6d3234 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -1121,12 +1121,16 @@
       : super(compiler, dynamicType, voidType);
 
   bool isMoreSpecific(DartType t, DartType s) {
-    if (identical(t, s) ||
-        t.treatAsDynamic ||
-        identical(s.element, compiler.objectClass) ||
+    if (identical(t, s) || s.treatAsDynamic ||
         identical(t.element, compiler.nullClass)) {
       return true;
     }
+    if (t.treatAsDynamic) {
+      return false;
+    }
+    if (identical(s.element, compiler.objectClass)) {
+      return true;
+    }
     t = t.unalias(compiler);
     s = s.unalias(compiler);
 
@@ -1138,6 +1142,7 @@
   }
 
   bool invalidFunctionReturnTypes(DartType t, DartType s) {
+    if (s.treatAsDynamic && t.isVoid) return true;
     return !s.isVoid && !isMoreSpecific(t, s);
   }
 
@@ -1161,7 +1166,7 @@
       : super(compiler, dynamicType, voidType);
 
   bool isSubtype(DartType t, DartType s) {
-    return s.treatAsDynamic || isMoreSpecific(t, s);
+    return t.treatAsDynamic || isMoreSpecific(t, s);
   }
 
   bool isAssignable(DartType t, DartType s) {
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 06ed03b..e97f3dcb 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -218,7 +218,8 @@
       // need to emit the method.
       if (universe.hasInvokedGetter(member, compiler)) {
         registerClosurizedMember(member, compiler.globalDependencies);
-        return addToWorkList(member);
+        addToWorkList(member);
+        return;
       }
       // Store the member in [instanceFunctionsByName] to catch
       // getters on the function.
@@ -226,20 +227,24 @@
           memberName, () => const Link<Element>());
       instanceFunctionsByName[memberName] = members.prepend(member);
       if (universe.hasInvocation(member, compiler)) {
-        return addToWorkList(member);
+        addToWorkList(member);
+        return;
       }
     } else if (member.kind == ElementKind.GETTER) {
       if (universe.hasInvokedGetter(member, compiler)) {
-        return addToWorkList(member);
+        addToWorkList(member);
+        return;
       }
       // We don't know what selectors the returned closure accepts. If
       // the set contains any selector we have to assume that it matches.
       if (universe.hasInvocation(member, compiler)) {
-        return addToWorkList(member);
+        addToWorkList(member);
+        return;
       }
     } else if (member.kind == ElementKind.SETTER) {
       if (universe.hasInvokedSetter(member, compiler)) {
-        return addToWorkList(member);
+        addToWorkList(member);
+        return;
       }
     }
 
diff --git a/sdk/lib/_internal/compiler/implementation/filenames.dart b/sdk/lib/_internal/compiler/implementation/filenames.dart
index e357757..32aca53 100644
--- a/sdk/lib/_internal/compiler/implementation/filenames.dart
+++ b/sdk/lib/_internal/compiler/implementation/filenames.dart
@@ -4,7 +4,7 @@
 
 library filenames;
 
-import 'dart:io';
+import 'dart:io' show Platform;
 
 // For information about how to convert Windows file names to URIs:
 // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
@@ -29,8 +29,6 @@
   }
 }
 
-final Uri currentDirectory = new Uri(
-    scheme: 'file',
-    path: appendSlash(nativeToUriPath(new File('.').fullPathSync())));
+final Uri currentDirectory = Uri.base;
 
 String appendSlash(String path) => path.endsWith('/') ? path : '$path/';
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
index e1f31b9..a134ac6 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
@@ -110,6 +110,7 @@
 
     // From List.
     '[]',
+    '[]=',
     'length',
     'reversed',
     'sort',
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 09ddeb7..46170e4 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -256,6 +256,10 @@
     positional.forEach(f);
     named.values.forEach(f);
   }
+
+  bool every(bool f(T type)) {
+    return positional.every(f) && named.values.every(f);
+  }
 }
 
 abstract class MinimalInferrerEngine<T> {
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
index 8f41971..9be28ab 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -781,21 +781,23 @@
 
   T visitSuperSend(Send node) {
     Element element = elements[node];
-    if (Elements.isUnresolved(element)) {
-      return types.dynamicType;
-    }
     Selector selector = elements.getSelector(node);
     // TODO(ngeoffray): We could do better here if we knew what we
     // are calling does not expose this.
     isThisExposed = true;
-    if (node.isPropertyAccess) {
-      return handleStaticSend(node, selector, element, null);
-    } else if (element.isFunction() || element.isGenerativeConstructor()) {
-      if (!selector.applies(element, compiler)) return types.dynamicType;
-      ArgumentsTypes arguments = analyzeArguments(node.arguments);
+    ArgumentsTypes arguments = node.isPropertyAccess
+        ? null
+        : analyzeArguments(node.arguments);
+    if (Elements.isUnresolved(element)
+        || !selector.applies(element, compiler)) {
+      // Ensure we create a node, to make explicit the call to the
+      // `noSuchMethod` handler.
+      return handleDynamicSend(node, selector, superType, arguments);
+    } else if (node.isPropertyAccess
+              || element.isFunction()
+              || element.isGenerativeConstructor()) {
       return handleStaticSend(node, selector, element, arguments);
     } else {
-      ArgumentsTypes arguments = analyzeArguments(node.arguments);
       return inferrer.registerCalledClosure(
           node, selector, inferrer.typeOfElement(element),
           outermostElement, arguments, sideEffects, inLoop);
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
index f621f46..0e5cf70 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -382,6 +382,7 @@
   final List<CallSiteTypeInformation> allocatedCalls =
       <CallSiteTypeInformation>[];
   final WorkQueue workQueue = new WorkQueue();
+  final Element mainElement;
 
   /// The maximum number of times we allow a node in the graph to
   /// change types. If a node reaches that limit, we give up
@@ -390,7 +391,7 @@
 
   int overallRefineCount = 0;
 
-  TypeGraphInferrerEngine(Compiler compiler)
+  TypeGraphInferrerEngine(Compiler compiler, this.mainElement)
         : super(compiler, new TypeInformationSystem(compiler));
 
   void runOverAllElements() {
@@ -541,10 +542,12 @@
       if ((info.type = newType) != oldType) {
         overallRefineCount++;
         info.refineCount++;
-        if (info.refineCount > MAX_CHANGE_COUNT) {
+        workQueue.addAll(info.users);
+        if (info.hasStableType(this)) {
+          info.stabilize(this);
+        } else if (info.refineCount > MAX_CHANGE_COUNT) {
           info.giveUp(this);
         }
-        workQueue.addAll(info.users);
       }
     }
   }
@@ -848,8 +851,8 @@
 
   String get name => 'Graph inferrer';
 
-  void analyzeMain(_) {
-    inferrer = new TypeGraphInferrerEngine(compiler);
+  void analyzeMain(Element main) {
+    inferrer = new TypeGraphInferrerEngine(compiler, main);
     inferrer.runOverAllElements();
   }
 
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 ea4c22e..1057dcb 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -39,6 +39,10 @@
   /// work queue.
   bool inQueue = false;
 
+  /// Whether this [TypeInformation] has a stable [type] that will not
+  /// change.
+  bool isStable = false;
+
   // TypeInformations are unique.
   static int staticHashCode = 0;
   final int hashCode = staticHashCode++;
@@ -51,11 +55,13 @@
 
 
   void addUser(TypeInformation user) {
+    if (isStable) return;
     assert(!user.isConcrete);
     users.add(user);
   }
 
   void removeUser(TypeInformation user) {
+    if (isStable) return;
     assert(!user.isConcrete);
     users.remove(user);
   }
@@ -89,7 +95,12 @@
   void giveUp(TypeGraphInferrerEngine inferrer) {
     abandonInferencing = true;
     type = inferrer.types.dynamicType.type;
+    // Do not remove [this] as a user of nodes in [assignments],
+    // because our tracing analysis could be interested in tracing
+    // this node.
     assignments = const <TypeInformation>[];
+    // Do not remove users because our tracing analysis could be
+    // interested in tracing the users of this node.
   }
 
   void clear() {
@@ -114,6 +125,24 @@
   /// for some [TypeInformation] nodes, where we do not need to store
   /// the information.
   Element get owner => null;
+
+  /// Returns whether the type cannot change after it has been
+  /// inferred.
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    return !abandonInferencing && assignments.every((e) => e.isStable);
+  }
+
+  void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+    assignments.forEach((info) { info.removeUser(this); });
+  }
+
+  void stabilize(TypeGraphInferrerEngine inferrer) {
+    removeAndClearReferences(inferrer);
+    users = const <TypeInformation>[];
+    assignments = const <TypeInformation>[];
+    abandonInferencing = true;
+    isStable = true;
+  }
 }
 
 /**
@@ -228,6 +257,14 @@
         // [call] instance methods.
         giveUp(inferrer);
         return type;
+      } else if (enclosing == inferrer.mainElement) {
+        // The implicit call to main is not seen by the inferrer,
+        // therefore we explicitly set the type of its parameters as
+        // dynamic.
+        // TODO(14566): synthesize a call instead to get the exact
+        // types.
+        giveUp(inferrer);
+        return type;
       }
     }
     if (element.isField()
@@ -294,6 +331,21 @@
   }
 
   Element get owner => element.getOutermostEnclosingMemberOrTopLevel();
+
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    // The number of assignments of parameters of instance methods is
+    // not stable. Therefore such a parameter cannot be stable.
+    if (element.isParameter() && element.enclosingElement.isInstanceMember()) {
+      return false;
+    }
+    // The number of assignments of non-final fields is
+    // not stable. Therefore such a field cannot be stable.
+    if (element.isField()
+        && !(element.modifiers.isConst() || element.modifiers.isFinal())) {
+      return false;
+    }
+    return super.hasStableType(inferrer);
+  }
 }
 
 /**
@@ -380,6 +432,22 @@
   accept(TypeInformationVisitor visitor) {
     return visitor.visitStaticCallSiteTypeInformation(this);
   }
+
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    return inferrer.types.getInferredTypeOf(calledElement).isStable
+        && (arguments == null || arguments.every((info) => info.isStable))
+        && super.hasStableType(inferrer);
+  }
+
+  void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+    ElementTypeInformation callee =
+        inferrer.types.getInferredTypeOf(calledElement);
+    callee.removeUser(this);
+    if (arguments != null) {
+      arguments.forEach((info) => info.removeUser(this));
+    }
+    super.removeAndClearReferences(inferrer);
+  }
 }
 
 class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
@@ -479,7 +547,21 @@
     Iterable<Element> oldTargets = targets;
     Selector typedSelector = computeTypedSelector(inferrer);
     inferrer.updateSelectorInTree(caller, call, typedSelector);
-    targets = inferrer.compiler.world.allFunctions.filter(typedSelector);
+
+    Compiler compiler = inferrer.compiler;
+    Selector selectorToUse = typedSelector.extendIfReachesAll(compiler);
+
+    bool canReachAll = compiler.enabledInvokeOn
+        && (selectorToUse != typedSelector);
+
+    // If this call could potentially reach all methods that satisfy
+    // the untyped selector (through noSuchMethod's `Invocation`
+    // and a call to `delegate`), we iterate over all these methods to
+    // update their parameter types.
+    targets = compiler.world.allFunctions.filter(selectorToUse);
+    Iterable<Element> typedTargets = canReachAll
+        ? compiler.world.allFunctions.filter(typedSelector)
+        : targets;
 
     // Walk over the found targets, and compute the joined union type mask
     // for all these targets.
@@ -493,6 +575,15 @@
             this, element, arguments, typedSelector, remove: false);
       }
 
+      // If [canReachAll] is true, then we are iterating over all
+      // targets that satisfy the untyped selector. We skip the return
+      // type of the targets that can only be reached through
+      // `Invocation.delegate`. Note that the `noSuchMethod` targets
+      // are included in [typedTargets].
+      if (canReachAll && !typedTargets.contains(element)) {
+        return const TypeMask.nonNullEmpty();
+      }
+
       if (returnsElementType(typedSelector)) {
         ContainerTypeMask mask = receiver.type;
         return mask.elementType;
@@ -516,6 +607,7 @@
             this, element, arguments, typedSelector, remove: true);
       }
     });
+
     return newType;
   }
 
@@ -535,6 +627,17 @@
     super.giveUp(inferrer);
   }
 
+  void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+    for (Element element in targets) {
+      ElementTypeInformation callee = inferrer.types.getInferredTypeOf(element);
+      callee.removeUser(this);
+    }
+    if (arguments != null) {
+      arguments.forEach((info) => info.removeUser(this));
+    }
+    super.removeAndClearReferences(inferrer);
+  }
+
   bool reachedBy(TypeInformation info, TypeGraphInferrerEngine inferrer) {
     return targets
             .map((element) => inferrer.types.getInferredTypeOf(element))
@@ -546,6 +649,14 @@
   accept(TypeInformationVisitor visitor) {
     return visitor.visitDynamicCallSiteTypeInformation(this);
   }
+
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    return receiver.isStable
+        && targets.every(
+              (element) => inferrer.types.getInferredTypeOf(element).isStable)
+        && (arguments == null || arguments.every((info) => info.isStable))
+        && super.hasStableType(inferrer);
+  }
 }
 
 class ClosureCallSiteTypeInformation extends CallSiteTypeInformation {
@@ -576,6 +687,16 @@
   accept(TypeInformationVisitor visitor) {
     return visitor.visitClosureCallSiteTypeInformation(this);
   }
+
+  void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+    // This method is a placeholder for the following comment:
+    // We should maintain the information that the closure is a user
+    // of its arguments because we do not check that the arguments
+    // have a stable type for a closure call to be stable; our tracing
+    // analysis want to know whether an (non-stable) argument is
+    // passed to a closure.
+    return super.removeAndClearReferences(inferrer);
+  }
 }
 
 /**
@@ -592,6 +713,7 @@
   ConcreteTypeInformation(TypeMask type)
       : super(const <TypeInformation>[], const <TypeInformation>[]) {
     this.type = type;
+    this.isStable = true;
   }
 
   bool get isConcrete => true;
@@ -620,6 +742,10 @@
   accept(TypeInformationVisitor visitor) {
     return visitor.visitConcreteTypeInformation(this);
   }
+
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    return true;
+  }
 }
 
 /**
@@ -652,7 +778,9 @@
     return assignments[0].type.intersection(typeAnnotation, inferrer.compiler);
   }
 
-  String toString() => 'Narrow ${assignments.first} to $typeAnnotation $type';
+  String toString() {
+    return 'Narrow to $typeAnnotation $type';
+  }
 
   accept(TypeInformationVisitor visitor) {
     return visitor.visitNarrowTypeInformation(this);
@@ -689,6 +817,10 @@
     return visitor.visitContainerTypeInformation(this);
   }
 
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    return elementType.isStable && super.hasStableType(inferrer);
+  }
+
   TypeMask refine(TypeGraphInferrerEngine inferrer) {
     var mask = type;
     if (!mask.isContainer
@@ -728,6 +860,10 @@
   accept(TypeInformationVisitor visitor) {
     return visitor.visitElementInContainerTypeInformation(this);
   }
+
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    return inferred && super.hasStableType(inferrer);
+  }
 }
 
 /**
diff --git a/sdk/lib/_internal/compiler/implementation/js/printer.dart b/sdk/lib/_internal/compiler/implementation/js/printer.dart
index a21e713..1cf97a3 100644
--- a/sdk/lib/_internal/compiler/implementation/js/printer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/printer.dart
@@ -456,7 +456,7 @@
         (requiredPrecedence != EXPRESSION &&
          node.precedenceLevel < requiredPrecedence) ||
         // for (a = (x in o); ... ; ... ) { ... }
-        (newInForInit && node is Binary && (node as Binary).op == "in") ||
+        (newInForInit && node is Binary && node.op == "in") ||
         // (function() { ... })().
         // ({a: 2, b: 3}.toString()).
         (newAtStatementBegin && (node is NamedFunction ||
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 4cbc51c..0638d86 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -208,11 +208,19 @@
   Element mapTypeToInterceptor;
 
   HType stringType;
+  HType doubleType;
+  HType intType;
+  HType numType;
+  HType boolType;
   HType indexablePrimitiveType;
   HType readableArrayType;
   HType mutableArrayType;
   HType fixedArrayType;
   HType extendableArrayType;
+  HType nonNullType;
+  HType dynamicType;
+  HType nullType = const HBoundedType(const TypeMask.empty());
+  HType emptyType = const HBoundedType(const TypeMask.nonNullEmpty());
 
   // TODO(9577): Make it so that these are not needed when there are no native
   // classes.
@@ -419,7 +427,6 @@
 
   bool invokedReflectively(Element element) {
     if (element.isParameter() || element.isFieldParameter()) {
-      if (hasInsufficientMirrorsUsed && compiler.enabledInvokeOn) return true;
       if (invokedReflectively(element.enclosingElement)) return true;
     }
 
@@ -428,7 +435,6 @@
           && (element.modifiers.isFinal() || element.modifiers.isConst())) {
         return false;
       }
-      if (hasInsufficientMirrorsUsed && compiler.enabledInvokeOn) return true;
     }
 
     return isNeededForReflection(element.declaration);
@@ -615,6 +621,14 @@
 
     stringType = new HBoundedType(
         new TypeMask.nonNullExact(jsStringClass));
+    doubleType = new HBoundedType(
+        new TypeMask.nonNullExact(jsDoubleClass));
+    intType = new HBoundedType(
+        new TypeMask.nonNullExact(jsIntClass));
+    numType = new HBoundedType(
+        new TypeMask.nonNullSubclass(jsNumberClass));
+    boolType = new HBoundedType(
+        new TypeMask.nonNullExact(jsBoolClass));
     indexablePrimitiveType = new HBoundedType(
         new TypeMask.nonNullSubtype(jsIndexableClass));
     readableArrayType = new HBoundedType(
@@ -625,6 +639,10 @@
         new TypeMask.nonNullExact(jsFixedArrayClass));
     extendableArrayType = new HBoundedType(
         new TypeMask.nonNullExact(jsExtendableArrayClass));
+    nonNullType = new HBoundedType(
+        compiler.typesTask.dynamicType.nonNullable());
+    dynamicType = new HBoundedType(
+        compiler.typesTask.dynamicType);
 
     typeVariableClass = compiler.findHelper('TypeVariable');
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index 04f983b..c6ee2e5 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -155,6 +155,11 @@
   final Namer namer;
   final ConstantReferenceEmitter referenceEmitter;
 
+  // Matches blank lines, comment lines and trailing comments that can't be part
+  // of a string.
+  static final RegExp COMMENT_RE =
+      new RegExp(r'''^ *(//.*)?\n|  *//[^''"\n]*$''' , multiLine: true);
+
   ConstantInitializerEmitter(this.compiler, this.namer, this.referenceEmitter);
 
   jsAst.Expression generate(Constant constant) {
@@ -313,7 +318,8 @@
     if (element.isForeign(compiler)
         && element.name == 'JS_CONST') {
       StringConstant str = constant.fields[0];
-      return new jsAst.LiteralExpression(str.value.slowToString());
+      String value = str.value.slowToString();
+      return new jsAst.LiteralExpression(stripComments(value));
     }
     jsAst.New instantiation = new jsAst.New(
         new jsAst.VariableUse(getJsConstructor(constant.type.element)),
@@ -321,6 +327,10 @@
     return maybeAddTypeArguments(constant.type, instantiation);
   }
 
+  String stripComments(String rawJavaScript) {
+    return rawJavaScript.replaceAll(COMMENT_RE, '');
+  }
+
   List<jsAst.Expression> _array(List<Constant> values) {
     List<jsAst.Expression> valueList = <jsAst.Expression>[];
     for (int i = 0; i < values.length; i++) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
index 49c7121..9598af7 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -5,7 +5,7 @@
 library js_backend;
 
 import 'dart:async' show Future;
-import 'dart:collection' show Queue;
+import 'dart:collection' show Queue, LinkedHashMap;
 
 import '../closure.dart';
 import '../elements/elements.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 6febc82..e22454b 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -223,6 +223,9 @@
   final String methodsWithOptionalArgumentsField =
       r'$methodsWithOptionalArguments';
 
+  // Name of property in a class description for the native dispatch metadata.
+  final String nativeSpecProperty = '%';
+
   /**
    * Map from top-level or static elements to their unique identifiers provided
    * by [getName].
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index d7c0b4e..0ddad2a6 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -111,9 +111,14 @@
    * [classes] contains native classes, mixin applications, and user subclasses
    * of native classes.  ONLY the native classes are generated here.  [classes]
    * is sorted in desired output order.
+   *
+   * [additionalProperties] is used to collect properties that are pushed up
+   * from the above optimizations onto a non-native class, e.g, `Interceptor`.
    */
-  void generateNativeClasses(List<ClassElement> classes,
-                             CodeBuffer mainBuffer) {
+  void generateNativeClasses(
+      List<ClassElement> classes,
+      CodeBuffer mainBuffer,
+      Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties) {
     // Compute a pre-order traversal of the subclass forest.  We actually want a
     // post-order traversal but it is easier to compute the pre-order and use it
     // in reverse.
@@ -259,17 +264,14 @@
           // No builder because this is an intermediate mixin application or
           // Interceptor - these are not direct native classes.
           if (encoding != '') {
-            // TODO(sra): Figure out how to emit this as a property onto
-            // Interceptor's ClassBuilder.
-            jsAst.Expression assignment =
-                js.assign(
-                    js(backend.namer.isolateAccess(classElement))['%'],
-                    js.string(encoding));
-            nativeBuffer.add(jsAst.prettyPrint(assignment, compiler));
-            nativeBuffer.add('$N$n');
+            Map<String, jsAst.Expression> properties =
+                additionalProperties.putIfAbsent(classElement,
+                    () => new LinkedHashMap<String, jsAst.Expression>());
+            properties[backend.namer.nativeSpecProperty] = js.string(encoding);
           }
         } else {
-          builder.addProperty('%', js.string(encoding));
+          builder.addProperty(
+              backend.namer.nativeSpecProperty, js.string(encoding));
         }
       }
       generateClassInfo(backend.jsInterceptorClass);
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
index 53285fd..6ea330e 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
@@ -10,7 +10,9 @@
    *
    * Invariant: [classElement] must be a declaration element.
    */
-  void generateClass(ClassElement classElement, CodeBuffer buffer) {
+  void generateClass(ClassElement classElement,
+                     CodeBuffer buffer,
+                     Map<String, jsAst.Expression> additionalProperties) {
     final onlyForRti =
         task.typeTestEmitter.rtiNeededClasses.contains(classElement);
 
@@ -41,6 +43,9 @@
     emitClassGettersSetters(classElement, builder, onlyForRti: onlyForRti);
     emitInstanceMembers(classElement, builder, onlyForRti: onlyForRti);
     task.typeTestEmitter.emitIsTests(classElement, builder);
+    if (additionalProperties != null) {
+      additionalProperties.forEach(builder.addProperty);
+    }
 
     emitClassBuilderWithReflectionData(
         className, classElement, builder, buffer);
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index ac0cec4..1019547 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -39,6 +39,9 @@
   final Map<String, String> mangledGlobalFieldNames = <String, String>{};
   final Set<String> recordedMangledNames = new Set<String>();
 
+  final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties =
+      new Map<ClassElement, Map<String, jsAst.Expression>>();
+
   // TODO(ngeoffray): remove this field.
   Set<ClassElement> instantiatedClasses;
 
@@ -408,6 +411,8 @@
   }
 
   jsAst.FunctionDeclaration buildFinishClass() {
+    String specProperty = '"${namer.nativeSpecProperty}"';  // "%"
+
     // function finishClass(cls) {
     jsAst.Fun fun = js.fun(['cls'], [
 
@@ -461,8 +466,8 @@
           //
           // The information is used to build tables referenced by
           // getNativeInterceptor and custom element support.
-          js.if_('hasOwnProperty.call(prototype, "%")', [
-              js('var nativeSpec = prototype["%"].split(";")'),
+          js.if_('hasOwnProperty.call(prototype, $specProperty)', [
+              js('var nativeSpec = prototype[$specProperty].split(";")'),
               js.if_('nativeSpec[0]', [
                   js('var tags = nativeSpec[0].split("|")'),
                   js.for_('var i = 0', 'i < tags.length', 'i++', [
@@ -734,7 +739,8 @@
   }
 
   void generateClass(ClassElement classElement, CodeBuffer buffer) {
-    classEmitter.generateClass(classElement, buffer);
+    classEmitter.generateClass(
+        classElement, buffer, additionalProperties[classElement]);
   }
 
   int _selectorRank(Selector selector) {
@@ -1177,6 +1183,16 @@
         mainBuffer.add('var $classesCollector$_=$_{}$N$n');
       }
 
+      // Emit native classes on [nativeBuffer].
+      // Might create methodClosures.
+      final CodeBuffer nativeBuffer = new CodeBuffer();
+      if (!nativeClasses.isEmpty) {
+        addComment('Native classes', nativeBuffer);
+        addComment('Native classes', mainBuffer);
+        nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer,
+            additionalProperties);
+      }
+
       // As a side-effect, emitting classes will produce "bound closures" in
       // [methodClosures].  The bound closures are JS AST nodes that add
       // properties to $$ [classesCollector].  The bound closures are not
@@ -1189,14 +1205,6 @@
         }
       }
 
-      // Emit native classes on [nativeBuffer].
-      // Might create methodClosures.
-      final CodeBuffer nativeBuffer = new CodeBuffer();
-      if (!nativeClasses.isEmpty) {
-        addComment('Native classes', nativeBuffer);
-        addComment('Native classes', mainBuffer);
-        nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer);
-      }
       nativeEmitter.finishGenerateNativeClasses();
       nativeEmitter.assembleCode(nativeBuffer);
 
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index d7b26d6d..94ace737 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -492,8 +492,7 @@
     return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>(
         _members,
         (MemberMirror member) =>
-            member is MethodMirror && (member as MethodMirror).isGetter ?
-                member : null);
+            member is MethodMirror && member.isGetter ? member : null);
   }
 
   Map<String, MethodMirror> get setters {
@@ -501,8 +500,7 @@
     return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>(
         _members,
         (MemberMirror member) =>
-            member is MethodMirror && (member as MethodMirror).isSetter ?
-                member : null);
+            member is MethodMirror && member.isSetter ? member : null);
   }
 
   Map<String, VariableMirror> get variables {
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 0d24f1d..bb42db9 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -1062,6 +1062,7 @@
   Compiler compiler = builder.compiler;
   FunctionElement element = builder.work.element;
   NativeEmitter nativeEmitter = builder.emitter.nativeEmitter;
+  JavaScriptBackend backend = builder.backend;
 
   HInstruction convertDartClosure(Element parameter, FunctionType type) {
     HInstruction local = builder.localsHandler.readLocal(parameter);
@@ -1070,7 +1071,7 @@
     HInstruction arity = builder.graph.addConstant(arityConstant, compiler);
     // TODO(ngeoffray): For static methods, we could pass a method with a
     // defined arity.
-    Element helper = builder.backend.getClosureConverter();
+    Element helper = backend.getClosureConverter();
     builder.pushInvokeStatic(nativeBody, helper, [local, arity]);
     HInstruction closure = builder.pop();
     return closure;
@@ -1134,7 +1135,7 @@
                                      element: element);
     }
 
-    builder.push(new HForeign(js.js(nativeMethodCall), HType.UNKNOWN,
+    builder.push(new HForeign(js.js(nativeMethodCall), backend.dynamicType,
                               inputs, effects: new SideEffects()));
     builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit);
   } else {
@@ -1148,6 +1149,7 @@
         new js.LiteralStatement(jsCode.dartString.slowToString()),
         <HInstruction>[],
         new SideEffects(),
-        null));
+        null,
+        backend.dynamicType));
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/patch_parser.dart b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
index b528fa2..06430af 100644
--- a/sdk/lib/_internal/compiler/implementation/patch_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
@@ -25,7 +25,7 @@
  * element, regardless of whether the element is one of the three patchable
  * element types or not.
  *
- * ## Variants of Classes and Functions ##
+ * ## Variants of classes and functions ##
  *
  * With patches there are four variants of classes and function:
  *
@@ -67,7 +67,7 @@
  *     }
  *
  *
- * ## Declaration and Implementation ##
+ * ## Declaration and implementation ##
  *
  * With patches we have two views on elements: as the 'declaration' which
  * introduces the entity and defines its interface, and as the 'implementation'
@@ -178,7 +178,7 @@
     // of calling its [parseNode] method.
     if (element.cachedNode != null) return;
 
-    return measure(() => compiler.withCurrentElement(element, () {
+    measure(() => compiler.withCurrentElement(element, () {
       PatchMemberListener listener = new PatchMemberListener(compiler, element);
       Parser parser = new PatchClassElementParser(listener);
       Token token = parser.parseTopLevelDeclaration(element.beginToken);
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index bab8bfe..cbc31ee 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -461,7 +461,7 @@
         FunctionExpression tree = element.parseNode(compiler);
         if (tree.modifiers.isExternal()) {
           error(tree, MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
-          return;
+          return null;
         }
         if (isConstructor || element.isFactoryConstructor()) {
           if (tree.returnType != null) {
@@ -1926,6 +1926,12 @@
   int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
       | ElementCategory.IMPLIES_TYPE;
 
+  /**
+   * Record of argument nodes to JS_INTERCEPTOR_CONSTANT for deferred
+   * processing.
+   */
+  Set<Node> argumentsToJsInterceptorConstant = null;
+
   /// When visiting the type declaration of the variable in a [ForIn] loop,
   /// the initializer of the variable is implicit and we should not emit an
   /// error when verifying that all final variables are initialized.
@@ -2602,7 +2608,7 @@
     // If the selector is null, it means that we will not be generating
     // code for this as a send.
     Selector selector = mapping.getSelector(node);
-    if (selector == null) return;
+    if (selector == null) return null;
 
     if (node.isCall) {
       if (Elements.isUnresolved(target) ||
@@ -2622,10 +2628,17 @@
         warnArgumentMismatch(node, target);
       }
 
-      if (target != null &&
-          target.isForeign(compiler) &&
-          selector.name == 'JS') {
-        world.registerJsCall(node, this);
+      if (target != null && target.isForeign(compiler)) {
+        if (selector.name == 'JS') {
+          world.registerJsCall(node, this);
+        } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') {
+          if (!node.argumentsNode.isEmpty) {
+            Node argument = node.argumentsNode.nodes.head;
+            if (argumentsToJsInterceptorConstant == null)
+              argumentsToJsInterceptorConstant = new Set<Node>();
+            argumentsToJsInterceptorConstant.add(argument);
+          }
+        }
       }
     }
 
@@ -3042,8 +3055,28 @@
 
   void analyzeConstant(Node node, {bool isConst: true}) {
     addDeferredAction(enclosingElement, () {
-       compiler.constantHandler.compileNodeWithDefinitions(
+       Constant constant = compiler.constantHandler.compileNodeWithDefinitions(
            node, mapping, isConst: isConst);
+
+       // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names
+       // a class that will be instantiated outside the program by attaching a
+       // native class dispatch record referencing the interceptor.
+       if (argumentsToJsInterceptorConstant != null &&
+           argumentsToJsInterceptorConstant.contains(node)) {
+         if (constant.isType()) {
+           TypeConstant typeConstant = constant;
+           if (typeConstant.representedType is InterfaceType) {
+             world.registerInstantiatedType(typeConstant.representedType,
+                 mapping);
+           } else {
+             compiler.reportError(node,
+                 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
+           }
+         } else {
+           compiler.reportError(node,
+               MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
+         }
+       }
     });
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
index 0d00bd0..8659ead 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
@@ -428,7 +428,7 @@
     if (identical(next, $CLOSE_SQUARE_BRACKET)) {
       Token token = previousToken();
       if (token is KeywordToken &&
-          identical((token as KeywordToken).keyword.syntax, 'operator')) {
+          identical(token.keyword.syntax, 'operator')) {
         return select($EQ, INDEX_EQ_INFO, INDEX_INFO);
       }
     }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index a0df363..0a88bd3 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -141,8 +141,9 @@
   HInstruction createBox() {
     // TODO(floitsch): Clean up this hack. Should we create a box-object by
     // just creating an empty object literal?
+    JavaScriptBackend backend = builder.backend;
     HInstruction box = new HForeign(new js.ObjectInitializer([]),
-                                    HType.UNKNOWN,
+                                    backend.nonNullType,
                                     <HInstruction>[]);
     builder.add(box);
     return box;
@@ -162,7 +163,8 @@
     if (element != null && element.isGenerativeConstructorBody()) {
       // The box is passed as a parameter to a generative
       // constructor body.
-      box = builder.addParameter(scopeData.boxElement);
+      JavaScriptBackend backend = builder.backend;
+      box = builder.addParameter(scopeData.boxElement, backend.nonNullType);
     } else {
       box = createBox();
     }
@@ -235,11 +237,11 @@
             return;
           }
         }
-        HInstruction parameter = builder.addParameter(parameterElement);
+        HInstruction parameter = builder.addParameter(
+            parameterElement,
+            new HType.inferredTypeForElement(parameterElement, compiler));
         builder.parameters[parameterElement] = parameter;
         directLocals[parameterElement] = parameter;
-        parameter.instructionType =
-            new HType.inferredTypeForElement(parameterElement, compiler);
       });
     }
 
@@ -251,10 +253,11 @@
     closureData.freeVariableMapping.forEach((Element from, Element to) {
       redirectElement(from, to);
     });
+    JavaScriptBackend backend = compiler.backend;
     if (closureData.isClosure()) {
       // Inside closure redirect references to itself to [:this:].
       HThis thisInstruction = new HThis(closureData.thisElement,
-                                        HType.NON_NULL);
+                                        backend.nonNullType);
       builder.graph.thisInstruction = thisInstruction;
       builder.graph.entry.addAtEntry(thisInstruction);
       updateLocal(closureData.closureElement, thisInstruction);
@@ -273,7 +276,6 @@
     // parameter to it, that is the actual receiver for intercepted
     // classes, or the same as [:this:] for non-intercepted classes.
     ClassElement cls = element.getEnclosingClass();
-    JavaScriptBackend backend = compiler.backend;
 
     // When the class extends a native class, the instance is pre-constructed
     // and passed to the generative constructor factory function as a parameter.
@@ -286,7 +288,8 @@
       String name = isInterceptorClass ? 'receiver' : '_';
       Element parameter = new InterceptedElement(
           cls.computeType(compiler), name, element);
-      HParameterValue value = new HParameterValue(parameter);
+      HParameterValue value =
+          new HParameterValue(parameter, builder.getTypeOfThis());
       builder.graph.explicitReceiverParameter = value;
       builder.graph.entry.addAfter(
           directLocals[closureData.thisElement], value);
@@ -294,16 +297,15 @@
         // Only use the extra parameter in intercepted classes.
         directLocals[closureData.thisElement] = value;
       }
-      value.instructionType = builder.getTypeOfThis();
     } else if (isNativeUpgradeFactory) {
       Element parameter = new InterceptedElement(
           cls.computeType(compiler), 'receiver', element);
-      HParameterValue value = new HParameterValue(parameter);
-      builder.graph.explicitReceiverParameter = value;
-      builder.graph.entry.addAtEntry(value);
       // Unlike `this`, receiver is nullable since direct calls to generative
       // constructor call the constructor with `null`.
-      value.instructionType = new HType.exact(cls, compiler);
+      HParameterValue value =
+          new HParameterValue(parameter, new HType.exact(cls, compiler));
+      builder.graph.explicitReceiverParameter = value;
+      builder.graph.entry.addAtEntry(value);
     }
   }
 
@@ -367,8 +369,8 @@
     } else if (isStoredInClosureField(element)) {
       Element redirect = redirectionMapping[element];
       HInstruction receiver = readLocal(closureData.closureElement);
-      HInstruction fieldGet = new HFieldGet(redirect, receiver);
-      fieldGet.instructionType = builder.getTypeOfCapturedVariable(redirect);
+      HInstruction fieldGet = new HFieldGet(
+          redirect, receiver, builder.getTypeOfCapturedVariable(redirect));
       builder.add(fieldGet);
       return fieldGet;
     } else if (isBoxed(element)) {
@@ -380,14 +382,15 @@
       // the box.
       assert(redirect.enclosingElement.isVariable());
       HInstruction box = readLocal(redirect.enclosingElement);
-      HInstruction lookup = new HFieldGet(redirect, box);
-      lookup.instructionType = builder.getTypeOfCapturedVariable(redirect);
+      HInstruction lookup = new HFieldGet(
+          redirect, box, builder.getTypeOfCapturedVariable(redirect));
       builder.add(lookup);
       return lookup;
     } else {
       assert(isUsedInTry(element));
       HLocalValue local = getLocal(element);
-      HInstruction variable = new HLocalGet(element, local);
+      HInstruction variable = new HLocalGet(
+          element, local, builder.backend.dynamicType);
       builder.add(variable);
       return variable;
     }
@@ -410,7 +413,8 @@
     if (element.isParameter()) return builder.parameters[element];
 
     return builder.activationVariables.putIfAbsent(element, () {
-      HLocalValue local = new HLocalValue(element);
+      JavaScriptBackend backend = builder.backend;
+      HLocalValue local = new HLocalValue(element, backend.nonNullType);
       builder.graph.entry.addAtExit(local);
       return local;
     });
@@ -507,12 +511,14 @@
     Map<Element, HInstruction> savedDirectLocals =
         new Map<Element, HInstruction>.from(directLocals);
 
+    JavaScriptBackend backend = builder.backend;
     // Create phis for all elements in the definitions environment.
     savedDirectLocals.forEach((Element element, HInstruction instruction) {
       if (isAccessedDirectly(element)) {
         // We know 'this' cannot be modified.
         if (!identical(element, closureData.thisElement)) {
-          HPhi phi = new HPhi.singleInput(element, instruction);
+          HPhi phi = new HPhi.singleInput(
+              element, instruction, backend.dynamicType);
           loopEntry.addPhi(phi);
           directLocals[element] = phi;
         } else {
@@ -574,6 +580,7 @@
     // true for nodes where we do joins.
     Map<Element, HInstruction> joinedLocals =
         new Map<Element, HInstruction>();
+    JavaScriptBackend backend = builder.backend;
     otherLocals.directLocals.forEach((element, instruction) {
       // We know 'this' cannot be modified.
       if (identical(element, closureData.thisElement)) {
@@ -585,8 +592,8 @@
         if (identical(instruction, mine)) {
           joinedLocals[element] = instruction;
         } else {
-          HInstruction phi =
-              new HPhi.manyInputs(element, <HInstruction>[mine, instruction]);
+          HInstruction phi = new HPhi.manyInputs(
+              element, <HInstruction>[mine, instruction], backend.dynamicType);
           joinBlock.addPhi(phi);
           joinedLocals[element] = phi;
         }
@@ -609,9 +616,10 @@
     Map<Element, HInstruction> joinedLocals =
         new Map<Element,HInstruction>();
     HInstruction thisValue = null;
+    JavaScriptBackend backend = builder.backend;
     directLocals.forEach((Element element, HInstruction instruction) {
       if (element != closureData.thisElement) {
-        HPhi phi = new HPhi.noInputs(element);
+        HPhi phi = new HPhi.noInputs(element, backend.dynamicType);
         joinedLocals[element] = phi;
         joinBlock.addPhi(phi);
       } else {
@@ -1047,7 +1055,8 @@
             () {
               HParameterValue parameter = parameters.values.first;
               push(new HIdentity(
-                  parameter, graph.addConstantNull(compiler)));
+                  parameter, graph.addConstantNull(compiler), null,
+                  backend.boolType));
             },
             () {
               closeAndGotoExit(new HReturn(
@@ -1113,9 +1122,9 @@
     return bodyElement;
   }
 
-  HParameterValue addParameter(Element element) {
+  HParameterValue addParameter(Element element, HType type) {
     assert(inliningStack.isEmpty);
-    HParameterValue result = new HParameterValue(element);
+    HParameterValue result = new HParameterValue(element, type);
     if (lastAddedParameter == null) {
       graph.entry.addBefore(graph.entry.first, result);
     } else {
@@ -1349,7 +1358,8 @@
           && !element.isGenerativeConstructorBody()
           && (selector.mask == null || selector.mask.isNullable)) {
         addWithPosition(
-            new HFieldGet(null, providedArguments[0], isAssignable: false),
+            new HFieldGet(null, providedArguments[0], backend.dynamicType,
+                          isAssignable: false),
             currentNode);
       }
       InliningState state = enterInlinedMethod(
@@ -1723,7 +1733,8 @@
       // Null guard ensures an error if we are being called from an explicit
       // 'new' of the constructor instead of via an upgrade. It is optimized out
       // if there are field initializers.
-      add(new HFieldGet(null, newObject, isAssignable: false));
+      add(new HFieldGet(
+          null, newObject, backend.dynamicType, isAssignable: false));
       for (int i = 0; i < fields.length; i++) {
         add(new HFieldSet(fields[i], newObject, constructorArguments[i]));
       }
@@ -1792,8 +1803,8 @@
           tryInlineMethod(body, null, bodyCallInputs, function)) {
         pop();
       } else {
-        HInvokeConstructorBody invoke =
-            new HInvokeConstructorBody(body.declaration, bodyCallInputs);
+        HInvokeConstructorBody invoke = new HInvokeConstructorBody(
+            body.declaration, bodyCallInputs, backend.nonNullType);
         invoke.sideEffects =
             compiler.world.getSideEffectsOfElement(constructor);
         add(invoke);
@@ -1830,7 +1841,8 @@
     if ((element.isConstructor() || element.isGenerativeConstructorBody())
         && backend.classNeedsRti(enclosing)) {
       enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
-        HParameterValue param = addParameter(typeVariable.element);
+        HParameterValue param = addParameter(
+            typeVariable.element, backend.nonNullType);
         localsHandler.directLocals[typeVariable.element] = param;
       });
     }
@@ -2008,7 +2020,7 @@
           compiler.boolClass.computeType(compiler),
           kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
     }
-    HInstruction result = new HBoolify(value);
+    HInstruction result = new HBoolify(value, backend.boolType);
     add(result);
     return result;
   }
@@ -2622,7 +2634,7 @@
   void visitLogicalNot(Send node) {
     assert(node.argumentsNode is Prefix);
     visit(node.receiver);
-    HNot not = new HNot(popBoolified());
+    HNot not = new HNot(popBoolified(), backend.boolType);
     pushWithPosition(not, node);
   }
 
@@ -2653,18 +2665,19 @@
                    Send send) {
     switch (op.source) {
       case "===":
-        pushWithPosition(new HIdentity(left, right), op);
+        pushWithPosition(
+            new HIdentity(left, right, null, backend.boolType), op);
         return;
       case "!==":
-        HIdentity eq = new HIdentity(left, right);
+        HIdentity eq = new HIdentity(left, right, null, backend.boolType);
         add(eq);
-        pushWithPosition(new HNot(eq), op);
+        pushWithPosition(new HNot(eq, backend.boolType), op);
         return;
     }
 
     pushInvokeDynamic(send, selector, [left, right], location: op);
     if (op.source == '!=') {
-      pushWithPosition(new HNot(popBoolified()), op);
+      pushWithPosition(new HNot(popBoolified(), backend.boolType), op);
     }
   }
 
@@ -2712,11 +2725,11 @@
         // handler in the case of lists, because the constant handler
         // does not look at elements in the list.
         HType type = new HType.inferredTypeForElement(element, compiler);
-        if (!type.isUnknown()) instruction.instructionType = type;
+        if (!type.containsAll(compiler)) instruction.instructionType = type;
       } else if (element.isField() && isLazilyInitialized(element)) {
-        HInstruction instruction = new HLazyStatic(element);
-        instruction.instructionType =
-            new HType.inferredTypeForElement(element, compiler);
+        HInstruction instruction = new HLazyStatic(
+            element,
+            new HType.inferredTypeForElement(element, compiler));
         push(instruction);
       } else {
         if (element.isGetter()) {
@@ -2724,9 +2737,9 @@
         } else {
           // TODO(5346): Try to avoid the need for calling [declaration] before
           // creating an [HStatic].
-          HInstruction instruction = new HStatic(element.declaration);
-          instruction.instructionType =
-              new HType.inferredTypeForElement(element, compiler);
+          HInstruction instruction = new HStatic(
+              element.declaration,
+              new HType.inferredTypeForElement(element, compiler));
           push(instruction);
         }
       }
@@ -2737,7 +2750,7 @@
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
       // TODO(5346): Try to avoid the need for calling [declaration] before
       // creating an [HStatic].
-      push(new HStatic(element.declaration));
+      push(new HStatic(element.declaration, backend.nonNullType));
       // TODO(ahe): This should be registered in codegen.
       compiler.enqueuer.codegen.registerGetOfStaticFunction(
           element.declaration);
@@ -2813,7 +2826,7 @@
   }
 
   HInstruction invokeInterceptor(HInstruction receiver) {
-    HInterceptor interceptor = new HInterceptor(receiver);
+    HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType);
     add(interceptor);
     return interceptor;
   }
@@ -2901,7 +2914,7 @@
     HInstruction instruction = buildIsNode(node, type, expression);
     if (isNot) {
       add(instruction);
-      instruction = new HNot(instruction);
+      instruction = new HNot(instruction, backend.boolType);
     }
     push(instruction);
   }
@@ -2921,7 +2934,8 @@
     if (type.kind == TypeKind.FUNCTION) {
       if (backend.rti.isSimpleFunctionType(type)) {
         // TODO(johnniwinther): Avoid interceptor if unneeded.
-        return new HIs.raw(type, expression, invokeInterceptor(expression));
+        return new HIs.raw(
+            type, expression, invokeInterceptor(expression), backend.boolType);
       }
       Element checkFunctionSubtype = backend.getCheckFunctionSubtype();
 
@@ -2957,16 +2971,16 @@
                                                  contextName,
                                                  context,
                                                  typeArguments];
-      pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN);
+      pushInvokeStatic(node, checkFunctionSubtype, inputs, backend.boolType);
       HInstruction call = pop();
-      return new HIs.compound(type, expression, call);
+      return new HIs.compound(type, expression, call, backend.boolType);
     } else if (type.kind == TypeKind.TYPE_VARIABLE) {
       HInstruction runtimeType = addTypeVariableReference(type);
       Element helper = backend.getCheckSubtypeOfRuntimeType();
       List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
-      pushInvokeStatic(null, helper, inputs, HType.BOOLEAN);
+      pushInvokeStatic(null, helper, inputs, backend.boolType);
       HInstruction call = pop();
-      return new HIs.variable(type, expression, call);
+      return new HIs.variable(type, expression, call, backend.boolType);
     } else if (RuntimeTypes.hasTypeArguments(type)) {
       ClassElement element = type.element;
       Element helper = backend.getCheckSubtype();
@@ -2983,15 +2997,16 @@
                                                  isFieldName,
                                                  representations,
                                                  asFieldName];
-      pushInvokeStatic(node, helper, inputs, HType.BOOLEAN);
+      pushInvokeStatic(node, helper, inputs, backend.boolType);
       HInstruction call = pop();
-      return new HIs.compound(type, expression, call);
+      return new HIs.compound(type, expression, call, backend.boolType);
     } else {
       if (backend.hasDirectCheckFor(type)) {
-        return new HIs.direct(type, expression);
+        return new HIs.direct(type, expression, backend.boolType);
       }
       // TODO(johnniwinther): Avoid interceptor if unneeded.
-      return new HIs.raw(type, expression, invokeInterceptor(expression));
+      return new HIs.raw(
+          type, expression, invokeInterceptor(expression), backend.boolType);
     }
   }
 
@@ -3100,7 +3115,9 @@
     inputs.add(closureTarget);
     addDynamicSendArgumentsToList(node, inputs);
     Selector closureSelector = new Selector.callClosureFrom(selector);
-    pushWithPosition(new HInvokeClosure(closureSelector, inputs), node);
+    pushWithPosition(
+        new HInvokeClosure(closureSelector, inputs, backend.dynamicType),
+        node);
   }
 
   void handleForeignJs(Send node) {
@@ -3136,7 +3153,7 @@
       // to fetch the current isolate.
       String name = backend.namer.CURRENT_ISOLATE;
       push(new HForeign(new js.LiteralString(name),
-                        HType.UNKNOWN,
+                        backend.dynamicType,
                         <HInstruction>[]));
     } else {
       // Call a helper method from the isolate library. The isolate
@@ -3147,7 +3164,7 @@
         compiler.cancel(
             'Isolate library and compiler mismatch', node: node);
       }
-      pushInvokeStatic(null, element, [], HType.UNKNOWN);
+      pushInvokeStatic(null, element, [], backend.dynamicType);
     }
   }
 
@@ -3184,6 +3201,29 @@
                 argument, string.dartString.slowToString())));
   }
 
+  void handleJsInterceptorConstant(Send node) {
+    // Single argument must be a TypeConstant which is converted into a
+    // InterceptorConstant.
+    if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) {
+      Node argument = node.arguments.head;
+      visit(argument);
+      HInstruction argumentInstruction = pop();
+      if (argumentInstruction is HConstant) {
+        Constant argumentConstant = argumentInstruction.constant;
+        if (argumentConstant is TypeConstant) {
+          Constant constant =
+              new InterceptorConstant(argumentConstant.representedType);
+          HInstruction instruction = graph.addConstant(constant, compiler);
+          stack.add(instruction);
+          return;
+        }
+      }
+    }
+    compiler.reportError(node,
+        MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
+    stack.add(graph.addConstantNull(compiler));
+  }
+
   void handleForeignJsCallInIsolate(Send node) {
     Link<Node> link = node.arguments;
     if (!compiler.hasIsolateSupport()) {
@@ -3191,7 +3231,9 @@
       // closure.
       visit(link.tail.head);
       Selector selector = new Selector.callClosure(0);
-      push(new HInvokeClosure(selector, <HInstruction>[pop()]));
+      push(new HInvokeClosure(selector,
+                              <HInstruction>[pop()],
+                              backend.dynamicType));
     } else {
       // Call a helper method from the isolate library.
       Element element = compiler.isolateHelperLibrary.find('_callInIsolate');
@@ -3201,7 +3243,7 @@
       }
       List<HInstruction> inputs = <HInstruction>[];
       addGenericSendArgumentsToList(link, inputs);
-      pushInvokeStatic(node, element, inputs, HType.UNKNOWN);
+      pushInvokeStatic(node, element, inputs, backend.dynamicType);
     }
   }
 
@@ -3238,7 +3280,7 @@
     String invocationName = backend.namer.invocationName(
         new Selector.callClosure(params.requiredParameterCount));
     push(new HForeign(js.js('#.$invocationName'),
-                      HType.UNKNOWN,
+                      backend.dynamicType,
                       inputs));
   }
 
@@ -3252,7 +3294,7 @@
     SideEffects sideEffects = new SideEffects.empty();
     sideEffects.setAllSideEffects();
     push(new HForeign(js.js("$isolateName = #"),
-                      HType.UNKNOWN,
+                      backend.dynamicType,
                       <HInstruction>[pop()],
                       effects: sideEffects));
   }
@@ -3264,7 +3306,7 @@
     }
     String constructorName = backend.namer.isolateName;
     push(new HForeign(js.js("new $constructorName()"),
-                      HType.UNKNOWN,
+                      backend.dynamicType,
                       <HInstruction>[]));
   }
 
@@ -3274,7 +3316,7 @@
     }
     String jsClassReference = backend.namer.isolateAccess(compiler.objectClass);
     push(new HForeign(new js.LiteralString(jsClassReference),
-                      HType.UNKNOWN,
+                      backend.dynamicType,
                       <HInstruction>[]));
   }
 
@@ -3283,7 +3325,7 @@
       compiler.cancel('Too many arguments', node: node.argumentsNode);
     }
     push(new HForeign(new js.LiteralString(backend.namer.CURRENT_ISOLATE),
-                      HType.UNKNOWN,
+                      backend.dynamicType,
                       <HInstruction>[]));
   }
 
@@ -3351,6 +3393,8 @@
       handleForeignJsGetName(node);
     } else if (name == 'JS_EFFECT') {
       stack.add(graph.addConstantNull(compiler));
+    } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
+      handleJsInterceptorConstant(node);
     } else {
       throw "Unknown foreign: ${selector}";
     }
@@ -3363,12 +3407,13 @@
 
     ClassElement cls = currentNonClosureClass;
     Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD);
-    if (element.enclosingElement.declaration != compiler.objectClass) {
+    if (compiler.enabledInvokeOn
+        && element.enclosingElement.declaration != compiler.objectClass) {
       // Register the call as dynamic if [noSuchMethod] on the super
       // class is _not_ the default implementation from [Object], in
       // case the [noSuchMethod] implementation calls
       // [JSInvocationMirror._invokeOn].
-      compiler.enqueuer.codegen.registerSelectorUse(selector);
+      compiler.enqueuer.codegen.registerSelectorUse(selector.asUntyped);
     }
     String publicName = name;
     if (selector.isSetter()) publicName += '=';
@@ -3404,7 +3449,7 @@
                       graph.addConstant(kindConstant, compiler),
                       argumentsInstruction,
                       argumentNamesInstruction],
-                      HType.UNKNOWN);
+                      backend.dynamicType);
 
     var inputs = <HInstruction>[pop()];
     push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs));
@@ -3452,7 +3497,7 @@
       inputs = <HInstruction>[target];
       addDynamicSendArgumentsToList(node, inputs);
       Selector closureSelector = new Selector.callClosureFrom(selector);
-      push(new HInvokeClosure(closureSelector, inputs));
+      push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType));
     }
   }
 
@@ -3478,7 +3523,7 @@
                      [target,
                       substitutionName,
                       graph.addConstantInt(index, compiler)],
-                      HType.UNKNOWN);
+                      backend.dynamicType);
     return pop();
   }
 
@@ -3584,7 +3629,7 @@
         null,
         typeInfoSetterElement,
         <HInstruction>[newObject, typeInfo],
-        HType.UNKNOWN);
+        backend.dynamicType);
     pop();
   }
 
@@ -3600,13 +3645,17 @@
         isListConstructor = true;
         HType inferred =
             new HType.inferredForNode(currentElement, send, compiler);
-        return inferred.isUnknown() ? backend.fixedArrayType : inferred;
+        return inferred.containsAll(compiler)
+            ? backend.fixedArrayType
+            : inferred;
       } else if (Elements.isGrowableListConstructorCall(
                     originalElement, send, compiler)) {
         isListConstructor = true;
         HType inferred =
             new HType.inferredForNode(currentElement, send, compiler);
-        return inferred.isUnknown() ? backend.extendableArrayType : inferred;
+        return inferred.containsAll(compiler)
+            ? backend.extendableArrayType
+            : inferred;
       } else if (element.isGenerativeConstructor()) {
         ClassElement cls = element.getEnclosingClass();
         return new HType.nonNullExact(cls.thisType.element, compiler);
@@ -3732,7 +3781,8 @@
       }
 
       if (element == compiler.identicalFunction) {
-        pushWithPosition(new HIdentity(inputs[0], inputs[1]), node);
+        pushWithPosition(
+            new HIdentity(inputs[0], inputs[1], null, backend.boolType), node);
         return;
       }
 
@@ -3742,7 +3792,9 @@
       List<HInstruction> inputs = <HInstruction>[pop()];
       addDynamicSendArgumentsToList(node, inputs);
       Selector closureSelector = new Selector.callClosureFrom(selector);
-      pushWithPosition(new HInvokeClosure(closureSelector, inputs), node);
+      pushWithPosition(
+          new HInvokeClosure(closureSelector, inputs, backend.dynamicType),
+          node);
     }
   }
 
@@ -3786,7 +3838,7 @@
       List<HInstruction> inputs = <HInstruction>[target];
       addDynamicSendArgumentsToList(node, inputs);
       Selector closureSelector = new Selector.callClosureFrom(selector);
-      push(new HInvokeClosure(closureSelector, inputs));
+      push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType));
     }
   }
 
@@ -3965,19 +4017,20 @@
       inputs.add(invokeInterceptor(receiver));
     }
     inputs.addAll(arguments);
+    HType type = new HType.inferredTypeForSelector(selector, compiler);
     if (selector.isGetter()) {
       bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
       pushWithPosition(
-          new HInvokeDynamicGetter(selector, null, inputs, !hasGetter),
+          new HInvokeDynamicGetter(selector, null, inputs, type, !hasGetter),
           location);
     } else if (selector.isSetter()) {
       bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
       pushWithPosition(
-          new HInvokeDynamicSetter(selector, null, inputs, !hasSetter),
+          new HInvokeDynamicSetter(selector, null, inputs, type, !hasSetter),
           location);
     } else {
       pushWithPosition(
-          new HInvokeDynamicMethod(selector, inputs, isIntercepted),
+          new HInvokeDynamicMethod(selector, inputs, type, isIntercepted),
           location);
     }
   }
@@ -4021,19 +4074,19 @@
     }
     inputs.add(receiver);
     inputs.addAll(arguments);
+    HType type;
+    if (!element.isGetter() && selector.isGetter()) {
+      type = new HType.inferredTypeForElement(element, compiler);
+    } else {
+      type = new HType.inferredReturnTypeForElement(element, compiler);
+    }
     HInstruction instruction = new HInvokeSuper(
         element,
         currentNonClosureClass,
         selector,
         inputs,
+        type,
         isSetter: selector.isSetter() || selector.isIndexSet());
-    if (!element.isGetter() && selector.isGetter()) {
-      instruction.instructionType =
-          new HType.inferredTypeForElement(element, compiler);
-    } else {
-      instruction.instructionType =
-          new HType.inferredReturnTypeForElement(element, compiler);
-    }
     instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
     return instruction;
   }
@@ -4384,7 +4437,7 @@
     }
 
     HType type = new HType.inferredForNode(currentElement, node, compiler);
-    if (!type.isUnknown()) instruction.instructionType = type;
+    if (!type.containsAll(compiler)) instruction.instructionType = type;
     stack.add(instruction);
   }
 
@@ -4809,7 +4862,7 @@
       void buildCondition() {
         js.Expression code = js.js.parseForeignJS('#');
         push(createForeign(code,
-                           HType.BOOLEAN,
+                           backend.boolType,
                            [localsHandler.readLocal(switchTarget)]));
       }
       handleIf(node, buildCondition, buildLoop, () => {});
@@ -5009,7 +5062,7 @@
       Element element = new ElementX('exception',
                                      ElementKind.PARAMETER,
                                      currentElement);
-      exception = new HLocalValue(element);
+      exception = new HLocalValue(element, backend.nonNullType);
       add(exception);
       HInstruction oldRethrowableException = rethrowableException;
       rethrowableException = exception;
@@ -5494,7 +5547,7 @@
       boolifiedLeft = builder.popBoolified();
       builder.stack.add(boolifiedLeft);
       if (!isAnd) {
-        builder.push(new HNot(builder.pop()));
+        builder.push(new HNot(builder.pop(), builder.backend.boolType));
       }
     }
 
@@ -5506,8 +5559,10 @@
     handleIf(visitCondition, visitThen, null);
     HConstant notIsAnd =
         builder.graph.addConstantBool(!isAnd, builder.compiler);
+    JavaScriptBackend backend = builder.backend;
     HPhi result = new HPhi.manyInputs(null,
-                                      <HInstruction>[boolifiedRight, notIsAnd]);
+                                      <HInstruction>[boolifiedRight, notIsAnd],
+                                      backend.dynamicType);
     builder.current.addPhi(result);
     builder.stack.add(result);
   }
@@ -5566,8 +5621,9 @@
 
     if (isExpression) {
       assert(thenValue != null && elseValue != null);
-      HPhi phi =
-          new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]);
+      JavaScriptBackend backend = builder.backend;
+      HPhi phi = new HPhi.manyInputs(
+          null, <HInstruction>[thenValue, elseValue], backend.dynamicType);
       joinBranch.block.addPhi(phi);
       builder.stack.add(phi);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 392350c..017889f 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -80,9 +80,9 @@
 
   js.Expression generateMethod(CodegenWorkItem work, HGraph graph) {
     return measure(() {
-      compiler.tracer.traceGraph("codegen", graph);
       SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
       codegen.visitGraph(graph);
+      compiler.tracer.traceGraph("codegen", graph);
       FunctionElement element = work.element;
       return buildJavaScriptFunction(element, codegen.parameters, codegen.body);
     });
@@ -278,10 +278,8 @@
     return jsNode;
   }
 
-  beginGraph(HGraph graph);
-  endGraph(HGraph graph);
-
   void preGenerateMethod(HGraph graph) {
+    new SsaTypeKnownRemover().visitGraph(graph);
     new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph);
     new SsaConditionMerger(
         generateAtUseSite, controlFlowOperators).visitGraph(graph);
@@ -1543,13 +1541,9 @@
           compiler);
       return receiverType.refine(selector, compiler);
     }
-    // If [JSInvocationMirror._invokeOn] has been called, we must not create a
-    // typed selector based on the receiver type.
-    if (backend.compiler.enabledInvokeOn) {
-      return selector.asUntyped;
-    }
-    HType receiverType = node.getDartReceiver(compiler).instructionType;
-    return receiverType.refine(selector, compiler);
+    // If [JSInvocationMirror._invokeOn] is enabled, and this call
+    // might hit a `noSuchMethod`, we register an untyped selector.
+    return selector.extendIfReachesAll(compiler);
   }
 
   void registerMethodInvoke(HInvokeDynamic node) {
@@ -1836,15 +1830,13 @@
 
       HInstruction left = relational.left;
       HInstruction right = relational.right;
-      if (left.instructionType.isUseful() && left.isString(compiler) &&
-          right.instructionType.isUseful() && right.isString(compiler)) {
+      if (left.isString(compiler) && right.isString(compiler)) {
         return true;
       }
 
       // This optimization doesn't work for NaN, so we only do it if the
       // type is known to be an integer.
-      return left.instructionType.isUseful() && left.isInteger()
-          && right.instructionType.isUseful() && right.isInteger();
+      return left.isInteger(compiler) && right.isInteger(compiler);
     }
 
     bool handledBySpecialCase = false;
@@ -1964,13 +1956,13 @@
       js.Expression over;
       if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) {
         use(node.index);
-        if (node.index.isInteger()) {
+        if (node.index.isInteger(compiler)) {
           under = js.js("# < 0", pop());
         } else {
           js.Expression jsIndex = pop();
           under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]);
         }
-      } else if (!node.index.isInteger()) {
+      } else if (!node.index.isInteger(compiler)) {
         checkInt(node.index, '!==');
         under = pop();
       }
@@ -2081,7 +2073,7 @@
     HInstruction input = node.inputs.first;
     if (input.isString(compiler)) {
       use(input);
-    } else if (input.isInteger() || input.isBoolean()) {
+    } else if (input.isInteger(compiler) || input.isBoolean(compiler)) {
       // JavaScript's + operator with a string for the left operand will convert
       // the right operand to a string, and the conversion result is correct.
       use(input);
@@ -2443,24 +2435,25 @@
     // V8 generally prefers 'typeof' checks, but for integers and
     // indexable primitives we cannot compile this test into a single
     // typeof check so the null check is cheaper.
-    bool turnIntoNumCheck = input.isIntegerOrNull() && checkedType.isInteger();
+    bool turnIntoNumCheck = input.isIntegerOrNull(compiler)
+        && checkedType.isInteger(compiler);
     bool turnIntoNullCheck = !turnIntoNumCheck
         && (mask.nullable() == receiver)
-        && (checkedType.isInteger()
+        && (checkedType.isInteger(compiler)
             || checkedType.isIndexablePrimitive(compiler));
     js.Expression test;
     if (turnIntoNullCheck) {
       use(input);
       test = new js.Binary("==", pop(), new js.LiteralNull());
-    } else if (checkedType.isInteger() && !turnIntoNumCheck) {
+    } else if (checkedType.isInteger(compiler) && !turnIntoNumCheck) {
       // input is !int
       checkInt(input, '!==');
       test = pop();
-    } else if (checkedType.isNumber() || turnIntoNumCheck) {
+    } else if (checkedType.isNumber(compiler) || turnIntoNumCheck) {
       // input is !num
       checkNum(input, '!==');
       test = pop();
-    } else if (checkedType.isBoolean()) {
+    } else if (checkedType.isBoolean(compiler)) {
       // input is !bool
       checkBool(input, '!==');
       test = pop();
@@ -2531,8 +2524,8 @@
     if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
       // An int check if the input is not int or null, is not
       // sufficient for doing a argument or receiver check.
-      assert(!node.checkedType.isInteger() ||
-          node.checkedInput.isIntegerOrNull());
+      assert(!node.checkedType.isInteger(compiler) ||
+          node.checkedInput.isIntegerOrNull(compiler));
       js.Expression test = generateTest(node.checkedInput, node.checkedType);
       js.Block oldContainer = currentContainer;
       js.Statement body = new js.Block.empty();
@@ -2577,7 +2570,8 @@
   }
 
   void visitTypeKnown(HTypeKnown node) {
-    use(node.checkedInput);
+    // [HTypeKnown] instructions are removed before generating code.
+    assert(false);
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
index a476a1e..8a72f49 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
@@ -5,6 +5,31 @@
 part of ssa;
 
 /**
+ * Remove [HTypeKnown] instructions from the graph, to make codegen
+ * analysis easier.
+ */
+class SsaTypeKnownRemover extends HBaseVisitor {
+
+  void visitGraph(HGraph graph) {
+    visitDominatorTree(graph);
+  }
+
+  void visitBasicBlock(HBasicBlock block) {
+    HInstruction instruction = block.first;
+    while (instruction != null) {
+      HInstruction next = instruction.next;
+      instruction.accept(this);
+      instruction = next;
+    }
+  }
+
+  void visitTypeKnown(HTypeKnown instruction) {
+    instruction.block.rewrite(instruction, instruction.checkedInput);
+    instruction.block.remove(instruction);
+  }
+}
+
+/**
  * Instead of emitting each SSA instruction with a temporary variable
  * mark instructions that can be emitted at their use-site.
  * For example, in:
@@ -119,7 +144,8 @@
   }
 
   void visitTypeKnown(HTypeKnown instruction) {
-    markAsGenerateAtUseSite(instruction);
+    // [HTypeKnown] instructions are removed before code generation.
+    assert(false);
   }
 
   void tryGenerateAtUseSite(HInstruction instruction) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index ae9f7e3..0f89282 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -107,17 +107,17 @@
       if (type.isNull()) {
         constantInterceptor = backend.jsNullClass;
       }
-    } else if (type.isInteger()) {
+    } else if (type.isInteger(compiler)) {
       constantInterceptor = backend.jsIntClass;
-    } else if (type.isDouble()) {
+    } else if (type.isDouble(compiler)) {
       constantInterceptor = backend.jsDoubleClass;
-    } else if (type.isBoolean()) {
+    } else if (type.isBoolean(compiler)) {
       constantInterceptor = backend.jsBoolClass;
     } else if (type.isString(compiler)) {
       constantInterceptor = backend.jsStringClass;
     } else if (type.isArray(compiler)) {
       constantInterceptor = backend.jsArrayClass;
-    } else if (type.isNumber()
+    } else if (type.isNumber(compiler)
         && !interceptedClasses.contains(backend.jsIntClass)
         && !interceptedClasses.contains(backend.jsDoubleClass)) {
       // If the method being intercepted is not defined in [int] or [double] we
@@ -246,10 +246,9 @@
     List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
     inputs[0] = nullConstant;
     HOneShotInterceptor interceptor = new HOneShotInterceptor(
-        user.selector, inputs, node.interceptedClasses);
+        user.selector, inputs, user.instructionType, node.interceptedClasses);
     interceptor.sourcePosition = user.sourcePosition;
     interceptor.sourceElement = user.sourceElement;
-    interceptor.instructionType = user.instructionType;
 
     HBasicBlock block = user.block;
     block.addAfter(user, interceptor);
@@ -273,17 +272,20 @@
           selector,
           node.element,
           <HInstruction>[constant, node.inputs[1]],
+          node.instructionType,
           false);
     } else if (node.selector.isSetter()) {
       instruction = new HInvokeDynamicSetter(
           selector,
           node.element,
           <HInstruction>[constant, node.inputs[1], node.inputs[2]],
+          node.instructionType,
           false);
     } else {
       List<HInstruction> inputs = new List<HInstruction>.from(node.inputs);
       inputs[0] = constant;
-      instruction = new HInvokeDynamicMethod(selector, inputs, true);
+      instruction = new HInvokeDynamicMethod(
+          selector, inputs, node.instructionType, true);
     }
 
     HBasicBlock block = node.block;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
index 67768a8..d2e54d0 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -15,16 +15,15 @@
 
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
-    HType receiverType = instruction.getDartReceiver(compiler).instructionType;
-    Selector refined = receiverType.refine(instruction.selector, compiler);
-    HType type = new HType.inferredTypeForSelector(refined, compiler);
+    Selector selector = instruction.selector;
+    HType type = new HType.inferredTypeForSelector(selector, compiler);
     // TODO(ngeoffray): Because we don't know yet the side effects of
     // a JS call, we sometimes know more in the compiler about the
     // side effects of an element (for example operator% on the int
     // class). We should remove this check once we analyze JS calls.
     if (!instruction.useGvn()) {
       instruction.sideEffects =
-          compiler.world.getSideEffectsOfSelector(refined);
+          compiler.world.getSideEffectsOfSelector(selector);
     }
     return type;
   }
@@ -90,7 +89,8 @@
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     if (instruction.inputs[1].isMutableIndexable(compiler)) {
-      if (!instruction.inputs[2].isInteger() && compiler.enableTypeAssertions) {
+      if (!instruction.inputs[2].isInteger(compiler)
+          && compiler.enableTypeAssertions) {
         // We want the right checked mode error.
         return null;
       }
@@ -109,17 +109,17 @@
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     if (!instruction.inputs[1].isIndexable(compiler)) return null;
-    if (!instruction.inputs[2].isInteger() && compiler.enableTypeAssertions) {
+    if (!instruction.inputs[2].isInteger(compiler)
+        && compiler.enableTypeAssertions) {
       // We want the right checked mode error.
       return null;
     }
-    HInstruction index = new HIndex(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
     HType receiverType = instruction.getDartReceiver(compiler).instructionType;
     Selector refined = receiverType.refine(instruction.selector, compiler);
     HType type = new HType.inferredTypeForSelector(refined, compiler);
-    index.instructionType = type;
-    return index;
+    return new HIndex(
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, type);
   }
 }
 
@@ -134,14 +134,20 @@
                                   Compiler compiler) {
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
-    if (instruction.inputs[1].isPrimitiveOrNull(compiler)) return HType.INTEGER;
+    JavaScriptBackend backend = compiler.backend;
+    if (instruction.inputs[1].isPrimitiveOrNull(compiler)) {
+      return backend.intType;
+    }
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     HInstruction input = instruction.inputs[1];
-    if (input.isNumber()) return new HBitNot(input, instruction.selector);
+    if (input.isNumber(compiler)) {
+      return new HBitNot(input, instruction.selector, backend.intType);
+    }
     return null;
   }
 }
@@ -156,14 +162,16 @@
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
     HType operandType = instruction.inputs[1].instructionType;
-    if (operandType.isNumberOrNull()) return operandType;
+    if (operandType.isNumberOrNull(compiler)) return operandType;
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     HInstruction input = instruction.inputs[1];
-    if (input.isNumber()) return new HNegate(input, instruction.selector);
+    if (input.isNumber(compiler)) {
+      return new HNegate(input, instruction.selector, input.instructionType);
+    }
     return null;
   }
 }
@@ -175,23 +183,28 @@
                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
-    if (left.isIntegerOrNull() && right.isIntegerOrNull()) return HType.INTEGER;
-    if (left.isNumberOrNull()) {
-      if (left.isDoubleOrNull() || right.isDoubleOrNull()) return HType.DOUBLE;
-      return HType.NUMBER;
+    JavaScriptBackend backend = compiler.backend;
+    if (left.isIntegerOrNull(compiler) && right.isIntegerOrNull(compiler)) {
+      return backend.intType;
+    }
+    if (left.isNumberOrNull(compiler)) {
+      if (left.isDoubleOrNull(compiler) || right.isDoubleOrNull(compiler)) {
+        return backend.doubleType;
+      }
+      return backend.numType;
     }
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
-  bool isBuiltin(HInvokeDynamic instruction) {
-    return instruction.inputs[1].isNumber()
-        && instruction.inputs[2].isNumber();
+  bool isBuiltin(HInvokeDynamic instruction, Compiler compiler) {
+    return instruction.inputs[1].isNumber(compiler)
+        && instruction.inputs[2].isNumber(compiler);
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
-    if (isBuiltin(instruction)) {
-      HInstruction builtin = newBuiltinVariant(instruction);
+    if (isBuiltin(instruction, compiler)) {
+      HInstruction builtin = newBuiltinVariant(instruction, compiler);
       if (builtin != null) return builtin;
       // Even if there is no builtin equivalent instruction, we know
       // the instruction does not have any side effect, and that it
@@ -203,7 +216,7 @@
     return null;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction);
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
 }
 
 class AddSpecializer extends BinaryArithmeticSpecializer {
@@ -213,9 +226,11 @@
     return constantSystem.add;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
     return new HAdd(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, computeTypeFromInputTypes(instruction, compiler));
   }
 }
 
@@ -229,13 +244,19 @@
   HType computeTypeFromInputTypes(HInstruction instruction,
                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
-    if (left.isNumberOrNull()) return HType.DOUBLE;
+    JavaScriptBackend backend = compiler.backend;
+    if (left.isNumberOrNull(compiler)) {
+      return backend.doubleType;
+    }
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HDivide(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.doubleType);
   }
 }
 
@@ -246,7 +267,8 @@
     return constantSystem.modulo;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
     // Modulo cannot be mapped to the native operator (different semantics).
     return null;
   }
@@ -259,9 +281,11 @@
     return constantSystem.multiply;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
     return new HMultiply(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, computeTypeFromInputTypes(instruction, compiler));
   }
 }
 
@@ -272,9 +296,11 @@
     return constantSystem.subtract;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
     return new HSubtract(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, computeTypeFromInputTypes(instruction, compiler));
   }
 }
 
@@ -285,7 +311,8 @@
     return constantSystem.truncatingDivide;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
     // Truncating divide does not have a JS equivalent.    
     return null;
   }
@@ -299,7 +326,10 @@
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
     HInstruction left = instruction.inputs[1];
-    if (left.isPrimitiveOrNull(compiler)) return HType.INTEGER;
+    JavaScriptBackend backend = compiler.backend;
+    if (left.isPrimitiveOrNull(compiler)) {
+      return backend.intType;
+    }
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 }
@@ -315,16 +345,19 @@
                                    Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
-    if (!left.isNumber()) return null;
+    if (!left.isNumber(compiler)) return null;
     if (argumentLessThan32(right)) {
-      return newBuiltinVariant(instruction);
+      return newBuiltinVariant(instruction, compiler);
     }
     return null;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HShiftLeft(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.intType);
   }
 
   bool argumentLessThan32(HInstruction instruction) {
@@ -339,7 +372,8 @@
 class ShiftRightSpecializer extends BinaryBitOpSpecializer {
   const ShiftRightSpecializer();
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
     // Shift right cannot be mapped to the native operator easily.    
     return null;
   }
@@ -356,9 +390,12 @@
     return constantSystem.bitOr;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HBitOr(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.intType);
   }
 }
 
@@ -369,9 +406,12 @@
     return constantSystem.bitAnd;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HBitAnd(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.intType);
   }
 }
 
@@ -382,9 +422,12 @@
     return constantSystem.bitXor;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HBitXor(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.intType);
   }
 }
 
@@ -393,8 +436,9 @@
 
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     if (instruction.inputs[1].instructionType.isPrimitiveOrNull(compiler)) {
-      return HType.BOOLEAN;
+      return backend.boolType;
     }
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
@@ -403,13 +447,13 @@
                                    Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
-    if (left.isNumber() && right.isNumber()) {
-      return newBuiltinVariant(instruction);
+    if (left.isNumber(compiler) && right.isNumber(compiler)) {
+      return newBuiltinVariant(instruction, compiler);
     }
     return null;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction);
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
 }
 
 class EqualsSpecializer extends RelationalSpecializer {
@@ -421,7 +465,7 @@
     HInstruction right = instruction.inputs[2];
     HType instructionType = left.instructionType;
     if (right.isConstantNull() || instructionType.isPrimitiveOrNull(compiler)) {
-      return newBuiltinVariant(instruction);
+      return newBuiltinVariant(instruction, compiler);
     }
     Selector selector = instructionType.refine(instruction.selector, compiler);
     World world = compiler.world;
@@ -431,7 +475,7 @@
     // implemented because if the selector matches by subtype, it still will be
     // a regular object or an interceptor.
     if (matches.every(backend.isDefaultEqualityImplementation)) {
-      return newBuiltinVariant(instruction);
+      return newBuiltinVariant(instruction, compiler);
     }
     return null;
   }
@@ -440,9 +484,12 @@
     return constantSystem.equal;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HIdentity(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.boolType);
   }
 }
 
@@ -453,9 +500,12 @@
     return constantSystem.less;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HLess(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.boolType);
   }
 }
 
@@ -466,9 +516,12 @@
     return constantSystem.greater;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HGreater(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.boolType);
   }
 }
 
@@ -479,9 +532,12 @@
     return constantSystem.greaterEqual;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HGreaterEqual(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.boolType);
   }
 }
 
@@ -492,8 +548,11 @@
     return constantSystem.lessEqual;
   }
 
-  HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+  HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+                                 Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     return new HLessEqual(
-        instruction.inputs[1], instruction.inputs[2], instruction.selector);
+        instruction.inputs[1], instruction.inputs[2],
+        instruction.selector, backend.boolType);
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index c72124e..3282eb0 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -163,17 +163,20 @@
 
   static HType mapConstantTypeToSsaType(Constant constant, Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
-    if (constant.isNull()) return HType.NULL;
-    if (constant.isBool()) return HType.BOOLEAN;
-    if (constant.isInt()) return HType.INTEGER;
-    if (constant.isDouble()) return HType.DOUBLE;
+    if (constant.isNull()) return backend.nullType;
+    if (constant.isBool()) return backend.boolType;
+    if (constant.isInt()) return backend.intType;
+    if (constant.isDouble()) return backend.doubleType;
     if (constant.isString()) return backend.stringType;
     if (constant.isList()) return backend.readableArrayType;
-    if (constant.isFunction()) return HType.UNKNOWN;
-    if (constant.isSentinel()) return HType.UNKNOWN;
+    if (constant.isFunction()) return backend.nonNullType;
+    if (constant.isSentinel()) return backend.nonNullType;
     // TODO(sra): What is the type of the prototype of an interceptor?
-    if (constant.isInterceptor()) return HType.UNKNOWN;
+    if (constant.isInterceptor()) return backend.nonNullType;
     ObjectConstant objectConstant = constant;
+    if (backend.isInterceptorClass(objectConstant.type.element)) {
+      return backend.nonNullType;
+    }
     TypeMask mask = new TypeMask.nonNullExact(objectConstant.type.element);
     return new HBoundedType(mask);
   }
@@ -749,6 +752,7 @@
   }
 }
 
+const HType EMPTY_TYPE = const HBoundedType(const TypeMask.nonNullEmpty());
 
 abstract class HInstruction implements Spannable {
   Element sourceElement;
@@ -800,7 +804,8 @@
   static const int IS_TYPECODE = 28;
   static const int INVOKE_DYNAMIC_TYPECODE = 29;
 
-  HInstruction(this.inputs) : id = idCounter++, usedBy = <HInstruction>[] {
+  HInstruction(this.inputs, this.instructionType)
+      : id = idCounter++, usedBy = <HInstruction>[] {
     assert(inputs.every((e) => e != null));
   }
 
@@ -852,13 +857,20 @@
       instructionType.isPrimitive(compiler);
   bool isPrimitiveOrNull(Compiler compiler) =>
       instructionType.isPrimitiveOrNull(compiler);
-  bool isBoolean() => instructionType.isBoolean();
-  bool isInteger() => instructionType.isInteger();
-  bool isIntegerOrNull() => instructionType.isIntegerOrNull();
-  bool isDouble() => instructionType.isDouble();
-  bool isDoubleOrNull() => instructionType.isDoubleOrNull();
-  bool isNumber() => instructionType.isNumber();
-  bool isNumberOrNull() => instructionType.isNumberOrNull();
+  bool isBoolean(Compiler compiler) =>
+      instructionType.isBoolean(compiler);
+  bool isInteger(Compiler compiler) =>
+      instructionType.isInteger(compiler);
+  bool isIntegerOrNull(Compiler compiler) =>
+      instructionType.isIntegerOrNull(compiler);
+  bool isDouble(Compiler compiler) =>
+      instructionType.isDouble(compiler);
+  bool isDoubleOrNull(Compiler compiler) =>
+      instructionType.isDoubleOrNull(compiler);
+  bool isNumber(Compiler compiler) =>
+      instructionType.isNumber(compiler);
+  bool isNumberOrNull(Compiler compiler) =>
+      instructionType.isNumberOrNull(compiler);
   bool isNull() => instructionType.isNull();
   bool canBeNull() => instructionType.canBeNull();
   bool canBePrimitive(Compiler compiler) =>
@@ -878,7 +890,7 @@
   /**
    * Type of the unstruction.
    */
-  HType instructionType = HType.UNKNOWN;
+  HType instructionType;
 
   Selector get selector => null;
   HInstruction getDartReceiver(Compiler compiler) => null;
@@ -1119,11 +1131,12 @@
     // The type element is either a class or the void element.
     Element element = type.element;
     if (identical(element, compiler.objectClass)) return this;
+    JavaScriptBackend backend = compiler.backend;
     if (type.kind != TypeKind.INTERFACE) {
-      return new HTypeConversion(type, kind, HType.UNKNOWN, this);
+      return new HTypeConversion(type, kind, backend.dynamicType, this);
     } else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
       // Boolean conversion checks work on non-nullable booleans.
-      return new HTypeConversion(type, kind, HType.BOOLEAN, this);
+      return new HTypeConversion(type, kind, backend.boolType, this);
     } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) {
       throw 'creating compound check to $type (this = ${this})';
     } else {
@@ -1142,9 +1155,9 @@
 }
 
 class HBoolify extends HInstruction {
-  HBoolify(HInstruction value) : super(<HInstruction>[value]) {
+  HBoolify(HInstruction value, HType type)
+      : super(<HInstruction>[value], type) {
     setUseGvn();
-    instructionType = HType.BOOLEAN;
   }
 
   accept(HVisitor visitor) => visitor.visitBoolify(this);
@@ -1161,7 +1174,7 @@
  * instruction itself.
  */
 abstract class HCheck extends HInstruction {
-  HCheck(inputs) : super(inputs) {
+  HCheck(inputs, type) : super(inputs, type) {
     setUseGvn();
   }
   HInstruction get checkedInput => inputs[0];
@@ -1183,10 +1196,8 @@
    */
   int staticChecks = FULL_CHECK;
 
-  HBoundsCheck(length, index, array)
-      : super(<HInstruction>[length, index, array]) {
-    instructionType = HType.INTEGER;
-  }
+  HBoundsCheck(length, index, array, type)
+      : super(<HInstruction>[length, index, array], type);
 
   HInstruction get length => inputs[1];
   HInstruction get index => inputs[0];
@@ -1207,7 +1218,7 @@
 }
 
 abstract class HControlFlow extends HInstruction {
-  HControlFlow(inputs) : super(inputs);
+  HControlFlow(inputs) : super(inputs, EMPTY_TYPE);
   bool isControlFlow() => true;
   bool isJsStatement() => true;
 }
@@ -1218,7 +1229,7 @@
     * the receiver of a method-call. The remaining inputs are the arguments
     * to the invocation.
     */
-  HInvoke(List<HInstruction> inputs) : super(inputs) {
+  HInvoke(List<HInstruction> inputs, type) : super(inputs, type) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
   }
@@ -1238,14 +1249,15 @@
 
 abstract class HInvokeDynamic extends HInvoke {
   final InvokeDynamicSpecializer specializer;
-  final Selector selector;
+  Selector selector;
   Element element;
 
   HInvokeDynamic(Selector selector,
                  this.element,
                  List<HInstruction> inputs,
+                 HType type,
                  [bool isIntercepted = false])
-    : super(inputs),
+    : super(inputs, type),
       this.selector = selector,
       specializer = isIntercepted
           ? InvokeDynamicSpecializer.lookupSpecializer(selector)
@@ -1275,8 +1287,8 @@
 }
 
 class HInvokeClosure extends HInvokeDynamic {
-  HInvokeClosure(Selector selector, List<HInstruction> inputs)
-    : super(selector, null, inputs) {
+  HInvokeClosure(Selector selector, List<HInstruction> inputs, HType type)
+    : super(selector, null, inputs, type) {
     assert(selector.isClosureCall());
   }
   accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
@@ -1285,8 +1297,9 @@
 class HInvokeDynamicMethod extends HInvokeDynamic {
   HInvokeDynamicMethod(Selector selector,
                        List<HInstruction> inputs,
+                       HType type,
                        [bool isIntercepted = false])
-    : super(selector, null, inputs, isIntercepted);
+    : super(selector, null, inputs, type, isIntercepted);
 
   String toString() => 'invoke dynamic method: $selector';
   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
@@ -1303,14 +1316,14 @@
   final bool isSideEffectFree;
   HInvokeDynamicField(
       Selector selector, Element element, List<HInstruction> inputs,
-      this.isSideEffectFree)
-      : super(selector, element, inputs);
+      HType type, this.isSideEffectFree)
+      : super(selector, element, inputs, type);
   toString() => 'invoke dynamic field: $selector';
 }
 
 class HInvokeDynamicGetter extends HInvokeDynamicField {
-  HInvokeDynamicGetter(selector, element, inputs, isSideEffectFree)
-    : super(selector, element, inputs, isSideEffectFree) {
+  HInvokeDynamicGetter(selector, element, inputs, type, isSideEffectFree)
+    : super(selector, element, inputs, type, isSideEffectFree) {
     sideEffects.clearAllSideEffects();
     if (isSideEffectFree) {
       setUseGvn();
@@ -1325,8 +1338,8 @@
 }
 
 class HInvokeDynamicSetter extends HInvokeDynamicField {
-  HInvokeDynamicSetter(selector, element, inputs, isSideEffectFree)
-    : super(selector, element, inputs, isSideEffectFree) {
+  HInvokeDynamicSetter(selector, element, inputs, type, isSideEffectFree)
+    : super(selector, element, inputs, type, isSideEffectFree) {
     sideEffects.clearAllSideEffects();
     if (isSideEffectFree) {
       sideEffects.setChangesInstanceProperty();
@@ -1349,9 +1362,7 @@
   List<DartType> instantiatedTypes;
 
   /** The first input must be the target. */
-  HInvokeStatic(this.element, inputs, HType type) : super(inputs) {
-    instructionType = type;
-  }
+  HInvokeStatic(this.element, inputs, HType type) : super(inputs, type);
 
   toString() => 'invoke static: ${element.name}';
   accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
@@ -1368,8 +1379,9 @@
                this.caller,
                this.selector,
                inputs,
+               type,
                {this.isSetter})
-      : super(element, inputs, HType.UNKNOWN);
+      : super(element, inputs, type);
   toString() => 'invoke super: ${element.name}';
   accept(HVisitor visitor) => visitor.visitInvokeSuper(this);
 
@@ -1384,8 +1396,8 @@
   // The 'inputs' are
   //     [receiver, arg1, ..., argN] or
   //     [interceptor, receiver, arg1, ... argN].
-  HInvokeConstructorBody(element, inputs)
-      : super(element, inputs, HType.UNKNOWN);
+  HInvokeConstructorBody(element, inputs, type)
+      : super(element, inputs, type);
 
   String toString() => 'invoke constructor body: ${element.name}';
   accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this);
@@ -1394,8 +1406,8 @@
 abstract class HFieldAccess extends HInstruction {
   final Element element;
 
-  HFieldAccess(Element element, List<HInstruction> inputs)
-      : this.element = element, super(inputs);
+  HFieldAccess(Element element, List<HInstruction> inputs, HType type)
+      : this.element = element, super(inputs, type);
 
   HInstruction get receiver => inputs[0];
 }
@@ -1403,11 +1415,14 @@
 class HFieldGet extends HFieldAccess {
   final bool isAssignable;
 
-  HFieldGet(Element element, HInstruction receiver, {bool isAssignable})
+  HFieldGet(Element element,
+            HInstruction receiver,
+            HType type,
+            {bool isAssignable})
       : this.isAssignable = (isAssignable != null)
             ? isAssignable
             : element.isAssignable(),
-        super(element, <HInstruction>[receiver]) {
+        super(element, <HInstruction>[receiver], type) {
     sideEffects.clearAllSideEffects();
     setUseGvn();
     if (this.isAssignable) {
@@ -1444,7 +1459,7 @@
   HFieldSet(Element element,
             HInstruction receiver,
             HInstruction value)
-      : super(element, <HInstruction>[receiver, value]) {
+      : super(element, <HInstruction>[receiver, value], EMPTY_TYPE) {
     sideEffects.clearAllSideEffects();
     sideEffects.setChangesInstanceProperty();
   }
@@ -1464,8 +1479,8 @@
 class HLocalGet extends HFieldAccess {
   // No need to use GVN for a [HLocalGet], it is just a local
   // access.
-  HLocalGet(Element element, HLocalValue local)
-      : super(element, <HInstruction>[local]);
+  HLocalGet(Element element, HLocalValue local, HType type)
+      : super(element, <HInstruction>[local], type);
 
   accept(HVisitor visitor) => visitor.visitLocalGet(this);
 
@@ -1474,7 +1489,7 @@
 
 class HLocalSet extends HFieldAccess {
   HLocalSet(Element element, HLocalValue local, HInstruction value)
-      : super(element, <HInstruction>[local, value]);
+      : super(element, <HInstruction>[local, value], EMPTY_TYPE);
 
   accept(HVisitor visitor) => visitor.visitLocalSet(this);
 
@@ -1494,18 +1509,18 @@
            {this.isStatement: false,
             SideEffects effects,
             native.NativeBehavior nativeBehavior})
-      : this.nativeBehavior = nativeBehavior, super(inputs) {
+      : this.nativeBehavior = nativeBehavior, super(inputs, type) {
     if (effects == null && nativeBehavior != null) {
       effects = nativeBehavior.sideEffects;
     }
     if (effects != null) sideEffects.add(effects);
-    instructionType = type;
   }
 
   HForeign.statement(codeAst, List<HInstruction> inputs,
                      SideEffects effects,
-                     native.NativeBehavior nativeBehavior)
-      : this(codeAst, HType.UNKNOWN, inputs, isStatement: true,
+                     native.NativeBehavior nativeBehavior,
+                     HType type)
+      : this(codeAst, type, inputs, isStatement: true,
              effects: effects, nativeBehavior: nativeBehavior);
 
   accept(HVisitor visitor) => visitor.visitForeign(this);
@@ -1534,8 +1549,8 @@
 
 abstract class HInvokeBinary extends HInstruction {
   final Selector selector;
-  HInvokeBinary(HInstruction left, HInstruction right, this.selector)
-      : super(<HInstruction>[left, right]) {
+  HInvokeBinary(HInstruction left, HInstruction right, this.selector, type)
+      : super(<HInstruction>[left, right], type) {
     sideEffects.clearAllSideEffects();
     setUseGvn();
   }
@@ -1547,12 +1562,13 @@
 }
 
 abstract class HBinaryArithmetic extends HInvokeBinary {
-  HBinaryArithmetic(left, right, selector) : super(left, right, selector);
+  HBinaryArithmetic(left, right, selector, type)
+      : super(left, right, selector, type);
   BinaryOperation operation(ConstantSystem constantSystem);
 }
 
 class HAdd extends HBinaryArithmetic {
-  HAdd(left, right, selector) : super(left, right, selector);
+  HAdd(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitAdd(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1563,9 +1579,7 @@
 }
 
 class HDivide extends HBinaryArithmetic {
-  HDivide(left, right, selector) : super(left, right, selector) {
-    instructionType = HType.DOUBLE;
-  }
+  HDivide(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitDivide(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1576,7 +1590,7 @@
 }
 
 class HMultiply extends HBinaryArithmetic {
-  HMultiply(left, right, selector) : super(left, right, selector);
+  HMultiply(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitMultiply(this);
 
   BinaryOperation operation(ConstantSystem operations)
@@ -1587,7 +1601,7 @@
 }
 
 class HSubtract extends HBinaryArithmetic {
-  HSubtract(left, right, selector) : super(left, right, selector);
+  HSubtract(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitSubtract(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1621,13 +1635,12 @@
 }
 
 abstract class HBinaryBitOp extends HInvokeBinary {
-  HBinaryBitOp(left, right, selector) : super(left, right, selector) {
-    instructionType = HType.INTEGER;
-  }
+  HBinaryBitOp(left, right, selector, type)
+      : super(left, right, selector, type);
 }
 
 class HShiftLeft extends HBinaryBitOp {
-  HShiftLeft(left, right, selector) : super(left, right, selector);
+  HShiftLeft(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitShiftLeft(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1638,7 +1651,7 @@
 }
 
 class HBitOr extends HBinaryBitOp {
-  HBitOr(left, right, selector) : super(left, right, selector);
+  HBitOr(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitBitOr(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1649,7 +1662,7 @@
 }
 
 class HBitAnd extends HBinaryBitOp {
-  HBitAnd(left, right, selector) : super(left, right, selector);
+  HBitAnd(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitBitAnd(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1660,7 +1673,7 @@
 }
 
 class HBitXor extends HBinaryBitOp {
-  HBitXor(left, right, selector) : super(left, right, selector);
+  HBitXor(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitBitXor(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1672,8 +1685,8 @@
 
 abstract class HInvokeUnary extends HInstruction {
   final Selector selector;
-  HInvokeUnary(HInstruction input, this.selector)
-      : super(<HInstruction>[input]) {
+  HInvokeUnary(HInstruction input, this.selector, type)
+      : super(<HInstruction>[input], type) {
     sideEffects.clearAllSideEffects();
     setUseGvn();
   }
@@ -1684,7 +1697,7 @@
 }
 
 class HNegate extends HInvokeUnary {
-  HNegate(input, selector) : super(input, selector);
+  HNegate(input, selector, type) : super(input, selector, type);
   accept(HVisitor visitor) => visitor.visitNegate(this);
 
   UnaryOperation operation(ConstantSystem constantSystem)
@@ -1695,9 +1708,7 @@
 }
 
 class HBitNot extends HInvokeUnary {
-  HBitNot(input, selector) : super(input, selector) {
-    instructionType = HType.INTEGER;
-  }
+  HBitNot(input, selector, type) : super(input, selector, type);
   accept(HVisitor visitor) => visitor.visitBitNot(this);
 
   UnaryOperation operation(ConstantSystem constantSystem)
@@ -1825,9 +1836,7 @@
 class HConstant extends HInstruction {
   final Constant constant;
   HConstant.internal(this.constant, HType constantType)
-      : super(<HInstruction>[]) {
-    instructionType = constantType;
-  }
+      : super(<HInstruction>[], constantType);
 
   toString() => 'literal: $constant';
   accept(HVisitor visitor) => visitor.visitConstant(this);
@@ -1851,9 +1860,8 @@
 }
 
 class HNot extends HInstruction {
-  HNot(HInstruction value) : super(<HInstruction>[value]) {
+  HNot(HInstruction value, HType type) : super(<HInstruction>[value], type) {
     setUseGvn();
-    instructionType = HType.BOOLEAN;
   }
 
   accept(HVisitor visitor) => visitor.visitNot(this);
@@ -1868,7 +1876,7 @@
   * value from the start, whereas [HLocalValue]s need to be initialized first.
   */
 class HLocalValue extends HInstruction {
-  HLocalValue(Element element) : super(<HInstruction>[]) {
+  HLocalValue(Element element, HType type) : super(<HInstruction>[], type) {
     sourceElement = element;
   }
 
@@ -1877,16 +1885,14 @@
 }
 
 class HParameterValue extends HLocalValue {
-  HParameterValue(Element element) : super(element);
+  HParameterValue(Element element, type) : super(element, type);
 
   toString() => 'parameter ${sourceElement.name}';
   accept(HVisitor visitor) => visitor.visitParameterValue(this);
 }
 
 class HThis extends HParameterValue {
-  HThis(Element element, [HType type = HType.UNKNOWN]) : super(element) {
-    instructionType = type;
-  }
+  HThis(Element element, HType type) : super(element, type);
   toString() => 'this';
   accept(HVisitor visitor) => visitor.visitThis(this);
   bool isCodeMotionInvariant() => true;
@@ -1906,14 +1912,16 @@
   // The order of the [inputs] must correspond to the order of the
   // predecessor-edges. That is if an input comes from the first predecessor
   // of the surrounding block, then the input must be the first in the [HPhi].
-  HPhi(Element element, List<HInstruction> inputs) : super(inputs) {
+  HPhi(Element element, List<HInstruction> inputs, HType type)
+      : super(inputs, type) {
     sourceElement = element;
   }
-  HPhi.noInputs(Element element) : this(element, <HInstruction>[]);
-  HPhi.singleInput(Element element, HInstruction input)
-      : this(element, <HInstruction>[input]);
-  HPhi.manyInputs(Element element, List<HInstruction> inputs)
-      : this(element, inputs);
+  HPhi.noInputs(Element element, HType type)
+      : this(element, <HInstruction>[], type);
+  HPhi.singleInput(Element element, HInstruction input, HType type)
+      : this(element, <HInstruction>[input], type);
+  HPhi.manyInputs(Element element, List<HInstruction> inputs, HType type)
+      : this(element, inputs, type);
 
   void addInput(HInstruction input) {
     assert(isInBasicBlock());
@@ -1937,13 +1945,11 @@
 
 abstract class HRelational extends HInvokeBinary {
   bool usesBoolifiedInterceptor = false;
-  HRelational(left, right, selector) : super(left, right, selector) {
-    instructionType = HType.BOOLEAN;
-  }
+  HRelational(left, right, selector, type) : super(left, right, selector, type);
 }
 
 class HIdentity extends HRelational {
-  HIdentity(left, right, [selector]) : super(left, right, selector);
+  HIdentity(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitIdentity(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1954,7 +1960,7 @@
 }
 
 class HGreater extends HRelational {
-  HGreater(left, right, selector) : super(left, right, selector);
+  HGreater(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitGreater(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1965,7 +1971,8 @@
 }
 
 class HGreaterEqual extends HRelational {
-  HGreaterEqual(left, right, selector) : super(left, right, selector);
+  HGreaterEqual(left, right, selector, type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1976,7 +1983,7 @@
 }
 
 class HLess extends HRelational {
-  HLess(left, right, selector) : super(left, right, selector);
+  HLess(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitLess(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1987,7 +1994,7 @@
 }
 
 class HLessEqual extends HRelational {
-  HLessEqual(left, right, selector) : super(left, right, selector);
+  HLessEqual(left, right, selector, type) : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitLessEqual(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -2004,7 +2011,7 @@
 }
 
 class HThrowExpression extends HInstruction {
-  HThrowExpression(value) : super(<HInstruction>[value]);
+  HThrowExpression(value) : super(<HInstruction>[value], EMPTY_TYPE);
   toString() => 'throw expression';
   accept(HVisitor visitor) => visitor.visitThrowExpression(this);
   bool canThrow() => true;
@@ -2019,7 +2026,7 @@
 
 class HStatic extends HInstruction {
   final Element element;
-  HStatic(this.element) : super(<HInstruction>[]) {
+  HStatic(this.element, type) : super(<HInstruction>[], type) {
     assert(element != null);
     assert(invariant(this, element.isDeclaration));
     sideEffects.clearAllSideEffects();
@@ -2042,7 +2049,8 @@
   // This field should originally be null to allow GVN'ing all
   // [HInterceptor] on the same input.
   Set<ClassElement> interceptedClasses;
-  HInterceptor(HInstruction receiver) : super(<HInstruction>[receiver]) {
+  HInterceptor(HInstruction receiver, HType type)
+      : super(<HInstruction>[receiver], type) {
     sideEffects.clearAllSideEffects();
     setUseGvn();
   }
@@ -2073,10 +2081,11 @@
   Set<ClassElement> interceptedClasses;
   HOneShotInterceptor(Selector selector,
                       List<HInstruction> inputs,
+                      HType type,
                       this.interceptedClasses)
-      : super(selector, null, inputs, true) {
+      : super(selector, null, inputs, type, true) {
     assert(inputs[0] is HConstant);
-    assert(inputs[0].instructionType == HType.NULL);
+    assert(inputs[0].instructionType.isNull());
   }
   bool isCallOnInterceptor(Compiler compiler) => true;
 
@@ -2087,7 +2096,7 @@
 /** An [HLazyStatic] is a static that is initialized lazily at first read. */
 class HLazyStatic extends HInstruction {
   final Element element;
-  HLazyStatic(this.element) : super(<HInstruction>[]) {
+  HLazyStatic(this.element, type) : super(<HInstruction>[], type) {
     // TODO(4931): The first access has side-effects, but we afterwards we
     // should be able to GVN.
     sideEffects.setAllSideEffects();
@@ -2106,7 +2115,7 @@
 class HStaticStore extends HInstruction {
   Element element;
   HStaticStore(this.element, HInstruction value)
-      : super(<HInstruction>[value]) {
+      : super(<HInstruction>[value], EMPTY_TYPE) {
     sideEffects.clearAllSideEffects();
     sideEffects.setChangesStaticProperty();
   }
@@ -2120,9 +2129,7 @@
 }
 
 class HLiteralList extends HInstruction {
-  HLiteralList(List<HInstruction> inputs, HType type) : super(inputs) {
-    instructionType = type;
-  }
+  HLiteralList(List<HInstruction> inputs, HType type) : super(inputs, type);
   toString() => 'literal list';
   accept(HVisitor visitor) => visitor.visitLiteralList(this);
 }
@@ -2133,8 +2140,8 @@
  */
 class HIndex extends HInstruction {
   final Selector selector;
-  HIndex(HInstruction receiver, HInstruction index, this.selector)
-      : super(<HInstruction>[receiver, index]) {
+  HIndex(HInstruction receiver, HInstruction index, this.selector, type)
+      : super(<HInstruction>[receiver, index], type) {
     sideEffects.clearAllSideEffects();
     sideEffects.setDependsOnIndexStore();
     setUseGvn();
@@ -2164,7 +2171,7 @@
                HInstruction index,
                HInstruction value,
                this.selector)
-      : super(<HInstruction>[receiver, index, value]) {
+      : super(<HInstruction>[receiver, index, value], EMPTY_TYPE) {
     sideEffects.clearAllSideEffects();
     sideEffects.setChangesIndex();
   }
@@ -2191,29 +2198,33 @@
   final int kind;
 
   HIs.direct(DartType typeExpression,
-             HInstruction expression)
-      : this.internal(typeExpression, [expression], RAW_CHECK);
+             HInstruction expression,
+             HType type)
+      : this.internal(typeExpression, [expression], RAW_CHECK, type);
 
   HIs.raw(DartType typeExpression,
           HInstruction expression,
-          HInterceptor interceptor)
-      : this.internal(typeExpression, [expression, interceptor], RAW_CHECK);
+          HInterceptor interceptor,
+          HType type)
+      : this.internal(
+            typeExpression, [expression, interceptor], RAW_CHECK, type);
 
   HIs.compound(DartType typeExpression,
                HInstruction expression,
-               HInstruction call)
-      : this.internal(typeExpression, [expression, call], COMPOUND_CHECK);
+               HInstruction call,
+               HType type)
+      : this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type);
 
   HIs.variable(DartType typeExpression,
                HInstruction expression,
-               HInstruction call)
-      : this.internal(typeExpression, [expression, call], VARIABLE_CHECK);
+               HInstruction call,
+               HType type)
+      : this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type);
 
-  HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind)
-      : super(inputs) {
+  HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind, type)
+      : super(inputs, type) {
     assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK);
     setUseGvn();
-    instructionType = HType.BOOLEAN;
   }
 
   HInstruction get expression => inputs[0];
@@ -2264,12 +2275,11 @@
                   [this.receiverTypeCheckSelector])
       : contextIsTypeArguments = false,
         checkedType = type,
-        super(<HInstruction>[input]) {
+        super(<HInstruction>[input], type) {
     assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
     assert(typeExpression == null ||
            typeExpression.kind != TypeKind.TYPEDEF);
     sourceElement = input.sourceElement;
-    instructionType = type;
   }
 
   HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
@@ -2277,23 +2287,21 @@
                                          HInstruction typeRepresentation)
       : contextIsTypeArguments = false,
         checkedType = type,
-        super(<HInstruction>[input, typeRepresentation]),
+        super(<HInstruction>[input, typeRepresentation],type),
         receiverTypeCheckSelector = null {
     assert(typeExpression.kind != TypeKind.TYPEDEF);
     sourceElement = input.sourceElement;
-    instructionType = type;
   }
 
   HTypeConversion.withContext(this.typeExpression, this.kind,
                               HType type, HInstruction input,
                               HInstruction context,
                               {bool this.contextIsTypeArguments})
-      : super(<HInstruction>[input, context]),
+      : super(<HInstruction>[input, context], type),
         checkedType = type,
         receiverTypeCheckSelector = null {
     assert(typeExpression.kind != TypeKind.TYPEDEF);
     sourceElement = input.sourceElement;
-    instructionType = type;
   }
 
   bool get hasTypeRepresentation {
@@ -2339,10 +2347,9 @@
 /// The [HTypeKnown] instruction marks a value with a refined type.
 class HTypeKnown extends HCheck {
   HType knownType;
-  HTypeKnown(HType this.knownType, HInstruction input)
-      : super(<HInstruction>[input]) {
-    instructionType = knownType;
-  }
+  HTypeKnown(HType knownType, HInstruction input)
+      : this.knownType = knownType,
+        super(<HInstruction>[input], knownType);
   toString() => 'TypeKnown $knownType';
   accept(HVisitor visitor) => visitor.visitTypeKnown(this);
 
@@ -2361,10 +2368,9 @@
 }
 
 class HRangeConversion extends HCheck {
-  HRangeConversion(HInstruction input) : super(<HInstruction>[input]) {
+  HRangeConversion(HInstruction input, type)
+      : super(<HInstruction>[input], type) {
     sourceElement = input.sourceElement;
-    // We currently only do range analysis for integers.
-    instructionType = HType.INTEGER;
   }
   accept(HVisitor visitor) => visitor.visitRangeConversion(this);
 }
@@ -2372,12 +2378,11 @@
 class HStringConcat extends HInstruction {
   final Node node;
   HStringConcat(HInstruction left, HInstruction right, this.node, HType type)
-      : super(<HInstruction>[left, right]) {
+      : super(<HInstruction>[left, right], type) {
     // TODO(sra): Until Issue 9293 is fixed, this false dependency keeps the
     // concats bunched with stringified inputs for much better looking code with
     // fewer temps.
     sideEffects.setDependsOnSomething();
-    instructionType = type;
   }
 
   HInstruction get left => inputs[0];
@@ -2394,10 +2399,9 @@
 class HStringify extends HInstruction {
   final Node node;
   HStringify(HInstruction input, this.node, HType type)
-      : super(<HInstruction>[input]) {
+      : super(<HInstruction>[input], type) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
-    instructionType = type;
   }
 
   accept(HVisitor visitor) => visitor.visitStringify(this);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index d85cc01..d3e21fd 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -39,13 +39,13 @@
           // some patterns useful for type conversion.
           new SsaInstructionSimplifier(constantSystem, backend, work),
           new SsaTypeConversionInserter(compiler),
+          new SsaRedundantPhiEliminator(),
+          new SsaDeadPhiEliminator(),
           new SsaTypePropagator(compiler),
           // After type propagation, more instructions can be
           // simplified.
           new SsaInstructionSimplifier(constantSystem, backend, work),
           new SsaCheckInserter(backend, work, context.boundsChecked),
-          new SsaRedundantPhiEliminator(),
-          new SsaDeadPhiEliminator(),
           new SsaInstructionSimplifier(constantSystem, backend, work),
           new SsaCheckInserter(backend, work, context.boundsChecked),
           new SsaTypePropagator(compiler),
@@ -53,6 +53,9 @@
           // interceptors are often in the way of LICM'able instructions.
           new SsaDeadCodeEliminator(compiler),
           new SsaGlobalValueNumberer(compiler),
+          // After GVN, some instructions might need their type to be
+          // updated because they now have different inputs.
+          new SsaTypePropagator(compiler),
           new SsaCodeMotion(),
           new SsaValueRangeAnalyzer(compiler, constantSystem, work),
           // Previous optimizations may have generated new
@@ -108,14 +111,7 @@
         // [replacement]'s type can be narrowed.
         HType newType = replacement.instructionType.intersection(
             instruction.instructionType, compiler);
-        if (!newType.isConflicting()) {
-          // [HType.intersection] may give up when doing the
-          // intersection of two types is too complicated, and return
-          // [HType.CONFLICTING]. We do not want instructions to have
-          // [HType.CONFLICTING], so we only update the type if the
-          // intersection did not give up.
-          replacement.instructionType = newType;
-        }
+        replacement.instructionType = newType;
 
         // If the replacement instruction does not know its
         // source element, use the source element of the
@@ -150,7 +146,7 @@
     assert(inputs.length == 1);
     HInstruction input = inputs[0];
     HType type = input.instructionType;
-    if (type.isBoolean()) return input;
+    if (type.isBoolean(compiler)) return input;
     // All values that cannot be 'true' are boolified to false.
     TypeMask mask = type.computeMask(compiler);
     // TODO(kasperl): Get rid of the null check here once all HTypes
@@ -206,8 +202,7 @@
       bool isAssignable = !actualReceiver.isFixedArray(compiler) &&
           !actualReceiver.isString(compiler);
       HFieldGet result = new HFieldGet(
-          element, actualReceiver, isAssignable: isAssignable);
-      result.instructionType = HType.INTEGER;
+          element, actualReceiver, backend.intType, isAssignable: isAssignable);
       return result;
     } else if (actualReceiver.isConstantMap()) {
       HConstant constantInput = actualReceiver;
@@ -277,7 +272,7 @@
         // bounds check will become explicit, so we won't need this
         // optimization.
         HInvokeDynamicMethod result = new HInvokeDynamicMethod(
-            node.selector, node.inputs.sublist(1));
+            node.selector, node.inputs.sublist(1), node.instructionType);
         result.element = target;
         return result;
       }
@@ -373,22 +368,21 @@
 
     if (!canInline) return null;
 
-    HInvokeDynamicMethod result =
-        new HInvokeDynamicMethod(node.selector, inputs);
-    result.element = method;
 
     // Strengthen instruction type from annotations to help optimize
     // dependent instructions.
     native.NativeBehavior nativeBehavior =
         native.NativeBehavior.ofMethod(method, compiler);
     HType returnType = new HType.fromNativeBehavior(nativeBehavior, compiler);
-    result.instructionType = returnType;
+    HInvokeDynamicMethod result =
+        new HInvokeDynamicMethod(node.selector, inputs, returnType);
+    result.element = method;
     return result;
   }
 
   HInstruction visitBoundsCheck(HBoundsCheck node) {
     HInstruction index = node.index;
-    if (index.isInteger()) return node;
+    if (index.isInteger(compiler)) return node;
     if (index.isConstant()) {
       HConstant constantInstruction = index;
       assert(!constantInstruction.constant.isInt());
@@ -448,7 +442,7 @@
 
     // Intersection of int and double return conflicting, so
     // we don't optimize on numbers to preserve the runtime semantics.
-    if (!(left.isNumberOrNull() && right.isNumberOrNull()) &&
+    if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler)) &&
         leftType.intersection(rightType, compiler).isConflicting()) {
       return graph.addConstantBool(false, compiler);
     }
@@ -457,21 +451,21 @@
       return graph.addConstantBool(true, compiler);
     }
 
-    if (left.isConstantBoolean() && right.isBoolean()) {
+    if (left.isConstantBoolean() && right.isBoolean(compiler)) {
       HConstant constant = left;
       if (constant.constant.isTrue()) {
         return right;
       } else {
-        return new HNot(right);
+        return new HNot(right, backend.boolType);
       }
     }
 
-    if (right.isConstantBoolean() && left.isBoolean()) {
+    if (right.isConstantBoolean() && left.isBoolean(compiler)) {
       HConstant constant = right;
       if (constant.constant.isTrue()) {
         return left;
       } else {
-        return new HNot(left);
+        return new HNot(left, backend.boolType);
       }
     }
 
@@ -534,7 +528,7 @@
     }
 
     HType expressionType = node.expression.instructionType;
-    if (expressionType.isInteger()) {
+    if (expressionType.isInteger(compiler)) {
       if (identical(element, compiler.intClass)
           || identical(element, compiler.numClass)
           || Elements.isNumberOrStringSupertype(element, compiler)) {
@@ -546,7 +540,7 @@
       } else {
         return graph.addConstantBool(false, compiler);
       }
-    } else if (expressionType.isDouble()) {
+    } else if (expressionType.isDouble(compiler)) {
       if (identical(element, compiler.doubleClass)
           || identical(element, compiler.numClass)
           || Elements.isNumberOrStringSupertype(element, compiler)) {
@@ -559,7 +553,7 @@
       } else {
         return graph.addConstantBool(false, compiler);
       }
-    } else if (expressionType.isNumber()) {
+    } else if (expressionType.isNumber(compiler)) {
       if (identical(element, compiler.numClass)) {
         return graph.addConstantBool(true, compiler);
       } else {
@@ -608,7 +602,7 @@
   }
 
   HInstruction removeIfCheckAlwaysSucceeds(HCheck node, HType checkedType) {
-    if (checkedType.isUnknown()) return node;
+    if (checkedType.containsAll(compiler)) return node;
     HInstruction input = node.checkedInput;
     HType inputType = input.instructionType;
     HType filteredType = inputType.intersection(checkedType, compiler);
@@ -635,7 +629,7 @@
         // that we know takes an int.
         if (element == compiler.unnamedListConstructor
             && receiver.inputs.length == 1
-            && receiver.inputs[0].isInteger()) {
+            && receiver.inputs[0].isInteger(compiler)) {
           return receiver.inputs[0];
         }
       } else if (receiver.isConstantList() || receiver.isConstantString()) {
@@ -699,18 +693,18 @@
       // distinct from ordinary Dart effects.
       isAssignable = true;
     }
-    HFieldGet result = new HFieldGet(
-        field, receiver, isAssignable: isAssignable);
 
+    HType type;
     if (field.getEnclosingClass().isNative()) {
-      result.instructionType = new HType.fromNativeBehavior(
+      type = new HType.fromNativeBehavior(
           native.NativeBehavior.ofFieldLoad(field, compiler),
           compiler);
     } else {
-      result.instructionType =
-          new HType.inferredTypeForElement(field, compiler);
+      type = new HType.inferredTypeForElement(field, compiler);
     }
-    return result;
+
+    return new HFieldGet(
+        field, receiver, type, isAssignable: isAssignable);
   }
 
   HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
@@ -836,11 +830,12 @@
     bool isAssignable =
         !array.isFixedArray(compiler) && !array.isString(compiler);
     HFieldGet length = new HFieldGet(
-        backend.jsIndexableLength, array, isAssignable: isAssignable);
-    length.instructionType = HType.INTEGER;
+        backend.jsIndexableLength, array, backend.intType,
+        isAssignable: isAssignable);
     indexNode.block.addBefore(indexNode, length);
 
-    HBoundsCheck check = new HBoundsCheck(indexArgument, length, array);
+    HBoundsCheck check = new HBoundsCheck(
+        indexArgument, length, array, backend.intType);
     indexNode.block.addBefore(indexNode, check);
     // If the index input to the bounds check was not known to be an integer
     // then we replace its uses with the bounds check, which is known to be an
@@ -849,7 +844,7 @@
     // the index eg. if it is a constant.  The range information from the
     // BoundsCheck instruction is attached to the input directly by
     // visitBoundsCheck in the SsaValueRangeAnalyzer.
-    if (!indexArgument.isInteger()) {
+    if (!indexArgument.isInteger(compiler)) {
       indexArgument.replaceAllUsersDominatedBy(indexNode, check);
     }
     boundsChecked.add(indexNode);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index eea1cc5..f62a343 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -179,9 +179,9 @@
   String temporaryId(HInstruction instruction) {
     String prefix;
     HType type = instruction.instructionType;
-    if (type == HType.NULL) {
+    if (type.isNull()) {
       prefix = 'u';
-    } else if (type == HType.CONFLICTING) {
+    } else if (type.isConflicting()) {
       prefix = 'c';
     } else if (type.isExtendableArray(compiler)) {
       prefix = 'e';
@@ -195,15 +195,15 @@
       prefix = 's';
     } else if (type.isIndexable(compiler)) {
       prefix = 'r';
-    } else if (type == HType.BOOLEAN) {
+    } else if (type.isBoolean(compiler)) {
       prefix = 'b';
-    } else if (type == HType.INTEGER) {
+    } else if (type.isInteger(compiler)) {
       prefix = 'i';
-    } else if (type == HType.DOUBLE) {
+    } else if (type.isDouble(compiler)) {
       prefix = 'd';
-    } else if (type == HType.NUMBER) {
+    } else if (type.isNumber(compiler)) {
       prefix = 'n';
-    } else if (type == HType.UNKNOWN) {
+    } else if (type.containsAll(compiler)) {
       prefix = 'v';
     } else {
       prefix = 'U';
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index bfdb564..a8e4238 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -14,18 +14,24 @@
    */
   factory HType.fromMask(TypeMask mask, Compiler compiler) {
     bool isNullable = mask.isNullable;
+    JavaScriptBackend backend = compiler.backend;
     if (mask.isEmpty) {
-      return isNullable ? HType.NULL : HType.CONFLICTING;
+      return isNullable ? backend.nullType : backend.emptyType;
     }
 
-    JavaScriptBackend backend = compiler.backend;
     if (mask.containsOnlyInt(compiler)) {
-      return isNullable ? HType.INTEGER_OR_NULL : HType.INTEGER;
+      return mask.isNullable
+          ? new HBoundedType(new TypeMask.exact(backend.jsIntClass))
+          : backend.intType;
     } else if (mask.containsOnlyDouble(compiler)) {
-      return isNullable ? HType.DOUBLE_OR_NULL : HType.DOUBLE;
+      return mask.isNullable
+          ? new HBoundedType(new TypeMask.exact(backend.jsDoubleClass))
+          : backend.doubleType;
     } else if (mask.containsOnlyNum(compiler)
                || mask.satisfies(backend.jsNumberClass, compiler)) {
-      return isNullable ? HType.NUMBER_OR_NULL : HType.NUMBER;
+      return mask.isNullable
+          ? new HBoundedType(new TypeMask.subclass(backend.jsNumberClass))
+          : backend.numType;
     } else if (mask.containsOnlyString(compiler)) {
       // TODO(ngeoffray): Avoid creating [TypeMask]s with the string
       // class as base.
@@ -33,15 +39,17 @@
           ? new HBoundedType(new TypeMask.exact(backend.jsStringClass))
           : backend.stringType;
     } else if (mask.containsOnlyBool(compiler)) {
-      return isNullable ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
+      return isNullable
+          ? new HBoundedType(new TypeMask.exact(backend.jsBoolClass))
+          : backend.boolType;
     } else if (mask.containsOnlyNull(compiler)) {
-      return HType.NULL;
+      return backend.nullType;
     }
 
     // TODO(kasperl): A lot of the code in the system currently
     // expects the top type to be 'unknown'. I'll rework this.
     if (mask.containsAll(compiler)) {
-      return isNullable ? HType.UNKNOWN : HType.NON_NULL;
+      return isNullable ? backend.dynamicType : backend.nonNullType;
     }
 
     return new HBoundedType(mask);
@@ -78,7 +86,8 @@
   }
 
   factory HType.fromInferredType(TypeMask mask, Compiler compiler) {
-    if (mask == null) return HType.UNKNOWN;
+    JavaScriptBackend backend = compiler.backend;
+    if (mask == null) return backend.dynamicType;
     return new HType.fromMask(mask, compiler);
   }
 
@@ -109,7 +118,8 @@
 
   factory HType.fromNativeBehavior(native.NativeBehavior nativeBehavior,
                                    Compiler compiler) {
-    if (nativeBehavior.typesReturned.isEmpty) return HType.UNKNOWN;
+    JavaScriptBackend backend = compiler.backend;
+    if (nativeBehavior.typesReturned.isEmpty) return backend.dynamicType;
 
     HType result = nativeBehavior.typesReturned
         .map((type) => fromNativeType(type, compiler))
@@ -121,14 +131,15 @@
   // [type] is either an instance of [DartType] or special objects
   // like [native.SpecialType.JsObject].
   static HType fromNativeType(type, Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     if (type == native.SpecialType.JsObject) {
       return new HType.nonNullExact(compiler.objectClass, compiler);
     } else if (type.isVoid) {
-      return HType.NULL;
+      return backend.nullType;
     } else if (type.element == compiler.nullClass) {
-      return HType.NULL;
+      return backend.nullType;
     } else if (type.treatAsDynamic) {
-      return HType.UNKNOWN;
+      return backend.dynamicType;
     } else if (compiler.world.hasAnySubtype(type.element)) {
       return new HType.nonNullSubtype(type.element, compiler);
     } else if (compiler.world.hasAnySubclass(type.element)) {
@@ -138,28 +149,13 @@
     }
   }
 
-  static const HType CONFLICTING = const HConflictingType();
-  static const HType UNKNOWN = const HUnknownType();
-  static const HType NON_NULL = const HNonNullType();
-  static const HType BOOLEAN = const HBooleanType();
-  static const HType NUMBER = const HNumberType();
-  static const HType INTEGER = const HIntegerType();
-  static const HType DOUBLE = const HDoubleType();
-  static const HType NULL = const HNullType();
-
-  static const HType BOOLEAN_OR_NULL = const HBooleanOrNullType();
-  static const HType NUMBER_OR_NULL = const HNumberOrNullType();
-  static const HType INTEGER_OR_NULL = const HIntegerOrNullType();
-  static const HType DOUBLE_OR_NULL = const HDoubleOrNullType();
-
-  bool isConflicting() => identical(this, CONFLICTING);
-  bool isUnknown() => identical(this, UNKNOWN);
+  bool isConflicting() => false;
   bool isExact() => false;
   bool isNull() => false;
-  bool isBoolean() => false;
-  bool isNumber() => false;
-  bool isInteger() => false;
-  bool isDouble() => false;
+  bool isBoolean(Compiler compiler) => false;
+  bool isNumber(Compiler compiler) => false;
+  bool isInteger(Compiler compiler) => false;
+  bool isDouble(Compiler compiler) => false;
 
   bool isString(Compiler compiler) => false;
   bool isFixedArray(Compiler compiler) => false;
@@ -169,10 +165,10 @@
   bool isPrimitive(Compiler compiler) => false;
   bool isPrimitiveOrNull(Compiler compiler) => false;
 
-  bool isBooleanOrNull() => false;
-  bool isNumberOrNull() => false;
-  bool isIntegerOrNull() => false;
-  bool isDoubleOrNull() => false;
+  bool isBooleanOrNull(Compiler compiler) => false;
+  bool isNumberOrNull(Compiler compiler) => false;
+  bool isIntegerOrNull(Compiler compiler) => false;
+  bool isDoubleOrNull(Compiler compiler) => false;
 
   // TODO(kasperl): Get rid of this one.
   bool isIndexablePrimitive(Compiler compiler) => false;
@@ -199,8 +195,6 @@
   bool canBePrimitiveArray(Compiler compiler) => false;
   bool canBePrimitiveBoolean(Compiler compiler) => false;
 
-  /** A type is useful it is not unknown, not conflicting, and not null. */
-  bool isUseful() => !isUnknown() && !isConflicting() && !isNull();
   /** Alias for isReadableArray. */
   bool isArray(Compiler compiler) => isReadableArray(compiler);
 
@@ -258,175 +252,9 @@
   HType nonNullable(compiler) {
     return new HType.fromMask(computeMask(compiler).nonNullable(), compiler);
   }
-}
 
-/** Used to represent [HType.UNKNOWN] and [HType.CONFLICTING]. */
-abstract class HAnalysisType extends HType {
-  final String name;
-  const HAnalysisType(this.name);
-  String toString() => name;
-}
-
-class HUnknownType extends HAnalysisType {
-  const HUnknownType() : super("unknown");
-  bool canBePrimitive(Compiler compiler) => true;
-  bool canBeNull() => true;
-  bool canBePrimitiveNumber(Compiler compiler) => true;
-  bool canBePrimitiveString(Compiler compiler) => true;
-  bool canBePrimitiveArray(Compiler compiler) => true;
-  bool canBePrimitiveBoolean(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.subclass(compiler.objectClass);
-  }
-}
-
-class HNonNullType extends HAnalysisType {
-  const HNonNullType() : super("non-null");
-  bool canBePrimitive(Compiler compiler) => true;
-  bool canBeNull() => false;
-  bool canBePrimitiveNumber(Compiler compiler) => true;
-  bool canBePrimitiveString(Compiler compiler) => true;
-  bool canBePrimitiveArray(Compiler compiler) => true;
-  bool canBePrimitiveBoolean(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullSubclass(compiler.objectClass);
-  }
-}
-
-class HConflictingType extends HAnalysisType {
-  const HConflictingType() : super("conflicting");
-  bool canBePrimitive(Compiler compiler) => true;
-  bool canBeNull() => false;
-
-  TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullEmpty();
-  }
-}
-
-abstract class HPrimitiveType extends HType {
-  const HPrimitiveType();
-  bool isPrimitive(Compiler compiler) => true;
-  bool canBePrimitive(Compiler compiler) => true;
-  bool isPrimitiveOrNull(Compiler compiler) => true;
-}
-
-class HNullType extends HPrimitiveType {
-  const HNullType();
-  bool canBeNull() => true;
-  bool isNull() => true;
-  String toString() => 'null type';
-  bool isExact() => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.empty();
-  }
-}
-
-abstract class HPrimitiveOrNullType extends HType {
-  const HPrimitiveOrNullType();
-  bool canBePrimitive(Compiler compiler) => true;
-  bool canBeNull() => true;
-  bool isPrimitiveOrNull(Compiler compiler) => true;
-}
-
-class HBooleanOrNullType extends HPrimitiveOrNullType {
-  const HBooleanOrNullType();
-  String toString() => "boolean or null";
-  bool isBooleanOrNull() => true;
-  bool canBePrimitiveBoolean(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.exact(backend.jsBoolClass);
-  }
-}
-
-class HBooleanType extends HPrimitiveType {
-  const HBooleanType();
-  bool isBoolean() => true;
-  bool isBooleanOrNull() => true;
-  String toString() => "boolean";
-  bool isExact() => true;
-  bool canBePrimitiveBoolean(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.nonNullExact(backend.jsBoolClass);
-  }
-}
-
-class HNumberOrNullType extends HPrimitiveOrNullType {
-  const HNumberOrNullType();
-  bool isNumberOrNull() => true;
-  String toString() => "number or null";
-  bool canBePrimitiveNumber(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.subclass(backend.jsNumberClass);
-  }
-}
-
-class HNumberType extends HPrimitiveType {
-  const HNumberType();
-  bool isNumber() => true;
-  bool isNumberOrNull() => true;
-  String toString() => "number";
-  bool canBePrimitiveNumber(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.nonNullSubclass(backend.jsNumberClass);
-  }
-}
-
-class HIntegerOrNullType extends HNumberOrNullType {
-  const HIntegerOrNullType();
-  bool isIntegerOrNull() => true;
-  String toString() => "integer or null";
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.exact(backend.jsIntClass);
-  }
-}
-
-class HIntegerType extends HNumberType {
-  const HIntegerType();
-  bool isInteger() => true;
-  bool isIntegerOrNull() => true;
-  String toString() => "integer";
-  bool isExact() => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.nonNullExact(backend.jsIntClass);
-  }
-}
-
-class HDoubleOrNullType extends HNumberOrNullType {
-  const HDoubleOrNullType();
-  bool isDoubleOrNull() => true;
-  String toString() => "double or null";
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.exact(backend.jsDoubleClass);
-  }
-}
-
-class HDoubleType extends HNumberType {
-  const HDoubleType();
-  bool isDouble() => true;
-  bool isDoubleOrNull() => true;
-  String toString() => "double";
-  bool isExact() => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return new TypeMask.nonNullExact(backend.jsDoubleClass);
+  bool containsAll(Compiler compiler) {
+    return computeMask(compiler).containsAll(compiler);
   }
 }
 
@@ -434,15 +262,19 @@
   final TypeMask mask;
   const HBoundedType(this.mask);
 
-  bool isExact() => mask.isExact;
+  bool isExact() => mask.isExact || isNull();
 
   bool canBeNull() => mask.isNullable;
 
+  bool isNull() => mask.isEmpty && mask.isNullable;
+  bool isConflicting() => mask.isEmpty && !mask.isNullable;
+
   bool canBePrimitive(Compiler compiler) {
     return canBePrimitiveNumber(compiler)
         || canBePrimitiveArray(compiler)
         || canBePrimitiveBoolean(compiler)
-        || canBePrimitiveString(compiler);
+        || canBePrimitiveString(compiler)
+        || isNull();
   }
 
   bool canBePrimitiveNumber(Compiler compiler) {
@@ -500,16 +332,52 @@
     return new HType.fromMask(mask.simplify(compiler), compiler);
   }
 
+  bool isInteger(Compiler compiler) {
+    return mask.containsOnlyInt(compiler) && !mask.isNullable;
+  }
+
+  bool isIntegerOrNull(Compiler compiler) {
+    return mask.containsOnlyInt(compiler);
+  }
+
+  bool isNumber(Compiler compiler) {
+    return mask.containsOnlyNum(compiler) && !mask.isNullable;
+  }
+
+  bool isNumberOrNull(Compiler compiler) {
+    return mask.containsOnlyNum(compiler);
+  }
+
+  bool isDouble(Compiler compiler) {
+    return mask.containsOnlyDouble(compiler) && !mask.isNullable;
+  }
+
+  bool isDoubleOrNull(Compiler compiler) {
+    return mask.containsOnlyDouble(compiler);
+  }
+
+  bool isBoolean(Compiler compiler) {
+    return mask.containsOnlyBool(compiler) && !mask.isNullable;
+  }
+
+  bool isBooleanOrNull(Compiler compiler) {
+    return mask.containsOnlyBool(compiler);
+  }
+
   bool isString(Compiler compiler) {
     return mask.containsOnlyString(compiler);
   }
 
   bool isPrimitive(Compiler compiler) {
-    return isIndexablePrimitive(compiler) && !mask.isNullable;
+    return (isPrimitiveOrNull(compiler) && !mask.isNullable)
+        || isNull();
   }
 
   bool isPrimitiveOrNull(Compiler compiler) {
-    return isIndexablePrimitive(compiler);
+    return isIndexablePrimitive(compiler)
+        || isNumberOrNull(compiler)
+        || isBooleanOrNull(compiler)
+        || isNull();
   }
 
   bool operator ==(other) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 4122364..60e6744 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -15,26 +15,6 @@
 
   SsaTypePropagator(this.compiler);
 
-  // Compute the (shared) type of the inputs if any. If all inputs
-  // have the same known type return it. If any two inputs have
-  // different known types, we'll return a conflict -- otherwise we'll
-  // simply return an unknown type.
-  HType computeInputsType(HPhi phi, bool ignoreUnknowns) {
-    HType candidateType = HType.CONFLICTING;
-    for (int i = 0, length = phi.inputs.length; i < length; i++) {
-      HType inputType = phi.inputs[i].instructionType;
-      if (inputType.isConflicting()) return HType.CONFLICTING;
-      if (ignoreUnknowns && inputType.isUnknown()) continue;
-      // Phis need to combine the incoming types using the union operation.
-      // For example, if one incoming edge has type integer and the other has
-      // type double, then the phi is either an integer or double and thus has
-      // type number.
-      candidateType = candidateType.union(inputType, compiler);
-      if (candidateType.isUnknown()) return HType.UNKNOWN;
-    }
-    return candidateType;
-  }
-
   HType computeType(HInstruction instruction) {
     return instruction.accept(this);
   }
@@ -119,9 +99,12 @@
   HType visitBinaryArithmetic(HBinaryArithmetic instruction) {
     HInstruction left = instruction.left;
     HInstruction right = instruction.right;
-    if (left.isInteger() && right.isInteger()) return HType.INTEGER;
-    if (left.isDouble()) return HType.DOUBLE;
-    return HType.NUMBER;
+    JavaScriptBackend backend = compiler.backend;    
+    if (left.isInteger(compiler) && right.isInteger(compiler)) {
+      return backend.intType;
+    }
+    if (left.isDouble(compiler)) return backend.doubleType;
+    return backend.numType;
   }
 
   HType visitNegate(HNegate instruction) {
@@ -134,24 +117,30 @@
   }
 
   HType visitPhi(HPhi phi) {
-    HType inputsType = computeInputsType(phi, false);
-    if (inputsType.isConflicting()) return HType.UNKNOWN;
-    return inputsType;
+    JavaScriptBackend backend = compiler.backend;    
+    HType candidateType = backend.emptyType;
+    for (int i = 0, length = phi.inputs.length; i < length; i++) {
+      HType inputType = phi.inputs[i].instructionType;
+      candidateType = candidateType.union(inputType, compiler);
+    }
+    return candidateType;
   }
 
   HType visitTypeConversion(HTypeConversion instruction) {
     HType inputType = instruction.checkedInput.instructionType;
     HType checkedType = instruction.checkedType;
+    JavaScriptBackend backend = compiler.backend;
     if (instruction.isArgumentTypeCheck || instruction.isReceiverTypeCheck) {
       // We must make sure a type conversion for receiver or argument check
       // does not try to do an int check, because an int check is not enough.
       // We only do an int check if the input is integer or null.
-      if (checkedType.isNumber()
-          && !checkedType.isDouble()
-          && inputType.isIntegerOrNull()) {
-        instruction.checkedType = HType.INTEGER;
-      } else if (checkedType.isInteger() && !inputType.isIntegerOrNull()) {
-        instruction.checkedType = HType.NUMBER;
+      if (checkedType.isNumber(compiler)
+          && !checkedType.isDouble(compiler)
+          && inputType.isIntegerOrNull(compiler)) {
+        instruction.checkedType = backend.intType;
+      } else if (checkedType.isInteger(compiler)
+                 && !inputType.isIntegerOrNull(compiler)) {
+        instruction.checkedType = backend.numType;
       }
     }
 
@@ -162,11 +151,13 @@
       // can be a literal double '8.0' that is marked as an integer (because 'is
       // int' will return 'true').  What we really need to do is make the
       // overlap between int and double values explicit in the HType system.
-      if (inputType.isIntegerOrNull() && checkedType.isDoubleOrNull()) {
+      if (inputType.isIntegerOrNull(compiler)
+          && checkedType.isDoubleOrNull(compiler)) {
         if (inputType.canBeNull() && checkedType.canBeNull()) {
-          outputType = HType.DOUBLE_OR_NULL;
+          outputType =
+              new HBoundedType(new TypeMask.exact(backend.jsDoubleClass));
         } else {
-          outputType = HType.DOUBLE;
+          outputType = backend.doubleType;
         }
       }
     }
@@ -196,11 +187,11 @@
     // In some cases, we want the receiver to be an integer,
     // but that does not mean we will get a NoSuchMethodError
     // if it's not: the receiver could be a double.
-    if (type.isInteger()) {
+    if (type.isInteger(compiler)) {
       // If the instruction's type is integer or null, the codegen
       // will emit a null check, which is enough to know if it will
       // hit a noSuchMethod.
-      return instruction.instructionType.isIntegerOrNull();
+      return instruction.instructionType.isIntegerOrNull(compiler);
     }
     return true;
   }
@@ -210,8 +201,8 @@
   // Return true if the receiver type check was added.
   bool checkReceiver(HInvokeDynamic instruction) {
     HInstruction receiver = instruction.inputs[1];
-    if (receiver.isNumber()) return false;
-    if (receiver.isNumberOrNull()) {
+    if (receiver.isNumber(compiler)) return false;
+    if (receiver.isNumberOrNull(compiler)) {
       convertInput(instruction,
                    receiver,
                    receiver.instructionType.nonNullable(compiler),
@@ -250,9 +241,12 @@
 
     HInstruction right = instruction.inputs[2];
     Selector selector = instruction.selector;
-    if (selector.isOperator() && receiverType.isNumber()) {
-      if (right.isNumber()) return false;
-      HType type = right.isIntegerOrNull() ? HType.INTEGER : HType.NUMBER;
+    if (selector.isOperator() && receiverType.isNumber(compiler)) {
+      if (right.isNumber(compiler)) return false;
+      JavaScriptBackend backend = compiler.backend;    
+      HType type = right.isIntegerOrNull(compiler)
+          ? backend.intType
+          : backend.numType;
       // TODO(ngeoffray): Some number operations don't have a builtin
       // variant and will do the check in their method anyway. We
       // still add a check because it allows to GVN these operations,
@@ -292,8 +286,7 @@
       // of [instruction] might move from number to dynamic.
       pendingOptimizations.putIfAbsent(instruction, () => () {
         Selector selector = instruction.selector;
-        if (selector.isOperator()
-            && selector.name != '==') {
+        if (selector.isOperator() && selector.name != '==') {
           if (checkReceiver(instruction)) {
             addAllUsersBut(instruction, instruction.inputs[1]);
           }
@@ -303,6 +296,41 @@
         }
       });
     }
+
+    HInstruction receiver = instruction.getDartReceiver(compiler);
+    HType receiverType = receiver.instructionType;
+    Selector selector = receiverType.refine(instruction.selector, compiler);
+    instruction.selector = selector;
+
+    // Try to specialize the receiver after this call.
+    if (receiver.dominatedUsers(instruction).length != 1
+        && !selector.isClosureCall()) {
+      TypeMask oldMask = receiverType.computeMask(compiler);
+      TypeMask newMask = compiler.world.allFunctions.receiverType(selector);
+      newMask = newMask.intersection(oldMask, compiler);
+
+      if (newMask != oldMask) {
+        HType newType = new HType.fromMask(newMask, compiler);
+        var next = instruction.next;
+        if (next is HTypeKnown && next.checkedInput == receiver) {
+          // We already have refined [receiver].
+          HType nextType = next.instructionType;
+          if (nextType != newType) {
+            next.knownType = next.instructionType = newType;
+            addDependentInstructionsToWorkList(next);
+          }
+        } else {
+          // Insert a refinement node after the call and update all
+          // users dominated by the call to use that node instead of
+          // [receiver].
+          HTypeKnown converted = new HTypeKnown(newType, receiver);
+          instruction.block.addBefore(instruction.next, converted);
+          receiver.replaceAllUsersDominatedBy(converted.next, converted);
+          addDependentInstructionsToWorkList(converted);
+        }
+      }
+    }
+
     return instruction.specializer.computeTypeFromInputTypes(
         instruction, compiler);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
index 2f4f70a..829012d 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
@@ -626,7 +626,7 @@
 
     void visit(HInstruction instruction) {
       Range range = instruction.accept(this);
-      if (instruction.isInteger()) {
+      if (instruction.isInteger(compiler)) {
         assert(range != null);
         ranges[instruction] = range;
       }
@@ -641,20 +641,22 @@
   }
 
   Range visitParameterValue(HParameterValue parameter) {
-    if (!parameter.isInteger()) return info.newUnboundRange();
+    if (!parameter.isInteger(compiler)) return info.newUnboundRange();
     Value value = info.newInstructionValue(parameter);
     return info.newNormalizedRange(value, value);
   }
 
   Range visitPhi(HPhi phi) {
-    if (!phi.isInteger()) return info.newUnboundRange();
+    if (!phi.isInteger(compiler)) return info.newUnboundRange();
     // Some phases may replace instructions that change the inputs of
     // this phi. Only the [SsaTypesPropagation] phase will update the
     // phi type. Play it safe by assuming the [SsaTypesPropagation]
     // phase is not necessarily run before the [ValueRangeAnalyzer].
-    if (phi.inputs.any((i) => !i.isInteger())) return info.newUnboundRange();
+    if (phi.inputs.any((i) => !i.isInteger(compiler))) {
+      return info.newUnboundRange();
+    }
     if (phi.block.isLoopHeader()) {
-      Range range = new LoopUpdateRecognizer(ranges, info).run(phi);
+      Range range = new LoopUpdateRecognizer(compiler, ranges, info).run(phi);
       if (range == null) return info.newUnboundRange();
       return range;
     }
@@ -667,14 +669,14 @@
   }
 
   Range visitConstant(HConstant constant) {
-    if (!constant.isInteger()) return info.newUnboundRange();
+    if (!constant.isInteger(compiler)) return info.newUnboundRange();
     IntConstant constantInt = constant.constant;
     Value value = info.newIntValue(constantInt.value);
     return info.newNormalizedRange(value, value);
   }
 
   Range visitFieldGet(HFieldGet fieldGet) {
-    if (!fieldGet.isInteger()) return info.newUnboundRange();
+    if (!fieldGet.isInteger(compiler)) return info.newUnboundRange();
     if (!fieldGet.receiver.isIndexable(compiler)) {
       return visitInstruction(fieldGet);
     }
@@ -693,9 +695,9 @@
     Range lengthRange = ranges[check.length];
     if (indexRange == null) {
       indexRange = info.newUnboundRange();
-      assert(!check.index.isInteger());
+      assert(!check.index.isInteger(compiler));
     }
-    assert(check.length.isInteger());
+    assert(check.length.isInteger(compiler));
 
     // Check if the index is strictly below the upper bound of the length
     // range.
@@ -749,8 +751,8 @@
   Range visitRelational(HRelational relational) {
     HInstruction right = relational.right;
     HInstruction left = relational.left;
-    if (!left.isInteger()) return info.newUnboundRange();
-    if (!right.isInteger()) return info.newUnboundRange();
+    if (!left.isInteger(compiler)) return info.newUnboundRange();
+    if (!right.isInteger(compiler)) return info.newUnboundRange();
     BinaryOperation operation = relational.operation(constantSystem);
     Range rightRange = ranges[relational.right];
     Range leftRange = ranges[relational.left];
@@ -780,7 +782,7 @@
   }
 
   Range handleBinaryOperation(HBinaryArithmetic instruction) {
-    if (!instruction.isInteger()) return info.newUnboundRange();
+    if (!instruction.isInteger(compiler)) return info.newUnboundRange();
     return instruction.operation(constantSystem).apply(
         ranges[instruction.left], ranges[instruction.right]);
   }
@@ -794,10 +796,10 @@
   }
 
   Range visitBitAnd(HBitAnd node) {
-    if (!node.isInteger()) return info.newUnboundRange();
+    if (!node.isInteger(compiler)) return info.newUnboundRange();
     HInstruction right = node.right;
     HInstruction left = node.left;
-    if (left.isInteger() && right.isInteger()) {
+    if (left.isInteger(compiler) && right.isInteger(compiler)) {
       return ranges[left] & ranges[right];
     }
 
@@ -811,9 +813,9 @@
       return info.newUnboundRange();
     }
 
-    if (left.isInteger()) {
+    if (left.isInteger(compiler)) {
       return tryComputeRange(left);
-    } else if (right.isInteger()) {
+    } else if (right.isInteger(compiler)) {
       return tryComputeRange(right);
     }
     return info.newUnboundRange();
@@ -828,7 +830,9 @@
 
   HInstruction createRangeConversion(HInstruction cursor,
                                      HInstruction instruction) {
-    HRangeConversion newInstruction = new HRangeConversion(instruction);
+    JavaScriptBackend backend = compiler.backend;
+    HRangeConversion newInstruction =
+        new HRangeConversion(instruction, backend.intType);
     conversions.add(newInstruction);
     cursor.block.addBefore(cursor, newInstruction);
     // Update the users of the instruction dominated by [cursor] to
@@ -878,8 +882,8 @@
     if (condition is HIdentity) return info.newUnboundRange();
     HInstruction right = condition.right;
     HInstruction left = condition.left;
-    if (!left.isInteger()) return info.newUnboundRange();
-    if (!right.isInteger()) return info.newUnboundRange();
+    if (!left.isInteger(compiler)) return info.newUnboundRange();
+    if (!right.isInteger(compiler)) return info.newUnboundRange();
 
     Range rightRange = ranges[right];
     Range leftRange = ranges[left];
@@ -939,9 +943,10 @@
  * Tries to find a range for the update instruction of a loop phi.
  */
 class LoopUpdateRecognizer extends HBaseVisitor {
+  final Compiler compiler;
   final Map<HInstruction, Range> ranges;
   final ValueRangeInfo info;
-  LoopUpdateRecognizer(this.ranges, this.info);
+  LoopUpdateRecognizer(this.compiler, this.ranges, this.info);
 
   Range run(HPhi loopPhi) {
     // Create a marker range for the loop phi, so that if the update
@@ -966,7 +971,7 @@
   }
 
   Range visit(HInstruction instruction) {
-    if (!instruction.isInteger()) return null;
+    if (!instruction.isInteger(compiler)) return null;
     if (ranges[instruction] != null) return ranges[instruction];
     return instruction.accept(this);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 9aa6409..338258b 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -933,21 +933,13 @@
                 new TypePromotion(node, variable, shownType);
             if (!types.isMoreSpecific(shownType, knownType)) {
               String variableName = variable.name;
-              if (types.isMoreSpecific(shownType.asRaw(), knownType)) {
-                //trace('$node');
-                typePromotion.addHint(node,
-                    MessageKind.NOT_MORE_SPECIFIC_RAW,
-                    {'variableName': variableName,
-                     'shownType': shownType,
-                     'knownType': knownType,
-                     'shownTypeRaw': shownType.asRaw()});
-              } else {
-                typePromotion.addHint(node,
-                    MessageKind.NOT_MORE_SPECIFIC,
-                    {'variableName': variableName,
-                     'shownType': shownType,
-                     'knownType': knownType});
-              }
+              // TODO(johnniwinther): Provide a how-to-fix in the case one tries
+              // to promote a generic type to a raw type.
+              typePromotion.addHint(node,
+                  MessageKind.NOT_MORE_SPECIFIC,
+                  {'variableName': variableName,
+                   'shownType': shownType,
+                   'knownType': knownType});
             }
             showTypePromotion(node, typePromotion);
           }
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
index f65de47..c2e7ada 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
@@ -100,6 +100,6 @@
   }
 
   String toString() {
-    return 'Container mask: $elementType';
+    return 'Container mask: $elementType $length';
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
index 8848fb9..c58baef 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -93,7 +93,9 @@
   }
 
   bool containsOnlyNum(Compiler compiler) {
-    return base == compiler.numClass
+    return containsOnlyInt(compiler)
+        || containsOnlyDouble(compiler)
+        || base == compiler.numClass
         || base == compiler.backend.numImplementation;
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
index 269b1b5..e6232cc 100644
--- a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
@@ -197,19 +197,36 @@
   bool get isContainer => false;
   bool get isForwarding => false;
 
-  bool containsOnlyInt(Compiler compiler) => false;
-  bool containsOnlyDouble(Compiler compiler) => false;
+  bool containsOnlyInt(Compiler compiler) {
+    return disjointMasks.every((mask) => mask.containsOnlyInt(compiler));
+  }
+
+  bool containsOnlyDouble(Compiler compiler) {
+    return disjointMasks.every((mask) => mask.containsOnlyDouble(compiler));
+  }
+
   bool containsOnlyNum(Compiler compiler) {
     return disjointMasks.every((mask) {
-      return mask.containsOnlyInt(compiler)
-          || mask.containsOnlyDouble(compiler)
-          || mask.containsOnlyNum(compiler);
+      return mask.containsOnlyNum(compiler);
     });
   }
-  bool containsOnlyNull(Compiler compiler) => false;
-  bool containsOnlyBool(Compiler compiler) => false;
-  bool containsOnlyString(Compiler compiler) => false;
-  bool containsOnly(ClassElement element) => false;
+
+  bool containsOnlyNull(Compiler compiler) {
+    return disjointMasks.every((mask) => mask.containsOnlyNull(compiler));
+  }
+
+  bool containsOnlyBool(Compiler compiler) {
+    return disjointMasks.every((mask) => mask.containsOnlyBool(compiler));
+  }
+
+  bool containsOnlyString(Compiler compiler) {
+    return disjointMasks.every((mask) => mask.containsOnlyString(compiler));
+  }
+
+  bool containsOnly(ClassElement element) {
+    return disjointMasks.every((mask) => mask.containsOnly(element));
+  }
+
   bool satisfies(ClassElement cls, Compiler compiler) {
     return disjointMasks.every((mask) => mask.satisfies(cls, compiler));
   }
@@ -218,7 +235,9 @@
     return disjointMasks.any((e) => e.contains(type, compiler));
   }
 
-  bool containsAll(Compiler compiler) => false;
+  bool containsAll(Compiler compiler) {
+    return disjointMasks.any((mask) => mask.containsAll(compiler));
+  }
 
   ClassElement singleClass(Compiler compiler) => null;
 
diff --git a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
index 522ff2b..c79f826 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
@@ -225,8 +225,8 @@
             return const TypeMask.empty();
           }
           return compiler.world.hasSubclasses(cls)
-              ? new TypeMask.nonNullSubclass(cls)
-              : new TypeMask.nonNullExact(cls);
+              ? new TypeMask.nonNullSubclass(cls.declaration)
+              : new TypeMask.nonNullExact(cls.declaration);
         }),
         compiler);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index 8470f83..5c0c9da 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -595,6 +595,10 @@
     return 'Selector($kind, $name, '
            'arity=$argumentCount$named$type)';
   }
+
+  Selector extendIfReachesAll(Compiler compiler) {
+    return new TypedSelector(compiler.typesTask.dynamicType, this);
+  }
 }
 
 class TypedSelector extends Selector {
@@ -656,4 +660,12 @@
     if (!mask.canHit(element, this, compiler)) return false;
     return appliesUntyped(element, compiler);
   }
+
+  Selector extendIfReachesAll(Compiler compiler) {
+    bool canReachAll = compiler.enabledInvokeOn
+        && mask.needsNoSuchMethodHandling(this, compiler);
+    return canReachAll
+        ? new TypedSelector(compiler.typesTask.dynamicType, this)
+        : this;
+  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index fb33d49..4b2d1c7 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -1300,6 +1300,10 @@
   static const MessageKind MIRROR_IMPORT = const MessageKind(
       "Info: Import of 'dart:mirrors'.");
 
+  static const MessageKind WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT =
+      const MessageKind(
+      "Error: Argument for 'JS_INTERCEPTOR_CONSTANT' must be a type constant.");
+
   static const MessageKind COMPILER_CRASHED = const MessageKind(
       "Error: The compiler crashed when compiling this element.");
 
@@ -1353,12 +1357,6 @@
       "'#{shownType}' because '#{shownType}' is not more specific than the "
       "known type '#{knownType}' of '#{variableName}'.");
 
-  static const MessageKind NOT_MORE_SPECIFIC_RAW = const MessageKind(
-      "Hint: Variable '#{variableName}' is not shown to have type "
-      "'#{shownType}' because '#{shownType}' is not more specific than the "
-      "known type '#{knownType}' of '#{variableName}'.",
-      howToFix: "Try replacing '#{shownType}' with '#{shownTypeRaw}'.");
-
   //////////////////////////////////////////////////////////////////////////////
   // Patch errors start.
   //////////////////////////////////////////////////////////////////////////////
diff --git a/sdk/lib/_internal/compiler/samples/darttags/darttags.dart b/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
index 347b230..4a3cd47 100644
--- a/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
+++ b/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
@@ -51,20 +51,16 @@
 RandomAccessFile output;
 Uri outputUri;
 
-main() {
-  mainWithOptions(new Options());
-}
-
-mainWithOptions(Options options) {
+main(List<String> arguments) {
   handler = new FormattingDiagnosticHandler()
       ..throwOnError = true;
 
   outputUri =
-      handler.provider.cwd.resolve(nativeToUriPath(options.arguments.first));
-  output = new File(options.arguments.first).openSync(mode: FileMode.WRITE);
+      handler.provider.cwd.resolve(nativeToUriPath(arguments.first));
+  output = new File(arguments.first).openSync(mode: FileMode.WRITE);
 
   Uri myLocation =
-      handler.provider.cwd.resolve(nativeToUriPath(options.script));
+      handler.provider.cwd.resolve(nativeToUriPath(Platform.script));
 
   // Get the names of public dart2js libraries.
   Iterable<String> names = LIBRARIES.keys.where(isPublicDart2jsLibrary);
@@ -118,7 +114,7 @@
     var lineStart = file.lineStarts[line_number - 1];
     // TODO(ahe): Most often an empty string.  Try to see if we can
     // get the position of the name token instead.
-    var tag_definition_text = file.text.substring(lineStart, byte_offset);
+    var tag_definition_text = file.slowText().substring(lineStart, byte_offset);
 
     // One definition.
     buffer.write('${tag_definition_text}\x7f${tagname}'
diff --git a/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
index 931e24b..e58ee6b 100644
--- a/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
+++ b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
@@ -32,20 +32,16 @@
 Uri outputUri;
 Uri sdkRoot;
 
-main() {
-  mainWithOptions(new Options());
-}
-
-mainWithOptions(Options options) {
+main(List<String> arguments) {
   handler = new FormattingDiagnosticHandler()
       ..throwOnError = true;
 
   outputUri =
-      handler.provider.cwd.resolve(nativeToUriPath(options.arguments.first));
-  output = new File(options.arguments.first).openSync(mode: FileMode.WRITE);
+      handler.provider.cwd.resolve(nativeToUriPath(arguments.first));
+  output = new File(arguments.first).openSync(mode: FileMode.WRITE);
 
   Uri myLocation =
-      handler.provider.cwd.resolve(nativeToUriPath(options.script));
+      handler.provider.cwd.resolve(nativeToUriPath(Platform.script));
 
   sdkRoot = myLocation.resolve(SDK_ROOT).resolve('../');
 
diff --git a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
index 31aaa55..3db4dda 100644
--- a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
+++ b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
@@ -94,8 +94,7 @@
   }
 }
 
-main() {
-  List<String> arguments = new Options().arguments;
+main(List<String> arguments) {
   if (arguments.length > 0) {
     Conversation.landingPage = arguments[0];
   }
diff --git a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
index 72c5c32..6c3ec50 100644
--- a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
@@ -27,20 +27,10 @@
 /**
  * Run this from the `lib/_internal/dartdoc` directory.
  */
-main() {
-  mainWithOptions(new Options());
-}
-
-/**
- * We use this to include dartdoc in a single snapshot with dart2js.
- * (They share 90% of the code)
- */
-mainWithOptions(Options options) {
+main(List<String> arguments) {
   // Need this because ArgParser.getUsage doesn't show command invocation.
   final USAGE = 'Usage dartdoc [options] <entrypoint(s)>\n[options] include:';
 
-  final args = options.arguments;
-
   final dartdoc = new Dartdoc();
 
   final argParser = new ArgParser();
@@ -197,7 +187,7 @@
 
   dartdoc.dartdocPath = path.join(libPath, 'lib', '_internal', 'dartdoc');
 
-  if (args.isEmpty) {
+  if (arguments.isEmpty) {
     print('No arguments provided.');
     print(USAGE);
     print(argParser.getUsage());
@@ -206,7 +196,7 @@
 
   final entrypoints = <Uri>[];
   try {
-    final option = argParser.parse(args, allowTrailingOptions: true);
+    final option = argParser.parse(arguments, allowTrailingOptions: true);
 
     // This checks to see if the root of all entrypoints is the same.
     // If it is not, then we display a warning, as package imports might fail.
diff --git a/sdk/lib/_internal/lib/foreign_helper.dart b/sdk/lib/_internal/lib/foreign_helper.dart
index ae91916..95b5907 100644
--- a/sdk/lib/_internal/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/lib/foreign_helper.dart
@@ -165,6 +165,14 @@
 JS_DART_OBJECT_CONSTRUCTOR() {}
 
 /**
+ * Returns the interceptor for class [type].  The interceptor is the type's
+ * constructor's `prototype` property.  [type] will typically be the class, not
+ * an interface, e.g. `JS_INTERCEPTOR_CONSTANT(JSInt)`, not
+ * `JS_INTERCEPTOR_CONSTANT(int)`.
+ */
+JS_INTERCEPTOR_CONSTANT(Type type) {}
+
+/**
  * Returns the prefix used for generated is checks on classes.
  */
 String JS_OPERATOR_IS_PREFIX() {}
diff --git a/sdk/lib/_internal/lib/interceptors.dart b/sdk/lib/_internal/lib/interceptors.dart
index e87ce4f..f56d424 100644
--- a/sdk/lib/_internal/lib/interceptors.dart
+++ b/sdk/lib/_internal/lib/interceptors.dart
@@ -27,7 +27,7 @@
                               lookupDispatchRecord,
                               StringMatch,
                               firstMatchAfter;
-import 'dart:_foreign_helper' show JS, JS_EFFECT;
+import 'dart:_foreign_helper' show JS, JS_EFFECT, JS_INTERCEPTOR_CONSTANT;
 import 'dart:math' show Random;
 
 part 'js_array.dart';
@@ -145,7 +145,7 @@
 
   record = lookupDispatchRecord(object);
   if (record == null) {
-    return const UnknownJavaScriptObject();
+    return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject);
   }
   setDispatchProperty(JS('', 'Object.getPrototypeOf(#)', object), record);
   return getNativeInterceptor(object);
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index ff0cf49..74c0387 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -8,6 +8,7 @@
 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS,
                                    JS,
                                    JS_CALL_IN_ISOLATE,
+                                   JS_CONST,
                                    JS_CURRENT_ISOLATE,
                                    JS_CURRENT_ISOLATE_CONTEXT,
                                    JS_DART_OBJECT_CONSTRUCTOR,
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index f6f521d..610af50 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -229,8 +229,8 @@
   bool get hasReflectedType => false;
   Type get reflectedType => throw new UnsupportedError("This type does not support reflectedTypees");
 
-  List<TypeVariableMirror> get typeVariables => throw new UnimplementedError();
-  List<TypeMirror> get typeArguments => throw new UnimplementedError();
+  List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[];
+  List<TypeMirror> get typeArguments => const <TypeMirror>[];
 
   bool get isOriginalDeclaration => true;
   TypeMirror get originalDeclaration => this;
@@ -689,7 +689,7 @@
     throw new UnimplementedError();
   }
 
-  List<TypeMirror> get typeArguments => new List();
+  List<TypeMirror> get typeArguments => const <TypeMirror>[];
 }
 
 abstract class JsObjectMirror implements ObjectMirror {
@@ -1422,7 +1422,7 @@
     return _cachedTypeVariables = new UnmodifiableListView(result);
   }
 
-  List<TypeMirror> get typeArguments => new List();
+  List<TypeMirror> get typeArguments => const <TypeMirror>[];
 }
 
 class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
diff --git a/sdk/lib/_internal/lib/mirrors_patch.dart b/sdk/lib/_internal/lib/mirrors_patch.dart
index 1254791..71c1e68 100644
--- a/sdk/lib/_internal/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/lib/mirrors_patch.dart
@@ -16,10 +16,6 @@
 
 patch MirrorSystem currentMirrorSystem() => js.currentJsMirrorSystem;
 
-patch Future<MirrorSystem> mirrorSystemOf(SendPort port) {
-  throw new UnsupportedError("MirrorSystem not implemented");
-}
-
 patch InstanceMirror reflect(Object reflectee) => js.reflect(reflectee);
 
 patch ClassMirror reflectClass(Type key) {
@@ -33,4 +29,9 @@
   return (tm as ClassMirror).originalDeclaration;
 }
 
-patch TypeMirror reflectType(Type key) => js.reflectType(key);
+patch TypeMirror reflectType(Type key) {
+  if (key == dynamic) {
+    return currentMirrorSystem().dynamicType;
+  }
+  return js.reflectType(key);
+}
diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
index b5f24ff..c85aede 100644
--- a/sdk/lib/_internal/lib/native_helper.dart
+++ b/sdk/lib/_internal/lib/native_helper.dart
@@ -4,102 +4,6 @@
 
 part of _js_helper;
 
-String typeNameInChrome(obj) {
-  String name = JS('String', "#.constructor.name", obj);
-  return typeNameInWebKitCommon(name);
-}
-
-String typeNameInSafari(obj) {
-  String name = JS('String', '#', constructorNameFallback(obj));
-  // Safari is very similar to Chrome.
-  return typeNameInWebKitCommon(name);
-}
-
-String typeNameInWebKitCommon(tag) {
-  String name = JS('String', '#', tag);
-  return name;
-}
-
-String typeNameInOpera(obj) {
-  String name = JS('String', '#', constructorNameFallback(obj));
-  return name;
-}
-
-String typeNameInFirefox(obj) {
-  String name = JS('String', '#', constructorNameFallback(obj));
-  if (name == 'BeforeUnloadEvent') return 'Event';
-  if (name == 'DataTransfer') return 'Clipboard';
-  if (name == 'GeoGeolocation') return 'Geolocation';
-  if (name == 'WorkerMessageEvent') return 'MessageEvent';
-  if (name == 'XMLDocument') return 'Document';
-  return name;
-}
-
-String typeNameInIE(obj) {
-  String name = JS('String', '#', constructorNameFallback(obj));
-  if (name == 'Document') {
-    // IE calls both HTML and XML documents 'Document', so we check for the
-    // xmlVersion property, which is the empty string on HTML documents.
-    if (JS('bool', '!!#.xmlVersion', obj)) return 'Document';
-    return 'HTMLDocument';
-  }
-  if (name == 'BeforeUnloadEvent') return 'Event';
-  if (name == 'DataTransfer') return 'Clipboard';
-  if (name == 'HTMLDDElement') return 'HTMLElement';
-  if (name == 'HTMLDTElement') return 'HTMLElement';
-  if (name == 'HTMLPhraseElement') return 'HTMLElement';
-  if (name == 'Position') return 'Geoposition';
-
-  // Patches for types which report themselves as Objects.
-  if (name == 'Object') {
-    if (JS('bool', 'window.DataView && (# instanceof window.DataView)', obj)) {
-      return 'DataView';
-    }
-  }
-  return name;
-}
-
-String constructorNameFallback(object) {
-  if (object == null) return 'Null';
-  var constructor = JS('var', "#.constructor", object);
-  if (identical(JS('String', "typeof(#)", constructor), 'function')) {
-    var name = JS('var', r'#.builtin$cls', constructor);
-    if (name != null) return name;
-    // The constructor isn't null or undefined at this point. Try
-    // to grab hold of its name.
-    name = JS('var', '#.name', constructor);
-    // If the name is a non-empty string, we use that as the type
-    // name of this object. On Firefox, we often get 'Object' as
-    // the constructor name even for more specialized objects so
-    // we have to fall through to the toString() based implementation
-    // below in that case.
-    if (name is String
-        && !identical(name, '')
-        && !identical(name, 'Object')
-        && !identical(name, 'Function.prototype')) {  // Can happen in Opera.
-      return name;
-    }
-  }
-  String string = JS('String', 'Object.prototype.toString.call(#)', object);
-  return JS('String', '#.substring(8, # - 1)', string, string.length);
-}
-
-/**
- * If a lookup on an object [object] that has [tag] fails, this function is
- * called to provide an alternate tag.  This allows us to fail gracefully if we
- * can make a good guess, for example, when browsers add novel kinds of
- * HTMLElement that we have never heard of.
- */
-String alternateTag(object, String tag) {
-  // Does it smell like some kind of HTML element?
-  if (JS('bool', r'!!/^HTML[A-Z].*Element$/.test(#)', tag)) {
-    // Check that it is not a simple JavaScript object.
-    String string = JS('String', 'Object.prototype.toString.call(#)', object);
-    if (string == '[object Object]') return null;
-    return 'HTMLElement';
-  }
-  return null;
-}
 
 // TODO(ngeoffray): stop using this method once our optimizers can
 // change str1.contains(str2) into str1.indexOf(str2) != -1.
@@ -139,77 +43,29 @@
   return JS('var', '{}');
 }
 
-Function getTypeNameOf = getFunctionForTypeNameOf();
+/**
+ * Returns a String tag identifying the type of the native object, or `null`.
+ * The tag is not the name of the type, but usually the name of the JavaScript
+ * constructor function.
+ */
+Function getTagFunction;
 
 /**
- * Returns the function to use to get the type name (i.e. dispatch tag) of an
- * object.
+ * If a lookup via [getTagFunction] on an object [object] that has [tag] fails,
+ * this function is called to provide an alternate tag.  This allows us to fail
+ * gracefully if we can make a good guess, for example, when browsers add novel
+ * kinds of HTMLElement that we have never heard of.
  */
-Function getFunctionForTypeNameOf() {
-  var getTagFunction = getBaseFunctionForTypeNameOf();
-  if (JS('bool', 'typeof dartExperimentalFixupGetTag == "function"')) {
-    return applyExperimentalFixup(
-        JS('', 'dartExperimentalFixupGetTag'), getTagFunction);
-  }
-  return getTagFunction;
-}
-
-/// Don't call directly, use [getFunctionForTypeNameOf] instead.
-Function getBaseFunctionForTypeNameOf() {
-  // If we're not in the browser, we're almost certainly running on v8.
-  if (!identical(JS('String', 'typeof(navigator)'), 'object')) {
-    return typeNameInChrome;
-  }
-
-  String userAgent = JS('String', "navigator.userAgent");
-  // TODO(antonm): remove a reference to DumpRenderTree.
-  if (contains(userAgent, 'Chrome') || contains(userAgent, 'DumpRenderTree')) {
-    return typeNameInChrome;
-  } else if (contains(userAgent, 'Firefox')) {
-    return typeNameInFirefox;
-  } else if (contains(userAgent, 'Trident/')) {
-    return typeNameInIE;
-  } else if (contains(userAgent, 'Opera')) {
-    return typeNameInOpera;
-  } else if (contains(userAgent, 'AppleWebKit')) {
-    // Chrome matches 'AppleWebKit' too, but we test for Chrome first, so this
-    // is not a problem.
-    // Note: Just testing for "Safari" doesn't work when the page is embedded
-    // in a UIWebView on iOS 6.
-    return typeNameInSafari;
-  } else {
-    return constructorNameFallback;
-  }
-}
-
-Function applyExperimentalFixup(fixupJSFunction,
-                                Function originalGetTagDartFunction) {
-  var originalGetTagJSFunction =
-      convertDartClosure1ArgToJSNoDataConversions(
-          originalGetTagDartFunction);
-
-  var newGetTagJSFunction =
-      JS('', '#(#)', fixupJSFunction, originalGetTagJSFunction);
-
-  String newGetTagDartFunction(object) =>
-      JS('', '#(#)', newGetTagJSFunction, object);
-
-  return newGetTagDartFunction;
-}
-
-callDartFunctionWith1Arg(fn, arg) => fn(arg);
-
-convertDartClosure1ArgToJSNoDataConversions(dartClosure) {
-  return JS('',
-      '(function(invoke, closure){'
-        'return function(arg){ return invoke(closure, arg); };'
-      '})(#, #)',
-      DART_CLOSURE_TO_JS(callDartFunctionWith1Arg), dartClosure);
-}
+Function alternateTagFunction;
 
 
 String toStringForNativeObject(var obj) {
-  String name = JS('String', '#', getTypeNameOf(obj));
+  // TODO(sra): Is this code dead?
+  // [getTagFunction] might be uninitialized, but in usual usage, toString has
+  // been called via an interceptor and initialized it.
+  String name = getTagFunction == null
+      ? '<Unknown>'
+      : JS('String', '#', getTagFunction(obj));
   return 'Instance of $name';
 }
 
@@ -237,16 +93,15 @@
 /**
  * A JavaScript object mapping tags to the constructors of interceptors.
  *
- * Example: 'HTMLImageElement' maps to the ImageElement native class
- * constructor.
+ * Example: 'HTMLImageElement' maps to the ImageElement class constructor.
  */
 get interceptorsByTag => JS('=Object', 'init.interceptorsByTag');
 
 /**
  * A JavaScript object mapping tags to `true` or `false`.
  *
- * Example: 'HTMLImageElement' maps to `true` since, as since there are no
- * subclasses of ImageElement, it is a leaf class in the native class hierarchy.
+ * Example: 'HTMLImageElement' maps to `true` since, as there are no subclasses
+ * of ImageElement, it is a leaf class in the native class hierarchy.
  */
 get leafTags => JS('=Object', 'init.leafTags');
 
@@ -266,11 +121,11 @@
   var hasOwnPropertyFunction = JS('var', 'Object.prototype.hasOwnProperty');
   var interceptorClass = null;
   assert(!isDartObject(obj));
-  String tag = getTypeNameOf(obj);
+  String tag = getTagFunction(obj);
 
   interceptorClass = lookupInterceptor(hasOwnPropertyFunction, tag);
   if (interceptorClass == null) {
-    String secondTag = alternateTag(obj, tag);
+    String secondTag = alternateTagFunction(obj, tag);
     if (secondTag != null) {
       interceptorClass = lookupInterceptor(hasOwnPropertyFunction, secondTag);
     }
@@ -310,11 +165,27 @@
   }
 }
 
+/**
+ * [proto] should have no shadowing prototypes that are not also assigned a
+ * dispatch rescord.
+ */
+setNativeSubclassDispatchRecord(proto, interceptor) {
+  setDispatchProperty(proto, makeLeafDispatchRecord(interceptor));
+}
+
+String constructorNameFallback(object) {
+  return JS('String', '#(#)', _constructorNameFallback, object);
+}
+
+
 var initNativeDispatchFlag;  // null or true
 
 void initNativeDispatch() {
+  if (true == initNativeDispatchFlag) return;
   initNativeDispatchFlag = true;
 
+  initHooks();
+
   // Try to pro-actively patch prototypes of DOM objects.  For each of our known
   // tags `TAG`, if `window.TAG` is a (constructor) function, set the dispatch
   // property if the function's prototype to a dispatch record.
@@ -341,9 +212,253 @@
 
 
 /**
- * [proto] should have no shadowing prototypes that are not also assigned a
- * dispatch rescord.
+ * Initializes [getTagFunction] and [alternateTagFunction].
+ *
+ * These functions are 'hook functions', collectively 'hooks'.  They initialized
+ * by applying a series of hooks transformers.  Built-in hooks transformers deal
+ * with various known browser behaviours.
+ *
+ * Each hook tranformer takes a 'hooks' input which is a JavaScript object
+ * containing the hook functions, and returns the same or a new object with
+ * replacements.  The replacements can wrap the originals to provide alternate
+ * or modified behaviour.
+ *
+ *     { getTag: function(obj) {...},
+ *       getUnknownTag: function(obj, tag) {...},
+ *       discriminator: function(tag) {...},
+ *      }
+ *
+ * * getTag(obj) returns the dispatch tag, or `null`.
+ * * getUnknownTag(obj, tag) returns a tag when [getTag] fails.
+ * * discriminator returns a function TBD.
+ *
+ * The web site can adapt a dart2js application by loading code ahead of the
+ * dart2js application that defines hook transformers to be after the built in
+ * ones.  Code defining a transformer HT should use the following pattern to
+ * ensure multiple transformers can be composed:
+ *
+ *     (dartNativeDispatchHooksTransformer =
+ *      window.dartNativeDispatchHooksTransformer || []).push(HT);
+ *
+ *
+ * TODO: Implement and describe dispatch tags and their caching methods.
  */
-setNativeSubclassDispatchRecord(proto, interceptor) {
-  setDispatchProperty(proto, makeLeafDispatchRecord(interceptor));
+void initHooks() {
+  // The initial simple hooks:
+  var hooks = JS('', '#()', _baseHooks);
+
+  // Customize for browsers where `object.constructor.name` fails:
+  var _fallbackConstructorHooksTransformer =
+      JS('', '#(#)', _fallbackConstructorHooksTransformerGenerator,
+          _constructorNameFallback);
+  hooks = applyHooksTransformer(_fallbackConstructorHooksTransformer, hooks);
+
+  // Customize for browsers:
+  hooks = applyHooksTransformer(_firefoxHooksTransformer, hooks);
+  hooks = applyHooksTransformer(_ieHooksTransformer, hooks);
+  hooks = applyHooksTransformer(_operaHooksTransformer, hooks);
+  hooks = applyHooksTransformer(_safariHooksTransformer, hooks);
+
+  // TODO(sra): Update ShadowDOM polyfil to use
+  // [dartNativeDispatchHooksTransformer] and remove this hook.
+  hooks = applyHooksTransformer(_dartExperimentalFixupGetTagHooksTransformer,
+      hooks);
+
+  // Apply global hooks.
+  //
+  // If defined, dartNativeDispatchHookdTransformer should be a single function
+  // of a JavaScript Array of functions.
+
+  if (JS('bool', 'typeof dartNativeDispatchHooksTransformer != "undefined"')) {
+    var transformers = JS('', 'dartNativeDispatchHooksTransformer');
+    if (JS('bool', 'typeof # == "function"', transformers)) {
+      transformers = [transformers];
+    }
+    if (JS('bool', '#.constructor == Array', transformers)) {
+      for (int i = 0; i < JS('int', '#.length', transformers); i++) {
+        var transformer = JS('', '#[#]', transformers, i);
+        if (JS('bool', 'typeof # == "function"', transformer)) {
+          hooks = applyHooksTransformer(transformer, hooks);
+        }
+      }
+    }
+  }
+
+  var getTag = JS('', '#.getTag', hooks);
+  var getUnknownTag = JS('', '#.getUnknownTag', hooks);
+
+  getTagFunction = (o) => JS('String|Null', '#(#)', getTag, o);
+  alternateTagFunction =
+      (o, String tag) => JS('String|Null', '#(#, #)', getUnknownTag, o, tag);
 }
+
+applyHooksTransformer(transformer, hooks) {
+  var newHooks = JS('=Object|Null', '#(#)', transformer, hooks);
+  return JS('', '# || #', newHooks, hooks);
+}
+
+
+// JavaScript code fragments.
+//
+// This is a temporary place for the JavaScript code.
+//
+// TODO(sra): These code fragments are not minified.  They could be generated by
+// the code emitter, or JS_CONST could be improved to parse entire functions and
+// take care of the minification.
+
+const _baseHooks = const JS_CONST(r'''
+function() {
+  function typeNameInChrome(obj) { return obj.constructor.name; }
+  function getUnknownTag(object, tag) {
+    // This code really belongs in [getUnknownTagGenericBrowser] but having it
+    // here allows [getUnknownTag] to be tested on d8.
+    if (/^HTML[A-Z].*Element$/.test(tag)) {
+      // Check that it is not a simple JavaScript object.
+      var name = Object.prototype.toString.call(object);
+      if (name == "[object Object]") return null;
+      return "HTMLElement";
+    }
+  }
+  function getUnknownTagGenericBrowser(object, tag) {
+    if (object instanceof HTMLElement) return "HTMLElement";
+    return getUnknownTag(object, tag);
+  }
+  function discriminator(tag) { return null; }
+
+  var isBrowser = typeof navigator == "object";
+
+  return {
+    getTag: typeNameInChrome,
+    getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag,
+    discriminator: discriminator };
+}''');
+
+
+/**
+ * Returns the name of the constructor function for browsers where
+ * `object.constructor.name` is not reliable.
+ *
+ * This function is split out of [_fallbackConstructorHooksTransformerGenerator]
+ * as it is called from both the dispatch hooks and via
+ * [constructorNameFallback] from objectToString.
+ */
+const _constructorNameFallback = const JS_CONST(r'''
+function getTagFallback(o) {
+  if (o == null) return "Null";
+  var constructor = o.constructor;
+  if (typeof constructor == "function") {
+    var name = constructor.builtin$cls;
+    if (typeof name == "string") return name;
+    // The constructor is not null or undefined at this point. Try
+    // to grab hold of its name.
+    name = constructor.name;
+    // If the name is a non-empty string, we use that as the type name of this
+    // object. On Firefox, we often get "Object" as the constructor name even
+    // for more specialized objects so we have to fall through to the toString()
+    // based implementation below in that case.
+    if (typeof name == "string"
+        && name !== ""
+        && name !== "Object"
+        && name !== "Function.prototype") {  // Can happen in Opera.
+      return name;
+    }
+  }
+  var s = Object.prototype.toString.call(o);
+  return s.substring(8, s.length - 1);
+}''');
+
+
+const _fallbackConstructorHooksTransformerGenerator = const JS_CONST(r'''
+function(getTagFallback) {
+  return function(hooks) {
+    // If we are not in a browser, assume we are in d8.
+    // TODO(sra): Recognize jsshell.
+    if (typeof navigator != "object") return hooks;
+
+    var userAgent = navigator.userAgent;
+    // TODO(antonm): remove a reference to DumpRenderTree.
+    if (userAgent.indexOf("Chrome") >= 0 ||
+        userAgent.indexOf("DumpRenderTree") >= 0) {
+      return hooks;
+    }
+
+    hooks.getTag = getTagFallback;
+  };
+}''');
+
+
+const _ieHooksTransformer = const JS_CONST(r'''
+function(hooks) {
+  var userAgent = typeof navigator == "object" ? navigator.userAgent : "";
+  if (userAgent.indexOf("Trident/") == -1) return hooks;
+
+  var getTag = hooks.getTag;
+
+  var quickMap = {
+    "BeforeUnloadEvent": "Event",
+    "DataTransfer": "Clipboard",
+    "HTMLDDElement": "HTMLElement",
+    "HTMLDTElement": "HTMLElement",
+    "HTMLPhraseElement": "HTMLElement",
+    "Position": "Geoposition"
+  };
+
+  function getTagIE(o) {
+    var tag = getTag(o);
+    var newTag = quickMap[tag];
+    if (newTag) return newTag;
+    if (tag == "Document") {
+      // IE calls both HTML and XML documents "Document", so we check for the
+      // xmlVersion property, which is the empty string on HTML documents.
+      if (!!o.xmlVersion) return "Document";
+      return "HTMLDocument";
+    }
+    // Patches for types which report themselves as Objects.
+    if (tag == "Object") {
+      if (window.DataView && (o instanceof window.DataView)) return "DataView";
+    }
+    return tag;
+  }
+
+  hooks.getTag = getTagIE;
+}''');
+
+
+const _firefoxHooksTransformer = const JS_CONST(r'''
+function(hooks) {
+  var userAgent = typeof navigator == "object" ? navigator.userAgent : "";
+  if (userAgent.indexOf("Firefox") == -1) return hooks;
+
+  var getTag = hooks.getTag;
+
+  var quickMap = {
+    "BeforeUnloadEvent": "Event",
+    "DataTransfer": "Clipboard",
+    "GeoGeolocation": "Geolocation",
+    "WorkerMessageEvent": "MessageEvent",
+    "XMLDocument": "Document"};
+
+  function getTagFirefox(o) {
+    var tag = getTag(o);
+    return quickMap[tag] || tag;
+  }
+
+  hooks.getTag = getTagFirefox;
+}''');
+
+
+const _operaHooksTransformer = const JS_CONST(r'''
+function(hooks) { return hooks; }
+''');
+
+
+const _safariHooksTransformer = const JS_CONST(r'''
+function(hooks) { return hooks; }
+''');
+
+
+const _dartExperimentalFixupGetTagHooksTransformer = const JS_CONST(r'''
+function(hooks) {
+  if (typeof dartExperimentalFixupGetTag != "function") return hooks;
+  hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag);
+}''');
diff --git a/sdk/lib/_internal/lib/platform_patch.dart b/sdk/lib/_internal/lib/platform_patch.dart
deleted file mode 100644
index 13fdeb8..0000000
--- a/sdk/lib/_internal/lib/platform_patch.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2013, 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.
-
-patch int get numberOfProcessors => null;
-
-patch String get pathSeparator => '/';
-
-patch String get operatingSystem => null;
-
-patch String get localHostname => null;
-
-patch String get version => null;
-
-patch Map<String, String> get environment => null;
-
-patch String get executable => null;
-
-patch Uri get script => null;
-
-// An unmodifiable list.
-patch List<String> get executableArguments => new List<String>(0);
-
-patch String get packageRoot => null;
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 6aa24dd..0c9925f 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -101,11 +101,6 @@
       documented: false,
       platforms: VM_PLATFORM),
 
-  "platform": const LibraryInfo(
-      "platform/platform.dart",
-      maturity: Maturity.UNSTABLE,
-      dart2jsPatchPath: "_internal/lib/platform_patch.dart"),
-
   "typed_data": const LibraryInfo(
       "typed_data/typed_data.dart",
       maturity: Maturity.STABLE,
diff --git a/sdk/lib/_internal/pub/bin/pub.dart b/sdk/lib/_internal/pub/bin/pub.dart
index ecd58bd..ca88d38 100644
--- a/sdk/lib/_internal/pub/bin/pub.dart
+++ b/sdk/lib/_internal/pub/bin/pub.dart
@@ -18,11 +18,11 @@
 
 final pubArgParser = initArgParser();
 
-void main() {
+void main(List<String> arguments) {
   ArgResults options;
 
   try {
-    options = pubArgParser.parse(new Options().arguments);
+    options = pubArgParser.parse(arguments);
   } on FormatException catch (e) {
     log.error(e.message);
     log.error('Run "pub help" to see available options.');
@@ -84,7 +84,7 @@
   }
 
   validatePlatform().then((_) {
-    PubCommand.commands[options.command.name].run(cacheDir, options);
+    PubCommand.commands[options.command.name].run(cacheDir, options, arguments);
   });
 }
 
diff --git a/sdk/lib/_internal/pub/lib/src/barback.dart b/sdk/lib/_internal/pub/lib/src/barback.dart
index a78f7b8..84a069a 100644
--- a/sdk/lib/_internal/pub/lib/src/barback.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback.dart
@@ -10,10 +10,10 @@
 import 'package:path/path.dart' as path;
 
 import 'barback/load_all_transformers.dart';
-import 'barback/pub_barback_logger.dart';
 import 'barback/pub_package_provider.dart';
 import 'barback/server.dart';
-import 'barback/watch_sources.dart';
+import 'barback/sources.dart';
+import 'log.dart' as log;
 import 'package_graph.dart';
 import 'utils.dart';
 
@@ -103,43 +103,54 @@
 ///
 /// If [builtInTransformers] is provided, then a phase is added to the end of
 /// each package's cascade including those transformers.
+///
+/// If [watchForUpdates] is true (the default), the server will continually
+/// monitor the app and its dependencies for any updates. Otherwise the state of
+/// the app when the server is started will be maintained.
 Future<BarbackServer> createServer(String host, int port, PackageGraph graph,
-    {Iterable<Transformer> builtInTransformers}) {
+    {Iterable<Transformer> builtInTransformers, bool watchForUpdates: true}) {
   var provider = new PubPackageProvider(graph);
-  var logger = new PubBarbackLogger();
-  var barback = new Barback(provider, logger: logger);
+  var barback = new Barback(provider);
+
+  barback.log.listen(_log);
 
   return BarbackServer.bind(host, port, barback, graph.entrypoint.root.name)
       .then((server) {
-    watchSources(graph, barback);
+    return new Future.sync(() {
+      if (watchForUpdates) return watchSources(graph, barback);
+      loadSources(graph, barback);
+    }).then((_) {
+      var completer = new Completer();
 
-    var completer = new Completer();
+      // If any errors get emitted either by barback or by the server, including
+      // non-programmatic barback errors, they should take down the whole
+      // program.
+      var subscriptions = [
+        server.barback.errors.listen((error) {
+          if (error is TransformerException) error = error.error;
+          if (!completer.isCompleted) completer.completeError(error);
+        }),
+        server.barback.results.listen((_) {}, onError: (error, stackTrace) {
+          if (completer.isCompleted) return;
+          completer.completeError(error, stackTrace);
+        }),
+        server.results.listen((_) {}, onError: (error, stackTrace) {
+          if (completer.isCompleted) return;
+          completer.completeError(error, stackTrace);
+        })
+      ];
 
-    // If any errors get emitted either by barback or by the server, including
-    // non-programmatic barback errors, they should take down the whole program.
-    var subscriptions = [
-      server.barback.errors.listen((error) {
-        if (error is TransformerException) error = error.error;
-        if (!completer.isCompleted) completer.completeError(error);
-      }),
-      server.barback.results.listen((_) {}, onError: (error, stackTrace) {
+      loadAllTransformers(server, graph, builtInTransformers).then((_) {
+        if (!completer.isCompleted) completer.complete(server);
+      }).catchError((error, stackTrace) {
         if (!completer.isCompleted) completer.completeError(error, stackTrace);
-      }),
-      server.results.listen((_) {}, onError: (error, stackTrace) {
-        if (!completer.isCompleted) completer.completeError(error, stackTrace);
-      })
-    ];
+      });
 
-    loadAllTransformers(server, graph, builtInTransformers).then((_) {
-      if (!completer.isCompleted) completer.complete(server);
-    }).catchError((error, stackTrace) {
-      if (!completer.isCompleted) completer.completeError(error, stackTrace);
-    });
-
-    return completer.future.whenComplete(() {
-      for (var subscription in subscriptions) {
-        subscription.cancel();
-      }
+      return completer.future.whenComplete(() {
+        for (var subscription in subscriptions) {
+          subscription.cancel();
+        }
+      });
     });
   });
 }
@@ -239,3 +250,56 @@
       throw new FormatException('Cannot access assets from "$dir".');
   }
 }
+
+/// Log [entry] using Pub's logging infrastructure.
+///
+/// Since both [LogEntry] objects and the message itself often redundantly
+/// show the same context like the file where an error occurred, this tries
+/// to avoid showing redundant data in the entry.
+void _log(LogEntry entry) {
+  messageMentions(String text) {
+    return entry.message.toLowerCase().contains(text.toLowerCase());
+  }
+
+  var prefixParts = [];
+
+  // Show the level (unless the message mentions it).
+  if (!messageMentions(entry.level.name)) {
+    prefixParts.add("${entry.level} in");
+  }
+
+  // Show the transformer.
+  prefixParts.add(entry.transform.transformer);
+
+  // Mention the primary input of the transform unless the message seems to.
+  if (!messageMentions(entry.transform.primaryId.path)) {
+    prefixParts.add("on ${entry.transform.primaryId}");
+  }
+
+  // If the relevant asset isn't the primary input, mention it unless the
+  // message already does.
+  if (entry.assetId != entry.transform.primaryId &&
+      !messageMentions(entry.assetId.path)) {
+    prefixParts.add("with input ${entry.assetId}");
+  }
+
+  var prefix = "[${prefixParts.join(' ')}]:";
+  var message = entry.message;
+  if (entry.span != null) {
+    message = entry.span.getLocationMessage(entry.message);
+  }
+
+  switch (entry.level) {
+    case LogLevel.ERROR:
+      log.error("${log.red(prefix)}\n$message");
+      break;
+
+    case LogLevel.WARNING:
+      log.warning("${log.yellow(prefix)}\n$message");
+      break;
+
+    case LogLevel.INFO:
+      log.message("$prefix\n$message");
+      break;
+  }
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
index d79cec7..293ac2f 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
@@ -26,12 +26,16 @@
 class Dart2JSTransformer extends Transformer {
   final PackageGraph _graph;
 
+  /// Whether the JavaScript output should be minified.
+  final bool _minify;
+
   /// The [AssetId]s the transformer has discovered so far. Used by pub build
   /// to determine where to copy the JS bootstrap files.
   // TODO(rnystrom): Do something cleaner for this, or eliminate those files.
   final entrypoints = new Set<AssetId>();
 
-  Dart2JSTransformer(this._graph);
+  Dart2JSTransformer(this._graph, {bool minify})
+      : _minify = minify == true ? true : false;
 
   /// Only ".dart" files within "web/" are processed.
   Future<bool> isPrimary(Asset asset) {
@@ -77,20 +81,20 @@
       // path so they can understand them.
       return dart.compile(entrypoint,
           packageRoot: packageRoot,
+          minify: _minify,
           inputProvider: provider.readStringFromUri,
           diagnosticHandler: provider.handleDiagnostic).then((js) {
-        if (js == null) {
-          // The compile failed and errors should have already been reported
-          // through the diagnostic handler, so just do nothing here.
-          return;
-        }
-
         var id = transform.primaryInput.id.changeExtension(".dart.js");
         transform.addOutput(new Asset.fromString(id, js));
 
         stopwatch.stop();
         transform.logger.info("Generated $id (${js.length} characters) in "
             "${stopwatch.elapsed}");
+      }).catchError((error) {
+        // The compile failed and errors have been reported through the
+        // diagnostic handler, so just do nothing here.
+        if (error is CompilerException) return;
+        throw error;
       });
     });
   }
diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
index 3eb02b7..621e85a 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
@@ -32,16 +32,16 @@
 import 'http://<<HOST_AND_PORT>>/packages/barback/barback.dart';
 
 /// Sets up the initial communication with the host isolate.
-void main(List<String> args, SendPort replyTo) {
+void main(_, SendPort replyTo) {
   var port = new ReceivePort();
-  replyTo.send(['success', port.sendPort]);
-  port.listen((args) {
-    _sendFuture(args['replyTo'], new Future.sync(() {
-      var library = Uri.parse(args['library']);
-      var configuration = JSON.decode(args['configuration']);
+  replyTo.send(port.sendPort);
+  port.first.then((wrappedMessage) {
+    _respond(wrappedMessage, (message) {
+      var library = Uri.parse(message['library']);
+      var configuration = JSON.decode(message['configuration']);
       return initialize(library, configuration).
           map(_serializeTransformerOrGroup).toList();
-    }));
+    });
   });
 }
 
@@ -103,7 +103,7 @@
       : _port = transform['port'],
         primaryInput = _deserializeAsset(transform['primaryInput']) {
     _logger = new TransformLogger((assetId, level, message, span) {
-      _port.send({
+      _call(_port, {
         'type': 'log',
         'level': level.name,
         'message': message,
@@ -114,7 +114,7 @@
   }
 
   Future<Asset> getInput(AssetId id) {
-    return _callAndReceiveFuture(_port, {
+    return _call(_port, {
       'type': 'getInput',
       'id': _serializeId(id)
     }).then(_deserializeAsset);
@@ -129,7 +129,7 @@
       _futureStream(getInput(id).then((input) => input.read()));
 
   void addOutput(Asset output) {
-    _port.send({
+    _call(_port, {
       'type': 'addOutput',
       'output': _serializeAsset(output)
     });
@@ -183,9 +183,8 @@
 /// Converts [transformer] into a serializable map.
 Map _serializeTransformer(Transformer transformer) {
   var port = new ReceivePort();
-  port.listen((message) {
-    var replyTo = message['replyTo'];
-    _sendFuture(replyTo, new Future.sync(() {
+  port.listen((wrappedMessage) {
+    _respond(wrappedMessage, (message) {
       if (message['type'] == 'isPrimary') {
         return transformer.isPrimary(_deserializeAsset(message['asset']));
       } else {
@@ -193,7 +192,7 @@
         return transformer.apply(
             new ForeignTransform(message['transform']));
       }
-    }));
+    });
   });
 
   return {
@@ -214,29 +213,45 @@
   };
 }
 
-/// When the input receives a 'done' as data-event, transforms it to a
-/// done event and cancels the subscription.
-StreamSubscription doneTransformer(Stream input, bool cancelOnError) {
+/// Converts a serializable map into an [Asset].
+Asset _deserializeAsset(Map asset) {
+  return new Asset.fromStream(
+      _deserializeId(asset['id']),
+      _deserializeStream(asset['stream']));
+}
+
+/// The body of a [StreamTransformer] that deserializes the values in a stream
+/// sent by [_serializeStream].
+StreamSubscription _deserializeTransformer(Stream input, bool cancelOnError) {
   var subscription;
   var transformed = input.transform(new StreamTransformer.fromHandlers(
       handleData: (data, sink) {
-        if (data == 'done') {
-          sink.close();
-          subscription.cancel();
-        } else {
-          sink.add(data);
-        }
-      }));
+    if (data['type'] == 'data') {
+      sink.add(data['data']);
+    } else if (data['type'] == 'error') {
+      sink.addError(CrossIsolateException.deserialize(data['error']));
+    } else {
+      assert(data['type'] == 'done');
+      sink.close();
+      subscription.cancel();
+    }
+  }));
   subscription = transformed.listen(null, cancelOnError: cancelOnError);
   return subscription;
 }
 
-/// Converts a serializable map into an [Asset].
-Asset _deserializeAsset(Map asset) {
-  var receivePort = new ReceivePort();
-  asset['sendPort'].send(receivePort.sendPort);
-  var stream = receivePort.transform(const StreamTransformer(doneTransformer));
-  return new Asset.fromStream(_deserializeId(asset['id']), stream);
+/// Convert a [SendPort] whose opposite is waiting to send us a stream into a
+/// [Stream].
+///
+/// No stream data will actually be sent across the isolate boundary until
+/// someone subscribes to the returned stream.
+Stream _deserializeStream(SendPort sendPort) {
+  return callbackStream(() {
+    var receivePort = new ReceivePort();
+    sendPort.send(receivePort.sendPort);
+    return receivePort.transform(
+        const StreamTransformer(_deserializeTransformer));
+  });
 }
 
 /// Converts a serializable map into an [AssetId].
@@ -244,23 +259,30 @@
 
 /// Converts [asset] into a serializable map.
 Map _serializeAsset(Asset asset) {
-  // We can't send IsolateStreams (issue 12437), so instead we send a sink and
-  // get the isolate to send us back another sink.
-  var receivePort = new ReceivePort();
-  receivePort.first.then((sendPort) {
-    asset.read().listen(sendPort.send,
-        onError: (error, stackTrace) {
-          throw new UnimplementedError('Error during asset serialization');
-        },
-        onDone: () { sendPort.send('done'); });
-  });
-
   return {
     'id': _serializeId(asset.id),
-    'sendPort': receivePort.sendPort
+    'stream': _serializeStream(asset.read())
   };
 }
 
+/// Converts [stream] into a [SendPort] with which another isolate can request
+/// the data from [stream].
+SendPort _serializeStream(Stream stream) {
+  var receivePort = new ReceivePort();
+  receivePort.first.then((sendPort) {
+    stream.listen((data) => sendPort.send({'type': 'data', 'data': data}),
+        onDone: () => sendPort.send({'type': 'done'}),
+        onError: (error, stackTrace) {
+      sendPort.send({
+        'type': 'error',
+        'error': CrossIsolateException.serialize(error, stackTrace)
+      });
+    });
+  });
+
+  return receivePort.sendPort;
+}
+
 /// Converts [id] into a serializable map.
 Map _serializeId(AssetId id) => {'package': id.package, 'path': id.path};
 
@@ -288,33 +310,42 @@
   };
 }
 
-/// Sends the result of [future] through [port].
+/// Responds to a message sent by [_call].
 ///
-/// This should be received on the other end using [_receiveFuture]. It
-/// re-raises any exceptions on the other side as [CrossIsolateException]s.
-void _sendFuture(SendPort port, Future future) {
-  future.then((result) {
-    port.send({'success': result});
-  }).catchError((error) {
+/// [wrappedMessage] is the raw message sent by [_call]. This unwraps it and
+/// passes the contents of the message to [callback], then sends the return
+/// value of [callback] back to [_call]. If [callback] returns a Future or
+/// throws an error, that will also be sent.
+void _respond(wrappedMessage, callback(message)) {
+  var replyTo = wrappedMessage['replyTo'];
+  new Future.sync(() => callback(wrappedMessage['message']))
+      .then((result) => replyTo.send({'type': 'success', 'value': result}))
+      .catchError((error, stackTrace) {
     // TODO(nweiz): at least MissingInputException should be preserved here.
-    port.send({'error': CrossIsolateException.serialize(error)});
+    replyTo.send({
+      'type': 'error',
+      'error': CrossIsolateException.serialize(error, stackTrace)
+    });
   });
 }
 
-/// Receives the result of [_sendFuture] from [portCall], which should be the
-/// return value of [SendPort.call].
+/// Wraps [message] and sends it across [port], then waits for a response which
+/// should be sent using [_respond].
 ///
-/// The [message] argument is modified to include the [replyTo] port.
-Future _callAndReceiveFuture(SendPort port, Map message) {
-  var responsePort = new ReceivePort();
-  message['replyTo'] = responsePort.sendPort;
-  return new Future.sync(() {
-    port.send(message);
-    return responsePort.first.then((response) {
-      if (response.containsKey('success')) return response['success'];
-      return new Future.error(
-          new CrossIsolateException.deserialize(response['error']));
-    });
+/// The returned Future will complete to the value or error returned by
+/// [_respond].
+Future _call(SendPort port, message) {
+  var receivePort = new ReceivePort();
+  port.send({
+    'message': message,
+    'replyTo': receivePort.sendPort
+  });
+
+  return receivePort.first.then((response) {
+    if (response['type'] == 'success') return response['value'];
+    assert(response['type'] == 'error');
+    return new Future.error(
+        new CrossIsolateException.deserialize(response['error']));
   });
 }
 
@@ -392,6 +423,21 @@
   });
   return controller.stream;
 }
+
+Stream callbackStream(Stream callback()) {
+  var subscription;
+  var controller;
+  controller = new StreamController(onListen: () {
+    subscription = callback().listen(controller.add,
+        onError: controller.addError,
+        onDone: controller.close);
+  },
+      onCancel: () => subscription.cancel(),
+      onPause: () => subscription.pause(),
+      onResume: () => subscription.resume(),
+      sync: true);
+  return controller.stream;
+}
 """;
 
 /// Load and return all transformers and groups from the library identified by
@@ -408,8 +454,11 @@
         _TRANSFORMER_ISOLATE.replaceAll('<<HOST_AND_PORT>>', hostAndPort);
     log.fine("Loading transformers from $assetId");
 
-    return dart.runInIsolate(code).then((sendPort) {
-      return _callAndReceiveFuture(sendPort, {
+    var port = new ReceivePort();
+    return dart.runInIsolate(code, port.sendPort)
+        .then((_) => port.first)
+        .then((sendPort) {
+      return _call(sendPort, {
         'library': uri,
         // TODO(nweiz): support non-JSON-encodable configuration maps.
         'configuration': JSON.encode(id.configuration)
@@ -452,14 +501,14 @@
         _toString = map['toString'];
 
   Future<bool> isPrimary(Asset asset) {
-    return _callAndReceiveFuture(_port, {
+    return _call(_port, {
       'type': 'isPrimary',
       'asset': _serializeAsset(asset)
     });
   }
 
   Future apply(Transform transform) {
-    return _callAndReceiveFuture(_port, {
+    return _call(_port, {
       'type': 'apply',
       'transform': _serializeTransform(transform)
     });
@@ -494,16 +543,19 @@
 /// Converts [transform] into a serializable map.
 Map _serializeTransform(Transform transform) {
   var receivePort = new ReceivePort();
-  receivePort.listen((message) {
-    var replyTo = message['replyTo'];
-    if (message['type'] == 'getInput') {
-      _sendFuture(replyTo, transform.getInput(_deserializeId(message['id']))
-          .then(_serializeAsset));
-    } else if (message['type'] == 'addOutput') {
-      transform.addOutput(_deserializeAsset(message['output']));
-    } else {
-      assert(message['type'] == 'log');
+  receivePort.listen((wrappedMessage) {
+    _respond(wrappedMessage, (message) {
+      if (message['type'] == 'getInput') {
+        return transform.getInput(_deserializeId(message['id']))
+            .then(_serializeAsset);
+      }
 
+      if (message['type'] == 'addOutput') {
+        transform.addOutput(_deserializeAsset(message['output']));
+        return;
+      }
+
+      assert(message['type'] == 'log');
       var method;
       if (message['level'] == 'Info') {
         method = transform.logger.info;
@@ -519,7 +571,7 @@
       var span = message['span'] == null ? null :
         _deserializeSpan(message['span']);
       method(message['message'], asset: assetId, span: span);
-    }
+    });
   });
 
   return {
@@ -528,29 +580,45 @@
   };
 }
 
-/// When the input receives a 'done' as data-event, transforms it to a
-/// done event and cancels the subscription.
-StreamSubscription doneTransformer(Stream input, bool cancelOnError) {
+/// Converts a serializable map into an [Asset].
+Asset _deserializeAsset(Map asset) {
+  return new Asset.fromStream(
+      _deserializeId(asset['id']),
+      _deserializeStream(asset['stream']));
+}
+
+/// A transformer that deserializes the values in a stream sent by
+/// [_serializeStream].
+StreamSubscription _deserializeTransformer(Stream input, bool cancelOnError) {
   var subscription;
   var transformed = input.transform(new StreamTransformer.fromHandlers(
       handleData: (data, sink) {
-        if (data == 'done') {
-          sink.close();
-          subscription.cancel();
-        } else {
-          sink.add(data);
-        }
-      }));
+    if (data['type'] == 'data') {
+      sink.add(data['data']);
+    } else if (data['type'] == 'error') {
+      sink.addError(CrossIsolateException.deserialize(data['error']));
+    } else {
+      assert(data['type'] == 'done');
+      sink.close();
+      subscription.cancel();
+    }
+  }));
   subscription = transformed.listen(null, cancelOnError: cancelOnError);
   return subscription;
 }
 
-/// Converts a serializable map into an [Asset].
-Asset _deserializeAsset(Map asset) {
-  var receivePort = new ReceivePort();
-  asset['sendPort'].send(receivePort.sendPort);
-  var stream = receivePort.transform(const StreamTransformer(doneTransformer));
-  return new Asset.fromStream(_deserializeId(asset['id']), stream);
+/// Convert a [SendPort] whose opposite is waiting to send us a stream into a
+/// [Stream].
+///
+/// No stream data will actually be sent across the isolate boundary until
+/// someone subscribes to the returned stream.
+Stream _deserializeStream(SendPort sendPort) {
+  return callbackStream(() {
+    var receivePort = new ReceivePort();
+    sendPort.send(receivePort.sendPort);
+    return receivePort.transform(
+        const StreamTransformer(_deserializeTransformer));
+  });
 }
 
 /// Converts a serializable map into an [AssetId].
@@ -575,52 +643,68 @@
 // efficiently serialized.
 /// Converts [asset] into a serializable map.
 Map _serializeAsset(Asset asset) {
-  // We can't send IsolateStreams (issue 12437), so instead we send a sink and
-  // get the isolate to send us back another sink.
-  var receivePort = new ReceivePort();
-  receivePort.first.then((sendPort) {
-    asset.read().listen(sendPort.send,
-        onError: (error, stackTrace) {
-          throw new UnimplementedError('Error during asset serialization');
-        },
-        onDone: () { sendPort.send('done'); });
-  });
-
   return {
     'id': _serializeId(asset.id),
-    'sendPort': receivePort.sendPort
+    'stream': _serializeStream(asset.read())
   };
 }
 
+/// Converts [stream] into a [SendPort] with which another isolate can request
+/// the data from [stream].
+SendPort _serializeStream(Stream stream) {
+  var receivePort = new ReceivePort();
+  receivePort.first.then((sendPort) {
+    stream.listen((data) => sendPort.send({'type': 'data', 'data': data}),
+        onDone: () => sendPort.send({'type': 'done'}),
+        onError: (error, stackTrace) {
+      sendPort.send({
+        'type': 'error',
+        'error': CrossIsolateException.serialize(error, stackTrace)
+      });
+    });
+  });
+
+  return receivePort.sendPort;
+}
+
 /// Converts [id] into a serializable map.
 Map _serializeId(AssetId id) => {'package': id.package, 'path': id.path};
 
-/// Sends the result of [future] through [port].
+/// Responds to a message sent by [_call].
 ///
-/// This should be received on the other end using [_callAndReceiveFuture]. It
-/// re-raises any exceptions on the other side as [dart.CrossIsolateException]s.
-void _sendFuture(SendPort port, Future future) {
-  future.then((result) {
-    port.send({'success': result});
-  }).catchError((error) {
+/// [wrappedMessage] is the raw message sent by [_call]. This unwraps it and
+/// passes the contents of the message to [callback], then sends the return
+/// value of [callback] back to [_call]. If [callback] returns a Future or
+/// throws an error, that will also be sent.
+void _respond(wrappedMessage, callback(message)) {
+  var replyTo = wrappedMessage['replyTo'];
+  new Future.sync(() => callback(wrappedMessage['message']))
+      .then((result) => replyTo.send({'type': 'success', 'value': result}))
+      .catchError((error, stackTrace) {
     // TODO(nweiz): at least MissingInputException should be preserved here.
-    port.send({'error': dart.CrossIsolateException.serialize(error)});
+    replyTo.send({
+      'type': 'error',
+      'error': dart.CrossIsolateException.serialize(error, stackTrace)
+    });
   });
 }
 
-/// Receives the result of [_sendFuture] from [portCall], which should be the
-/// return value of [SendPort.call].
+/// Wraps [message] and sends it across [port], then waits for a response which
+/// should be sent using [_respond].
 ///
-/// The [message] argument is modified to include the [replyTo] port.
-Future _callAndReceiveFuture(SendPort port, Map message) {
-  var responsePort = new ReceivePort();
-  message['replyTo'] = responsePort.sendPort;
-  return new Future.sync(() {
-    port.send(message);
-    return responsePort.first.then((response) {
-      if (response.containsKey('success')) return response['success'];
-      return new Future.error(
-          new dart.CrossIsolateException.deserialize(response['error']));
-    });
+/// The returned Future will complete to the value or error returned by
+/// [_respond].
+Future _call(SendPort port, message) {
+  var receivePort = new ReceivePort();
+  port.send({
+    'message': message,
+    'replyTo': receivePort.sendPort
+  });
+
+  return receivePort.first.then((response) {
+    if (response['type'] == 'success') return response['value'];
+    assert(response['type'] == 'error');
+    return new Future.error(
+        new dart.CrossIsolateException.deserialize(response['error']));
   });
 }
diff --git a/sdk/lib/_internal/pub/lib/src/barback/pub_barback_logger.dart b/sdk/lib/_internal/pub/lib/src/barback/pub_barback_logger.dart
deleted file mode 100644
index 374e158..0000000
--- a/sdk/lib/_internal/pub/lib/src/barback/pub_barback_logger.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2013, 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.
-
-library pub.pub_barback_logger;
-
-import 'package:barback/barback.dart';
-
-import '../log.dart' as log;
-
-/// A [BarbackLogger] that routes through pub's logging code.
-class PubBarbackLogger implements BarbackLogger {
-  /// Since both [LogEntry] objects and the message itself often redundantly
-  /// show the same context like the file where an error occurred, this tries
-  /// to avoid showing redundant data in the entry.
-  void logEntry(LogEntry entry) {
-    messageMentions(String text) {
-      return entry.message.toLowerCase().contains(text.toLowerCase());
-    }
-
-    var prefixParts = [];
-
-    // Show the level (unless the message mentions it.)
-    if (!messageMentions(entry.level.name)) {
-      prefixParts.add("${entry.level} in");
-    }
-
-    // Show the transformer.
-    prefixParts.add(entry.transform.transformer);
-
-    // Mention the primary input of the transform unless the message seems to.
-    if (!messageMentions(entry.transform.primaryId.path)) {
-      prefixParts.add("on ${entry.transform.primaryId}");
-    }
-
-    // If the relevant asset isn't the primary input, mention it unless the
-    // message already does.
-    if (entry.asset != entry.transform.primaryId &&
-        !messageMentions(entry.asset.path)) {
-      prefixParts.add("with input ${entry.asset}");
-    }
-
-    var prefix = "[${prefixParts.join(' ')}]:";
-    var message = entry.message;
-    if (entry.span != null) {
-      message = entry.span.getLocationMessage(entry.message);
-    }
-
-    switch (entry.level) {
-      case LogLevel.ERROR:
-        log.error("${log.red(prefix)}\n$message");
-        break;
-
-      case LogLevel.WARNING:
-        log.warning("${log.yellow(prefix)}\n$message");
-        break;
-
-      case LogLevel.INFO:
-        log.message("$prefix\n$message");
-        break;
-    }
-  }
-}
diff --git a/sdk/lib/_internal/pub/lib/src/barback/watch_sources.dart b/sdk/lib/_internal/pub/lib/src/barback/sources.dart
similarity index 79%
rename from sdk/lib/_internal/pub/lib/src/barback/watch_sources.dart
rename to sdk/lib/_internal/pub/lib/src/barback/sources.dart
index 6a176aa..c85044b 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/watch_sources.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/sources.dart
@@ -2,7 +2,9 @@
 // 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.
 
-library pub.barback.watch_sources;
+library pub.barback.sources;
+
+import 'dart:async';
 
 import 'package:barback/barback.dart';
 import 'package:path/path.dart' as path;
@@ -15,24 +17,26 @@
 
 /// Adds all of the source assets in the provided packages to barback and
 /// then watches the public directories for changes.
-void watchSources(PackageGraph graph, Barback barback) {
-  for (var package in graph.packages.values) {
-    // Add the initial sources.
-    barback.updateSources(_listAssets(graph.entrypoint, package));
-
+///
+/// Returns a Future that completes when the sources are loaded and the
+/// watchers are active.
+Future watchSources(PackageGraph graph, Barback barback) {
+  return Future.wait(graph.packages.values.map((package) {
     // If this package comes from a cached source, its contents won't change so
     // we don't need to monitor it. `packageId` will be null for the application
     // package, since that's not locked.
     var packageId = graph.lockFile.packages[package.name];
     if (packageId != null &&
         graph.entrypoint.cache.sources[packageId.source].shouldCache) {
-      continue;
+      barback.updateSources(_listAssets(graph.entrypoint, package));
+      return new Future.value();
     }
 
     // Watch the visible package directories for changes.
-    for (var name in _getPublicDirectories(graph.entrypoint, package)) {
+    return Future.wait(_getPublicDirectories(graph.entrypoint, package)
+        .map((name) {
       var subdirectory = path.join(package.dir, name);
-      if (!dirExists(subdirectory)) continue;
+      if (!dirExists(subdirectory)) return new Future.value();
 
       // TODO(nweiz): close these watchers when [barback] is closed.
       var watcher = new DirectoryWatcher(subdirectory);
@@ -50,7 +54,17 @@
           barback.updateSources([id]);
         }
       });
-    }
+      return watcher.ready;
+    })).then((_) {
+      barback.updateSources(_listAssets(graph.entrypoint, package));
+    });
+  }));
+}
+
+/// Adds all of the source assets in the provided packages to barback.
+void loadSources(PackageGraph graph, Barback barback) {
+  for (var package in graph.packages.values) {
+    barback.updateSources(_listAssets(graph.entrypoint, package));
   }
 }
 
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index e8b7ed0..167e2d1 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -78,7 +78,7 @@
         help: 'Print usage information for this command.');
   }
 
-  void run(String cacheDir, ArgResults options) {
+  void run(String cacheDir, ArgResults options, List<String> arguments) {
     commandOptions = options.command;
 
     if (commandOptions['help']) {
@@ -111,7 +111,7 @@
         log.error("""
 This is an unexpected error. Please run
 
-    pub --trace ${new Options().arguments.map((arg) => "'$arg'").join(' ')}
+    pub --trace ${arguments.map((arg) => "'$arg'").join(' ')}
 
 and include the results in a bug report on http://dartbug.com/new.
 """);
@@ -123,7 +123,8 @@
     new Future.sync(() {
       // Make sure there aren't unexpected arguments.
       if (!takesArguments && commandOptions.rest.isNotEmpty) {
-        log.error('Command does not take any arguments.');
+        log.error('Command "${commandOptions.name}" does not take any '
+                  'arguments.');
         this.printUsage();
         return flushThenExit(exit_codes.USAGE);
       }
diff --git a/sdk/lib/_internal/pub/lib/src/command/build.dart b/sdk/lib/_internal/pub/lib/src/command/build.dart
index 04d8ea6..93dee74 100644
--- a/sdk/lib/_internal/pub/lib/src/command/build.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/build.dart
@@ -21,10 +21,10 @@
 
 /// Handles the `build` pub command.
 class BuildCommand extends PubCommand {
-  final description = "Copy and compile all Dart entrypoints in the 'web' "
-      "directory.";
-  final usage = "pub build [options]";
-  final aliases = const ["deploy", "settle-up"];
+  String get description =>
+      "Copy and compile all Dart entrypoints in the 'web' directory.";
+  String get usage => "pub build [options]";
+  List<String> get aliases => const ["deploy", "settle-up"];
 
   // TODO(nweiz): make these configurable.
   /// The path to the source directory of the application.
@@ -33,6 +33,14 @@
   /// The path to the application's build output directory.
   String get target => path.join(entrypoint.root.dir, 'build');
 
+  /// `true` if generated JavaScript should be minified.
+  bool get minify => commandOptions['minify'];
+
+  BuildCommand() {
+    commandParser.addFlag('minify', defaultsTo: true,
+        help: 'Minify generated JavaScript.');
+  }
+
   Future onRun() {
     if (!dirExists(source)) {
       throw new ApplicationException("There is no '$source' directory.");
@@ -45,13 +53,14 @@
     return entrypoint.ensureLockFileIsUpToDate().then((_) {
       return entrypoint.loadPackageGraph();
     }).then((graph) {
-      dart2jsTransformer = new Dart2JSTransformer(graph);
+      dart2jsTransformer = new Dart2JSTransformer(graph, minify: minify);
 
       // Since this server will only be hit by the transformer loader and isn't
       // user-facing, just use an IPv4 address to avoid a weird bug on the
       // OS X buildbots.
       return barback.createServer("127.0.0.1", 0, graph,
-          builtInTransformers: [dart2jsTransformer]);
+          builtInTransformers: [dart2jsTransformer],
+          watchForUpdates: false);
     }).then((server) {
       // Show in-progress errors, but not results. Those get handled implicitly
       // by getAllAssets().
@@ -66,7 +75,7 @@
       // in the generated JavaScript.
       assets = assets.where((asset) => asset.id.extension != ".dart");
 
-      return Future.forEach(assets, (asset) {
+      return Future.wait(assets.map((asset) {
         // Figure out the output directory for the asset, which is the same
         // as the path pub serve would use to serve it.
         var relativeUrl = barback.idtoUrlPath(entrypoint.root.name, asset.id);
@@ -80,10 +89,11 @@
         ensureDir(path.dirname(destPath));
         // TODO(rnystrom): Should we display this to the user?
         return createFileFromStream(asset.read(), destPath);
-      }).then((_) {
+      })).then((_) {
         _copyBrowserJsFiles(dart2jsTransformer.entrypoints);
         // TODO(rnystrom): Should this count include the JS files?
-        log.message("Built ${assets.length} files!");
+        log.message("Built ${assets.length} "
+            "${pluralize('file', assets.length)}!");
       });
     }).catchError((error) {
       // If [getAllAssets()] throws a BarbackException, the error has already
@@ -100,8 +110,8 @@
   /// directories next to each entrypoint in [entrypoints].
   void _copyBrowserJsFiles(Iterable<AssetId> entrypoints) {
     // Must depend on the browser package.
-    if (!entrypoint.root.dependencies.any((dep) =>
-        dep.name == 'browser' && dep.source == 'hosted')) {
+    if (!entrypoint.root.dependencies.any(
+        (dep) => dep.name == 'browser' && dep.source == 'hosted')) {
       return;
     }
 
diff --git a/sdk/lib/_internal/pub/lib/src/command/cache.dart b/sdk/lib/_internal/pub/lib/src/command/cache.dart
index 29ad06b..97e5dbe 100644
--- a/sdk/lib/_internal/pub/lib/src/command/cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/cache.dart
@@ -15,7 +15,7 @@
 /// Handles the `cache` pub command.
 class CacheCommand extends PubCommand {
   String get description => "Inspect the system cache.";
-  String get usage => 'pub cache list';
+  String get usage => "pub cache list";
   bool get hidden => true;
   bool get requiresEntrypoint => false;
   bool get takesArguments => true;
diff --git a/sdk/lib/_internal/pub/lib/src/command/get.dart b/sdk/lib/_internal/pub/lib/src/command/get.dart
index 97db6c0..51c5f0a 100644
--- a/sdk/lib/_internal/pub/lib/src/command/get.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/get.dart
@@ -13,9 +13,8 @@
 class GetCommand extends PubCommand {
   String get description => "Get the current package's dependencies.";
   String get usage => "pub get";
-  final aliases = const ["install"];
-
-  bool get isOffline => commandOptions['offline'];
+  List<String> get aliases => const ["install"];
+  bool get isOffline => commandOptions["offline"];
 
   GetCommand() {
     commandParser.addFlag('offline',
diff --git a/sdk/lib/_internal/pub/lib/src/command/help.dart b/sdk/lib/_internal/pub/lib/src/command/help.dart
index a69171d..f02841f 100644
--- a/sdk/lib/_internal/pub/lib/src/command/help.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/help.dart
@@ -14,7 +14,7 @@
 /// Handles the `help` pub command.
 class HelpCommand extends PubCommand {
   String get description => "Display help information for Pub.";
-  String get usage => 'pub help [command]';
+  String get usage => "pub help [command]";
   bool get requiresEntrypoint => false;
   bool get takesArguments => true;
 
diff --git a/sdk/lib/_internal/pub/lib/src/command/lish.dart b/sdk/lib/_internal/pub/lib/src/command/lish.dart
index b962f24..d5b6b50 100644
--- a/sdk/lib/_internal/pub/lib/src/command/lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/lish.dart
@@ -21,9 +21,9 @@
 
 /// Handles the `lish` and `publish` pub commands.
 class LishCommand extends PubCommand {
-  final description = "Publish the current package to pub.dartlang.org.";
-  final usage = "pub publish [options]";
-  final aliases = const ["lish", "lush"];
+  String get description => "Publish the current package to pub.dartlang.org.";
+  String get usage => "pub publish [options]";
+  List<String> get aliases => const ["lish", "lush"];
 
   /// The URL of the server to which to upload the package.
   Uri get server => Uri.parse(commandOptions['server']);
diff --git a/sdk/lib/_internal/pub/lib/src/command/serve.dart b/sdk/lib/_internal/pub/lib/src/command/serve.dart
index bf2c571..0d7adfc 100644
--- a/sdk/lib/_internal/pub/lib/src/command/serve.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/serve.dart
@@ -22,7 +22,7 @@
 /// Handles the `serve` pub command.
 class ServeCommand extends PubCommand {
   String get description => "Run a local web development server.";
-  String get usage => 'pub serve';
+  String get usage => "pub serve";
 
   PubPackageProvider _provider;
 
@@ -31,6 +31,9 @@
   /// `true` if Dart entrypoints should be compiled to JavaScript.
   bool get useDart2JS => commandOptions['dart2js'];
 
+  /// `true` if generated JavaScript should be minified.
+  bool get minify => commandOptions['minify'];
+
   ServeCommand() {
     commandParser.addOption('port', defaultsTo: '8080',
         help: 'The port to listen on.');
@@ -45,6 +48,9 @@
 
     commandParser.addFlag('dart2js', defaultsTo: true,
         help: 'Compile Dart to JavaScript.');
+
+    commandParser.addFlag('minify', defaultsTo: false,
+        help: 'Minify generated JavaScript.');
   }
 
   Future onRun() {
@@ -64,7 +70,7 @@
       var builtInTransformers = null;
       if (useDart2JS) {
         builtInTransformers = [
-          new Dart2JSTransformer(graph),
+          new Dart2JSTransformer(graph, minify: minify),
           new DartForwardingTransformer()
         ];
       }
diff --git a/sdk/lib/_internal/pub/lib/src/command/upgrade.dart b/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
index 2f0add7..306e027 100644
--- a/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
@@ -13,9 +13,9 @@
 /// Handles the `upgrade` pub command.
 class UpgradeCommand extends PubCommand {
   String get description =>
-    "Upgrade the current package's dependencies to latest versions.";
-  String get usage => 'pub upgrade [dependencies...]';
-  final aliases = const ["update"];
+      "Upgrade the current package's dependencies to latest versions.";
+  String get usage => "pub upgrade [dependencies...]";
+  List<String> get aliases => const ["update"];
   bool get takesArguments => true;
 
   bool get isOffline => commandOptions['offline'];
diff --git a/sdk/lib/_internal/pub/lib/src/command/uploader.dart b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
index 32e21a8..f9aa11d 100644
--- a/sdk/lib/_internal/pub/lib/src/command/uploader.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
@@ -19,9 +19,10 @@
 
 /// Handles the `uploader` pub command.
 class UploaderCommand extends PubCommand {
-  final description = "Manage uploaders for a package on pub.dartlang.org.";
-  final usage = "pub uploader [options] {add/remove} <email>";
-  final requiresEntrypoint = false;
+  String get description =>
+      "Manage uploaders for a package on pub.dartlang.org.";
+  String get usage => "pub uploader [options] {add/remove} <email>";
+  bool get requiresEntrypoint => false;
   bool get takesArguments => true;
 
   /// The URL of the package hosting server.
diff --git a/sdk/lib/_internal/pub/lib/src/command/version.dart b/sdk/lib/_internal/pub/lib/src/command/version.dart
index 5fa6026..4855361 100644
--- a/sdk/lib/_internal/pub/lib/src/command/version.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/version.dart
@@ -12,11 +12,11 @@
 
 /// Handles the `version` pub command.
 class VersionCommand extends PubCommand {
-  String get description => 'Print pub version.';
-  String get usage => 'pub version';
+  String get description => "Print pub version.";
+  String get usage => "pub version";
   bool get requiresEntrypoint => false;
 
   Future onRun() {
-    log.message('Pub ${sdk.version}');
+    log.message("Pub ${sdk.version}");
   }
 }
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
index e0701a4..28902cc 100644
--- a/sdk/lib/_internal/pub/lib/src/dart.dart
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -30,12 +30,17 @@
 /// If [inputProvider] and [diagnosticHandler] are omitted, uses a default
 /// [compiler.CompilerInputProvider] that loads directly from the filesystem.
 /// If either is provided, both must be.
-Future<String> compile(String entrypoint, {String packageRoot,
-    bool toDart: false, compiler.CompilerInputProvider inputProvider,
+Future<String> compile(String entrypoint, {
+    String packageRoot,
+    bool toDart: false,
+    bool minify: true,
+    compiler.CompilerInputProvider inputProvider,
     compiler.DiagnosticHandler diagnosticHandler}) {
   return new Future.sync(() {
-    var options = <String>['--categories=Client,Server', '--minify'];
+    var options = <String>['--categories=Client,Server'];
     if (toDart) options.add('--output-type=dart');
+    if (minify) options.add('--minify');
+
     if (packageRoot == null) {
       packageRoot = path.join(path.dirname(entrypoint), 'packages');
     }
@@ -57,7 +62,10 @@
         path.toUri(entrypoint),
         path.toUri(appendSlash(_libPath)),
         path.toUri(appendSlash(packageRoot)),
-        inputProvider, diagnosticHandler, options);
+        inputProvider, diagnosticHandler, options).then((js) {
+      if (js == null) throw new CompilerException(entrypoint);
+      return js;
+    });
   });
 }
 
@@ -83,27 +91,26 @@
 /// Runs [code] in an isolate.
 ///
 /// [code] should be the contents of a Dart entrypoint. It may contain imports;
-/// they will be resolved in the same context as the host isolate.
+/// they will be resolved in the same context as the host isolate. [message] is
+/// passed to the [main] method of the code being run; the caller is responsible
+/// for using this to establish communication with the isolate.
 ///
-/// Returns a Future that will resolve to a [SendPort] that will communicate to
-/// the spawned isolate once it's spawned. If the isolate fails to spawn, the
-/// Future will complete with an error.
-Future<SendPort> runInIsolate(String code) {
+/// Returns a Future that will fire when the isolate has been spawned. If the
+/// isolate fails to spawn, the Future will complete with an error.
+Future runInIsolate(String code, message) {
   return withTempDir((dir) {
     var dartPath = path.join(dir, 'runInIsolate.dart');
     writeTextFile(dartPath, code, dontLogContents: true);
     var port = new ReceivePort();
-    var initialMessage =  [path.toUri(dartPath).toString(), port.sendPort];
-    var isolate = Isolate.spawn(_isolateBuffer, initialMessage);
-    return isolate.then((_) {
-      return port.first.then((response) {
-        if (response.first == 'error') {
-          return new Future.error(
-              new CrossIsolateException.deserialize(response.last));
-        }
-
-        return response.last;
-      });
+    return Isolate.spawn(_isolateBuffer, {
+      'replyTo': port.sendPort,
+      'uri': path.toUri(dartPath).toString(),
+      'message': message
+    }).then((_) => port.first).then((response) {
+      if (response['type'] == 'success') return;
+      assert(response['type'] == 'error');
+      return new Future.error(
+          new CrossIsolateException.deserialize(response['error']));
     });
   });
 }
@@ -114,18 +121,18 @@
 /// [spawnUri] synchronously loads the file and its imports, which can deadlock
 /// the host isolate if there's an HTTP import pointing at a server in the host.
 /// Adding an additional isolate in the middle works around this.
-void _isolateBuffer(initialMessage) {
-  var uri = initialMessage[0];
-  var replyTo = initialMessage[1];
-  try {
-    // TODO(floitsch): If we do it right we shouldn't need to have a try/catch
-    // and a catchError.
-    Isolate.spawnUri(Uri.parse(uri), [], replyTo).catchError((e, stack) {
-      replyTo.send(['error', CrossIsolateException.serialize(e, stack)]);
+void _isolateBuffer(message) {
+  var replyTo = message['replyTo'];
+  // TODO(floitsch): If we do it right we shouldn't need to capture synchronous
+  // errors.
+  new Future.sync(() {
+    return Isolate.spawnUri(Uri.parse(message['uri']), [], message['message']);
+  }).then((_) => replyTo.send({'type': 'success'})).catchError((e, stack) {
+    replyTo.send({
+      'type': 'error',
+      'error': CrossIsolateException.serialize(e, stack)
     });
-  } catch (e, stack) {
-    replyTo.send(['error', CrossIsolateException.serialize(e, stack)]);
-  }
+  });
 }
 
 /// An exception that was originally raised in another isolate.
@@ -175,3 +182,9 @@
 
   String toString() => "$message\n$stackTrace";
 }
+
+/// An exception thrown when dart2js generates compiler errors.
+class CompilerException extends ApplicationException {
+  CompilerException(String entrypoint)
+      : super('Failed to compile "$entrypoint".');
+}
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index 8a63d52..c17546e 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -393,6 +393,25 @@
   return controller.stream;
 }
 
+/// Returns a [Stream] that will emit the same values as the stream returned by
+/// [callback].
+///
+/// [callback] will only be called when the returned [Stream] gets a subscriber.
+Stream callbackStream(Stream callback()) {
+  var subscription;
+  var controller;
+  controller = new StreamController(onListen: () {
+    subscription = callback().listen(controller.add,
+        onError: controller.addError,
+        onDone: controller.close);
+  },
+      onCancel: () => subscription.cancel(),
+      onPause: () => subscription.pause(),
+      onResume: () => subscription.resume(),
+      sync: true);
+  return controller.stream;
+}
+
 /// A regular expression matching a trailing CR character.
 final _trailingCR = new RegExp(r"\r$");
 
diff --git a/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart b/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart
index 5d0b67a..f69676a 100644
--- a/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart
+++ b/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart
@@ -10,7 +10,8 @@
 main() {
   initConfig();
 
-  // TODO(rnystrom): Should also add tests that other transformers work.
+  // TODO(rnystrom): Should also add tests that other transformers work
+  // (#14556).
 
   integration("compiles Dart entrypoints to Dart and JS", () {
     // Dart2js can take a long time to compile dart code, so we increase the
@@ -28,6 +29,8 @@
       ])
     ]).create();
 
+    // TODO(rnystrom): If we flesh out the command-line output, validate that
+    // here.
     schedulePub(args: ["build"],
         output: new RegExp(r"Built 2 files!"),
         exitCode: 0);
diff --git a/sdk/lib/_internal/pub/test/build/minifies_js_by_default_test.dart b/sdk/lib/_internal/pub/test/build/minifies_js_by_default_test.dart
new file mode 100644
index 0000000..73f58dd
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/minifies_js_by_default_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, 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.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("generates minified JavaScript", () {
+    // Dart2js can take a long time to compile dart code, so we increase the
+    // timeout to cope with that.
+    currentSchedule.timeout *= 3;
+
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('main.dart', 'void main() => print("hello");')
+      ])
+    ]).create();
+
+    schedulePub(args: ["build"],
+        output: new RegExp(r"Built 1 file!"),
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir('build', [
+        d.matcherFile('main.dart.js', isMinifiedDart2JSOutput)
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/build/takes_flag_to_disable_minification_test.dart b/sdk/lib/_internal/pub/test/build/takes_flag_to_disable_minification_test.dart
new file mode 100644
index 0000000..fc4bfd0
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/takes_flag_to_disable_minification_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, 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.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("takes a flag to generate unminified JavaScript", () {
+    // Dart2js can take a long time to compile dart code, so we increase the
+    // timeout to cope with that.
+    currentSchedule.timeout *= 3;
+
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('main.dart', 'void main() => print("hello");')
+      ])
+    ]).create();
+
+    schedulePub(args: ["build", "--no-minify"],
+        output: new RegExp(r"Built 1 file!"),
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir('build', [
+        d.matcherFile('main.dart.js', isUnminifiedDart2JSOutput)
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/pub_test.dart b/sdk/lib/_internal/pub/test/pub_test.dart
index ed2507d..cf0749c 100644
--- a/sdk/lib/_internal/pub/test/pub_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_test.dart
@@ -123,7 +123,7 @@
          -h, --help    Print usage information for this command.
         ''',
         error: '''
-        Command does not take any arguments.
+        Command "version" does not take any arguments.
         ''',
         exitCode: 64);
   });
diff --git a/sdk/lib/_internal/pub/test/serve/utils.dart b/sdk/lib/_internal/pub/test/serve/utils.dart
index 6ff10c0..1013aec 100644
--- a/sdk/lib/_internal/pub/test/serve/utils.dart
+++ b/sdk/lib/_internal/pub/test/serve/utils.dart
@@ -100,19 +100,17 @@
 ///
 /// Returns the `pub serve` process.
 ScheduledProcess startPubServe({bool shouldGetFirst: false,
-    bool dart2js: true}) {
+    Iterable<String> args}) {
   // Use port 0 to get an ephemeral port.
-  var args = ["serve", "--port=0", "--hostname=127.0.0.1"];
+  var pubArgs = ["serve", "--port=0", "--hostname=127.0.0.1"];
 
-  if (!dart2js) args.add("--no-dart2js");
+  if (args != null) pubArgs.addAll(args);
 
   // Dart2js can take a long time to compile dart code, so we increase the
   // timeout to cope with that.
-  if (dart2js) {
-    currentSchedule.timeout = new Duration(seconds: 15);
-  }
+  currentSchedule.timeout = new Duration(seconds: 15);
 
-  _pubServer = startPub(args: args);
+  _pubServer = startPub(args: pubArgs);
 
   currentSchedule.onComplete.schedule(() {
     if (_webSocket != null) {
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index 2c85e8c..5da6eb6 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -46,10 +46,6 @@
   unittestConfiguration.timeout = null;
 }
 
-/// Returns whether we're running on a Dart build bot.
-bool get runningOnBuildbot =>
-  Platform.environment.containsKey('BUILDBOT_BUILDERNAME');
-
 /// The current [HttpServer] created using [serve].
 var _server;
 
@@ -60,6 +56,16 @@
 /// The cached value for [_portCompleter].
 Completer<int> _portCompleterCache;
 
+/// A [Matcher] that matches JavaScript generated by dart2js with minification
+/// enabled.
+Matcher isMinifiedDart2JSOutput =
+    isNot(contains("// The code supports the following hooks"));
+
+/// A [Matcher] that matches JavaScript generated by dart2js with minification
+/// disabled.
+Matcher isUnminifiedDart2JSOutput =
+    contains("// The code supports the following hooks");
+
 /// The completer for [port].
 Completer<int> get _portCompleter {
   if (_portCompleterCache != null) return _portCompleterCache;
@@ -582,14 +588,13 @@
 /// The path to the `packages` directory from which pub loads its dependencies.
 String get _packageRoot => path.absolute(Platform.packageRoot);
 
-/// Skips the current test if Git is not installed. This validates that the
-/// current test is running on a buildbot in which case we expect git to be
-/// installed. If we are not running on the buildbot, we will instead see if
-/// git is installed and skip the test if not. This way, users don't need to
-/// have git installed to run the tests locally (unless they actually care
-/// about the pub git tests).
+/// Fails the current test if Git is not installed.
 ///
-/// This will also increase the [Schedule] timeout to 30 seconds on Windows,
+/// We require machines running these tests to have git installed. This
+/// validation gives an easier-to-understand error when that requirement isn't
+/// met than just failing in the middle of a test when pub invokes git.
+///
+/// This also increases the [Schedule] timeout to 30 seconds on Windows,
 /// where Git runs really slowly.
 void ensureGit() {
   if (Platform.operatingSystem == "windows") {
@@ -598,9 +603,9 @@
 
   schedule(() {
     return gitlib.isInstalled.then((installed) {
-      if (installed) return;
-      if (runningOnBuildbot) return;
-      currentSchedule.abort();
+      if (!installed) {
+        throw new Exception("Git must be installed to run this test.");
+      }
     });
   }, 'ensuring that Git is installed');
 }
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart
index fc90667..848ae1b 100644
--- a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart
@@ -18,7 +18,7 @@
       ])
     ]).create();
 
-    startPubServe(dart2js: false);
+    startPubServe(args: ["--no-dart2js"]);
     requestShould404("main.dart.js");
     endPubServe();
   });
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/takes_flag_minify_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/takes_flag_minify_test.dart
new file mode 100644
index 0000000..e385237
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/takes_flag_minify_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+import '../../serve/utils.dart';
+
+main() {
+  initConfig();
+  integration("generates minified JS if the flag is set", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("web", [
+        d.file("main.dart", "void main() => print('hello');")
+      ])
+    ]).create();
+
+    startPubServe(args: ["--minify"]);
+    requestShouldSucceed("main.dart.js", isMinifiedDart2JSOutput);
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/unminified_by_default_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/unminified_by_default_test.dart
new file mode 100644
index 0000000..3f0bb23
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/unminified_by_default_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+import '../../serve/utils.dart';
+
+main() {
+  initConfig();
+  integration("generates unminified JS by default", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("web", [
+        d.file("main.dart", "void main() => print('hello');")
+      ])
+    ]).create();
+
+    startPubServe();
+    requestShouldSucceed("main.dart.js", isUnminifiedDart2JSOutput);
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index f15073f..a565220 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -10,7 +10,7 @@
  * [dart:async section of the language tour]
  * (https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-asynchronous-programming).
  *
- * ## Other Resources
+ * ## Other resources
  *
  * * [Using Future Based APIs]
  * (https://www.dartlang.org/articles/using-future-based-apis/): A first look at
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 2e43669..59e199c 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -183,9 +183,9 @@
     return subscription;
   }
 
-  void _recordCancel(_BroadcastSubscription<T> subscription) {
+  Future _recordCancel(_BroadcastSubscription<T> subscription) {
     // If already removed by the stream, don't remove it again.
-    if (identical(subscription._next, subscription)) return;
+    if (identical(subscription._next, subscription)) return null;
     assert(!identical(subscription._next, subscription));
     if (subscription._isFiring) {
       subscription._setRemoveAfterFiring();
@@ -238,10 +238,10 @@
 
   Future get done => _ensureDoneFuture();
 
-  Future addStream(Stream<T> stream) {
+  Future addStream(Stream<T> stream, {bool cancelOnError: true}) {
     if (!_mayAddEvent) throw _addEventError();
     _state |= _STATE_ADDSTREAM;
-    _addStreamState = new _AddStreamState(this, stream);
+    _addStreamState = new _AddStreamState(this, stream, cancelOnError);
     return _addStreamState.addStreamFuture;
   }
 
@@ -472,7 +472,7 @@
   void _resume(_) {
     if (_pauseCount > 0) _pauseCount--;
   }
-  void cancel() {}
+  Future cancel() { return new _Future.immediate(null); }
   bool get isPaused => _pauseCount > 0;
   Future asFuture([Object value]) => new _Future();
 }
diff --git a/sdk/lib/async/schedule_microtask.dart b/sdk/lib/async/schedule_microtask.dart
index dca72df..11eb778 100644
--- a/sdk/lib/async/schedule_microtask.dart
+++ b/sdk/lib/async/schedule_microtask.dart
@@ -46,7 +46,7 @@
  * callbacks through this method. For example the following program runs
  * the callbacks without ever giving the Timer callback a chance to execute:
  *
- *     Timer.run(() { print("executed"); });  // Will never be executed,
+ *     Timer.run(() { print("executed"); });  // Will never be executed.
  *     foo() {
  *       scheduleMicrotask(foo);  // Schedules [foo] in front of other events.
  *     }
@@ -54,7 +54,7 @@
  *       foo();
  *     }
  *
- * ## Other Resources
+ * ## Other resources
  *
  * * [The Event Loop and Dart](https://www.dartlang.org/articles/event-loop/):
  * Learn how Dart handles the event queue and microtask queue, so you can write
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 6672f47..48e70f1 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1030,7 +1030,16 @@
  * done.
  */
 abstract class StreamConsumer<S> {
+  /**
+   * Consumes the elements of [stream].
+   *
+   * Listens on [stream] and does something for each event.
+   *
+   * The consumer may stop listening after an error, or it may consume
+   * all the errors and only stop at a done event.
+   */
   Future addStream(Stream<S> stream);
+
   Future close();
 }
 
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index ba3fd61..b40ffb5 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -167,6 +167,26 @@
    * allows.
    */
   void addError(Object error, [StackTrace stackTrace]);
+
+  /**
+   * Receives events from [source] and puts them into this controller's stream.
+   *
+   * Returns a future which completes when the source stream is done.
+   *
+   * Events must not be added directly to this controller using [add],
+   * [addError], [close] or [addStream], until the returned future
+   * is complete.
+   *
+   * Data and error events are forwarded to this controller's stream. A done
+   * event on the source will end the `addStream` operation and complete the
+   * returned future.
+   *
+   * If [cancelOnError] is true, only the first error on [source] is
+   * forwarded to the controller's stream, and the `addStream` ends
+   * after this. If [cancelOnError] is false, all errors are forwarded
+   * and only a done event will end the `addStream`.
+   */
+  Future addStream(Stream<T> source, {bool cancelOnError: true});
 }
 
 
@@ -344,11 +364,14 @@
   }
 
   // StreamSink interface.
-  Future addStream(Stream<T> source) {
+  Future addStream(Stream<T> source, { bool cancelOnError: true }) {
     if (!_mayAddEvent) throw _badEventState();
     if (_isCanceled) return new _Future.immediate(null);
     _StreamControllerAddStreamState addState =
-        new _StreamControllerAddStreamState(this, _varData, source);
+        new _StreamControllerAddStreamState(this,
+                                            _varData,
+                                            source,
+                                            cancelOnError);
     _varData = addState;
     _state |= _STATE_ADDSTREAM;
     return addState.addStreamFuture;
@@ -454,6 +477,7 @@
     if (_isAddingStream) {
       _StreamControllerAddStreamState addState = _varData;
       addState.varData = subscription;
+      addState.resume();
     } else {
       _varData = subscription;
     }
@@ -633,7 +657,7 @@
 
 /** A class that exposes only the [StreamSink] interface of an object. */
 class _StreamSinkWrapper<T> implements StreamSink<T> {
-  final StreamSink _target;
+  final StreamController _target;
   _StreamSinkWrapper(this._target);
   void add(T data) { _target.add(data); }
   void addError(Object error, [StackTrace stackTrace]) {
@@ -649,17 +673,25 @@
  */
 class _AddStreamState<T> {
   // [_Future] returned by call to addStream.
-  _Future addStreamFuture;
+  final _Future addStreamFuture;
 
   // Subscription on stream argument to addStream.
-  StreamSubscription addSubscription;
+  final StreamSubscription addSubscription;
 
-  _AddStreamState(_EventSink<T> controller, Stream source)
+  _AddStreamState(_EventSink<T> controller, Stream source, bool cancelOnError)
       : addStreamFuture = new _Future(),
         addSubscription = source.listen(controller._add,
-                                        onError: controller._addError,
+                                        onError: cancelOnError
+                                             ? makeErrorHandler(controller)
+                                             : controller._addError,
                                         onDone: controller._close,
-                                        cancelOnError: true);
+                                        cancelOnError: cancelOnError);
+
+  static makeErrorHandler(_EventSink controller) =>
+      (e, StackTrace s) {
+        controller._addError(e, s);
+        controller._close();
+      };
 
   void pause() {
     addSubscription.pause();
@@ -687,7 +719,9 @@
 
   _StreamControllerAddStreamState(_StreamController controller,
                                   this.varData,
-                                  Stream source) : super(controller, source) {
+                                  Stream source,
+                                  bool cancelOnError)
+      : super(controller, source, cancelOnError) {
     if (controller.isPaused) {
       addSubscription.pause();
     }
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index bf7c8f0..e7ccead 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -488,6 +488,7 @@
 /** Stream that generates its own events. */
 class _GeneratedStreamImpl<T> extends _StreamImpl<T> {
   final _EventGenerator _pending;
+  bool _isUsed = false;
   /**
    * Initializes the stream to have only the events provided by a
    * [_PendingEvents].
@@ -497,6 +498,8 @@
   _GeneratedStreamImpl(this._pending);
 
   StreamSubscription _createSubscription(bool cancelOnError) {
+    if (_isUsed) throw new StateError("Stream has already been listened to.");
+    _isUsed = true;
     _BufferingStreamSubscription<T> subscription =
          new _BufferingStreamSubscription(cancelOnError);
     subscription._setPendingEvents(_pending());
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 5924084..ba286b4 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -147,12 +147,13 @@
     _subscription.resume();
   }
 
-  void _onCancel() {
+  Future _onCancel() {
     if (_subscription != null) {
       StreamSubscription subscription = _subscription;
       _subscription = null;
       subscription.cancel();
     }
+    return null;
   }
 
   // Methods used as listener on source subscription.
@@ -349,7 +350,7 @@
       _remaining--;
       return;
     }
-    return sink._add(inputEvent);
+    sink._add(inputEvent);
   }
 }
 
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index 1947235..c40ce7d 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -102,12 +102,13 @@
     if (_isSubscribed) _subscription.resume();
   }
 
-  void _onCancel() {
+  Future _onCancel() {
     if (_isSubscribed) {
       StreamSubscription subscription = _subscription;
       _subscription = null;
       subscription.cancel();
     }
+    return null;
   }
 
   void _handleData(S data) {
@@ -199,7 +200,7 @@
  *
  * This way we can reuse the code from [_StreamSinkTransformer].
  */
-class _HandlerEventSink<S, T> implements EventSink<T> {
+class _HandlerEventSink<S, T> implements EventSink<S> {
   final _TransformDataHandler<S, T> _handleData;
   final _TransformErrorHandler<T> _handleError;
   final _TransformDoneHandler<T> _handleDone;
diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
index cd89e78..fb5ac89 100644
--- a/sdk/lib/collection/linked_list.dart
+++ b/sdk/lib/collection/linked_list.dart
@@ -147,7 +147,7 @@
 }
 
 
-class _LinkedListIterator<E extends LinkedListEntry>
+class _LinkedListIterator<E extends LinkedListEntry<E>>
     implements Iterator<E> {
   final LinkedList<E> _list;
   final int _modificationCount;
@@ -185,7 +185,7 @@
 /**
  * Entry element for a [LinkedList]. Any entry must extend this class.
  */
-abstract class LinkedListEntry<E extends LinkedListEntry>
+abstract class LinkedListEntry<E extends LinkedListEntry<E>>
     implements _LinkedListLink {
   LinkedList<E> _list;
   _LinkedListLink _next;
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index ad5afc3..80425fd 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.dart
@@ -80,7 +80,7 @@
         _chunkedSink =
             converter.startChunkedConversion(new _EventSinkAdapter(sink));
 
-  void add(T o) => _chunkedSink.add(o);
+  void add(S o) => _chunkedSink.add(o);
   void addError(Object error, [StackTrace stackTrace]) {
     _eventSink.addError(error, stackTrace);
   }
diff --git a/sdk/lib/core/annotations.dart b/sdk/lib/core/annotations.dart
index 7bdc5f5..a0f70a4 100644
--- a/sdk/lib/core/annotations.dart
+++ b/sdk/lib/core/annotations.dart
@@ -89,16 +89,21 @@
  * instance fields, where it means that the implicit getter and setter of the
  * field is marked as overriding, but the field itself is not.
  *
- * A tool may report if no declaration of an annotated member is inherited by
- * the class from either a superclass or an interface.
- *
- * The intent of the "override" notation is to catch situations where a
+ * The intent of the "@override" notation is to catch situations where a
  * superclass renames a member, and an independent subclass which used to
  * override the member, could silently continue working using the
  * superclass implementation.
  *
- * The "@override" annotation is intentionally not used in the core libraries.
- * It is intended for the editor, or similar tools, to support user written
- * code.
+ * The editor, or a similar tool aimed at the programmer, may report if no
+ * declaration of an annotated member is inherited by the class from either a
+ * superclass or an interface.
+ *
+ * Use the "@override" annotation judiciously and only for methods where
+ * the superclass is not under the programmer's control, the superclass is in a
+ * different library or package, and it is not considered stable.
+ * In any case, the use of "@override" is optional.
+ *
+ * For example, the annotation is intentionally not used in the Dart platform
+ * libraries, since they only depend on themselves.
  */
 const override = const _Override();
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 6ef98dd..2331425 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -38,7 +38,7 @@
 import 'dart:web_gl' as gl;
 import 'dart:web_sql';
 import 'dart:_isolate_helper' show IsolateNatives;
-import 'dart:_foreign_helper' show JS;
+import 'dart:_foreign_helper' show JS, JS_INTERCEPTOR_CONSTANT;
 // Copyright (c) 2012, 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.
@@ -57,7 +57,7 @@
 import 'dart:_interceptors' show
     Interceptor, JSExtendableArray, findInterceptorConstructorForType,
     findConstructorForNativeSubclassType, getNativeInterceptor,
-    setDispatchProperty, findInterceptorForType;
+    setDispatchProperty;
 
 export 'dart:math' show Rectangle, Point;
 
@@ -7777,7 +7777,7 @@
 
 @DocsEditable()
 @DomName('DOMStringList')
-class DomStringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List native "DOMStringList" {
+class DomStringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List<String> native "DOMStringList" {
   // To suppress missing implicit constructor warnings.
   factory DomStringList._() { throw new UnsupportedError("Not supported"); }
 
@@ -8372,7 +8372,7 @@
 // ElementList as there are valid cases where a NodeList JavaScript object
 // contains Node objects that are not Elements.
 class _FrozenElementList<T extends Element> extends ListBase<T>
-    implements ElementList, NodeListWrapper {
+    implements ElementList<T>, NodeListWrapper {
   final List<Node> _nodeList;
   // The subset of _nodeList that are Elements.
   List<Element> _elementList;
@@ -11241,7 +11241,7 @@
 
 @DocsEditable()
 @DomName('FileList')
-class FileList extends Interceptor with ListMixin<File>, ImmutableListMixin<File> implements JavaScriptIndexingBehavior, List native "FileList" {
+class FileList extends Interceptor with ListMixin<File>, ImmutableListMixin<File> implements JavaScriptIndexingBehavior, List<File> native "FileList" {
   // To suppress missing implicit constructor warnings.
   factory FileList._() { throw new UnsupportedError("Not supported"); }
 
@@ -12235,7 +12235,7 @@
 
 @DocsEditable()
 @DomName('HTMLCollection')
-class HtmlCollection extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List native "HTMLCollection" {
+class HtmlCollection extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "HTMLCollection" {
   // To suppress missing implicit constructor warnings.
   factory HtmlCollection._() { throw new UnsupportedError("Not supported"); }
 
@@ -12630,7 +12630,7 @@
  * * [Using XMLHttpRequest](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest)
  */
 @DomName('XMLHttpRequest')
-class HttpRequest extends XmlHttpRequestEventTarget native "XMLHttpRequest" {
+class HttpRequest extends HttpRequestEventTarget native "XMLHttpRequest" {
 
   /**
    * Creates a URL get request for the specified [url].
@@ -13184,10 +13184,100 @@
 
 
 @DocsEditable()
+@DomName('XMLHttpRequestEventTarget')
+@Experimental() // untriaged
+class HttpRequestEventTarget extends EventTarget native "XMLHttpRequestEventTarget" {
+  // To suppress missing implicit constructor warnings.
+  factory HttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('XMLHttpRequestEventTarget.abortEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
+
+  @DomName('XMLHttpRequestEventTarget.errorEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
+
+  @DomName('XMLHttpRequestEventTarget.loadEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
+
+  @DomName('XMLHttpRequestEventTarget.loadendEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
+
+  @DomName('XMLHttpRequestEventTarget.loadstartEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
+
+  @DomName('XMLHttpRequestEventTarget.progressEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
+
+  @DomName('XMLHttpRequestEventTarget.timeoutEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
+
+  @DomName('XMLHttpRequestEventTarget.onabort')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onerror')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onload')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onloadend')
+  @DocsEditable()
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.IE, '10')
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onloadstart')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onprogress')
+  @DocsEditable()
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.IE, '10')
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.ontimeout')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
+}
+// Copyright (c) 2012, 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.
+
+
+@DocsEditable()
 @DomName('XMLHttpRequestUpload')
 // http://xhr.spec.whatwg.org/#xmlhttprequestupload
 @Experimental()
-class HttpRequestUpload extends XmlHttpRequestEventTarget native "XMLHttpRequestUpload,XMLHttpRequestEventTarget" {
+class HttpRequestUpload extends HttpRequestEventTarget native "XMLHttpRequestUpload,XMLHttpRequestEventTarget" {
   // To suppress missing implicit constructor warnings.
   factory HttpRequestUpload._() { throw new UnsupportedError("Not supported"); }
 }
@@ -16512,7 +16602,7 @@
 @DocsEditable()
 @DomName('MimeTypeArray')
 @Experimental() // non-standard
-class MimeTypeArray extends Interceptor with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements JavaScriptIndexingBehavior, List native "MimeTypeArray" {
+class MimeTypeArray extends Interceptor with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements JavaScriptIndexingBehavior, List<MimeType> native "MimeTypeArray" {
   // To suppress missing implicit constructor warnings.
   factory MimeTypeArray._() { throw new UnsupportedError("Not supported"); }
 
@@ -17816,7 +17906,7 @@
 
 @DocsEditable()
 @DomName('NodeList')
-class NodeList extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List native "NodeList,RadioNodeList" {
+class NodeList extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NodeList,RadioNodeList" {
   // To suppress missing implicit constructor warnings.
   factory NodeList._() { throw new UnsupportedError("Not supported"); }
 
@@ -18898,7 +18988,7 @@
 @DocsEditable()
 @DomName('PluginArray')
 @Experimental() // non-standard
-class PluginArray extends Interceptor with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements JavaScriptIndexingBehavior, List native "PluginArray" {
+class PluginArray extends Interceptor with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements JavaScriptIndexingBehavior, List<Plugin> native "PluginArray" {
   // To suppress missing implicit constructor warnings.
   factory PluginArray._() { throw new UnsupportedError("Not supported"); }
 
@@ -20869,7 +20959,7 @@
 @DomName('SourceBufferList')
 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebufferlist
 @Experimental()
-class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements JavaScriptIndexingBehavior, List native "SourceBufferList" {
+class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements JavaScriptIndexingBehavior, List<SourceBuffer> native "SourceBufferList" {
   // To suppress missing implicit constructor warnings.
   factory SourceBufferList._() { throw new UnsupportedError("Not supported"); }
 
@@ -21048,7 +21138,7 @@
 @DomName('SpeechGrammarList')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-speechgrammarlist
 @Experimental()
-class SpeechGrammarList extends Interceptor with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements JavaScriptIndexingBehavior, List native "SpeechGrammarList" {
+class SpeechGrammarList extends Interceptor with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements JavaScriptIndexingBehavior, List<SpeechGrammar> native "SpeechGrammarList" {
   // To suppress missing implicit constructor warnings.
   factory SpeechGrammarList._() { throw new UnsupportedError("Not supported"); }
 
@@ -22792,7 +22882,7 @@
 @DomName('TextTrackCueList')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcuelist
 @Experimental()
-class TextTrackCueList extends Interceptor with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements JavaScriptIndexingBehavior, List native "TextTrackCueList" {
+class TextTrackCueList extends Interceptor with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List<TextTrackCue>, JavaScriptIndexingBehavior native "TextTrackCueList" {
   // To suppress missing implicit constructor warnings.
   factory TextTrackCueList._() { throw new UnsupportedError("Not supported"); }
 
@@ -22861,7 +22951,7 @@
 @DomName('TextTrackList')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttracklist
 @Experimental()
-class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements JavaScriptIndexingBehavior, List native "TextTrackList" {
+class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements JavaScriptIndexingBehavior, List<TextTrack> native "TextTrackList" {
   // To suppress missing implicit constructor warnings.
   factory TextTrackList._() { throw new UnsupportedError("Not supported"); }
 
@@ -23165,7 +23255,7 @@
 @DomName('TouchList')
 // http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
 @Experimental()
-class TouchList extends Interceptor with ListMixin<Touch>, ImmutableListMixin<Touch> implements JavaScriptIndexingBehavior, List native "TouchList" {
+class TouchList extends Interceptor with ListMixin<Touch>, ImmutableListMixin<Touch> implements JavaScriptIndexingBehavior, List<Touch> native "TouchList" {
   /// NB: This constructor likely does not work as you might expect it to! This
   /// constructor will simply fail (returning null) if you are not on a device
   /// with touch enabled. See dartbug.com/8314.
@@ -24182,6 +24272,33 @@
 
 
 @DocsEditable()
+/**
+ * Top-level container for the current browser tab or window.
+ *
+ * In a web browser, each window has a [Window] object, but within the context
+ * of a script, a [Window] object represents only the current window. In
+ * addition to the open window, each window, tab, and iframe has its own
+ * [Window] object. A [Window] contains a [Document] object, which contains this
+ * web page's content.
+ *
+ * Use `window` to access properties of the current window. For example:
+ *
+ *     // Draw a scene when the window repaints.
+ *     drawScene(num delta) {...}
+ *     window.animationFrame.then(drawScene);.
+ *
+ *     // Write to the console.
+ *     window.console.log('Jinkies!');
+ *     window.console.error('Jeepers!');
+ *
+ * **Note:** This class represents the current window, whereas [WindowBase] is
+ * a representation of any window, including other tabs, windows, and frames.
+ *
+ * ## Other resources
+ *
+ * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
+ * * [Window](http://www.w3.org/TR/Window/) from the W3C.
+ */
 @DomName('Window')
 class Window extends EventTarget implements WindowBase, _WindowTimers, WindowBase64 native "Window,DOMWindow" {
 
@@ -25699,96 +25816,6 @@
 
 
 @DocsEditable()
-@DomName('XMLHttpRequestEventTarget')
-@Experimental() // untriaged
-class XmlHttpRequestEventTarget extends EventTarget native "XMLHttpRequestEventTarget" {
-  // To suppress missing implicit constructor warnings.
-  factory XmlHttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('XMLHttpRequestEventTarget.abortEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
-
-  @DomName('XMLHttpRequestEventTarget.errorEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
-
-  @DomName('XMLHttpRequestEventTarget.loadEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
-
-  @DomName('XMLHttpRequestEventTarget.loadendEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
-
-  @DomName('XMLHttpRequestEventTarget.loadstartEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
-
-  @DomName('XMLHttpRequestEventTarget.progressEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
-
-  @DomName('XMLHttpRequestEventTarget.timeoutEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
-
-  @DomName('XMLHttpRequestEventTarget.onabort')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onerror')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onload')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onloadend')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.FIREFOX)
-  @SupportedBrowser(SupportedBrowser.IE, '10')
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onloadstart')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onprogress')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.FIREFOX)
-  @SupportedBrowser(SupportedBrowser.IE, '10')
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.ontimeout')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
-}
-// Copyright (c) 2012, 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.
-
-
-@DocsEditable()
 @DomName('XMLSerializer')
 // http://domparsing.spec.whatwg.org/#the-xmlserializer-interface
 @deprecated // stable
@@ -26101,7 +26128,7 @@
 
 @DocsEditable()
 @DomName('ClientRectList')
-class _ClientRectList extends Interceptor with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements JavaScriptIndexingBehavior, List native "ClientRectList" {
+class _ClientRectList extends Interceptor with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List<Rectangle>, JavaScriptIndexingBehavior native "ClientRectList" {
   // To suppress missing implicit constructor warnings.
   factory _ClientRectList._() { throw new UnsupportedError("Not supported"); }
 
@@ -26177,7 +26204,7 @@
 
 @DocsEditable()
 @DomName('CSSRuleList')
-class _CssRuleList extends Interceptor with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements JavaScriptIndexingBehavior, List native "CSSRuleList" {
+class _CssRuleList extends Interceptor with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements JavaScriptIndexingBehavior, List<CssRule> native "CSSRuleList" {
   // To suppress missing implicit constructor warnings.
   factory _CssRuleList._() { throw new UnsupportedError("Not supported"); }
 
@@ -26242,7 +26269,7 @@
 @DomName('CSSValueList')
 // http://dev.w3.org/csswg/cssom/
 @deprecated // deprecated
-class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements JavaScriptIndexingBehavior, List native "CSSValueList" {
+class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements JavaScriptIndexingBehavior, List<_CSSValue> native "CSSValueList" {
   // To suppress missing implicit constructor warnings.
   factory _CssValueList._() { throw new UnsupportedError("Not supported"); }
 
@@ -26468,7 +26495,7 @@
 @DomName('GamepadList')
 // https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html
 @Experimental()
-class _GamepadList extends Interceptor with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements JavaScriptIndexingBehavior, List native "GamepadList" {
+class _GamepadList extends Interceptor with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements JavaScriptIndexingBehavior, List<Gamepad> native "GamepadList" {
   // To suppress missing implicit constructor warnings.
   factory _GamepadList._() { throw new UnsupportedError("Not supported"); }
 
@@ -26709,7 +26736,7 @@
 @DomName('NamedNodeMap')
 // http://dom.spec.whatwg.org/#namednodemap
 @deprecated // deprecated
-class _NamedNodeMap extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List native "NamedNodeMap,MozNamedAttrMap" {
+class _NamedNodeMap extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NamedNodeMap,MozNamedAttrMap" {
   // To suppress missing implicit constructor warnings.
   factory _NamedNodeMap._() { throw new UnsupportedError("Not supported"); }
 
@@ -26905,7 +26932,7 @@
 @DomName('SpeechInputResultList')
 // http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#speech_input_result_list_interface
 @Experimental()
-class _SpeechInputResultList extends Interceptor with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements JavaScriptIndexingBehavior, List native "SpeechInputResultList" {
+class _SpeechInputResultList extends Interceptor with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements JavaScriptIndexingBehavior, List<SpeechInputResult> native "SpeechInputResultList" {
   // To suppress missing implicit constructor warnings.
   factory _SpeechInputResultList._() { throw new UnsupportedError("Not supported"); }
 
@@ -26970,7 +26997,7 @@
 @DomName('SpeechRecognitionResultList')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechrecognitionresultlist
 @Experimental()
-class _SpeechRecognitionResultList extends Interceptor with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements JavaScriptIndexingBehavior, List native "SpeechRecognitionResultList" {
+class _SpeechRecognitionResultList extends Interceptor with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements JavaScriptIndexingBehavior, List<SpeechRecognitionResult> native "SpeechRecognitionResultList" {
   // To suppress missing implicit constructor warnings.
   factory _SpeechRecognitionResultList._() { throw new UnsupportedError("Not supported"); }
 
@@ -27033,7 +27060,7 @@
 
 @DocsEditable()
 @DomName('StyleSheetList')
-class _StyleSheetList extends Interceptor with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements JavaScriptIndexingBehavior, List native "StyleSheetList" {
+class _StyleSheetList extends Interceptor with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements JavaScriptIndexingBehavior, List<StyleSheet> native "StyleSheetList" {
   // To suppress missing implicit constructor warnings.
   factory _StyleSheetList._() { throw new UnsupportedError("Not supported"); }
 
@@ -27580,17 +27607,16 @@
 
 
 /**
- * An object representing the top-level context object for web scripting.
+ * Top-level container for a browser tab or window.
  *
- * In a web browser, a [Window] object represents the actual browser window.
- * In a multi-tabbed browser, each tab has its own [Window] object. A [Window]
- * is the container that displays a [Document]'s content. All web scripting
- * happens within the context of a [Window] object.
+ * In a web browser, a [WindowBase] object represents any browser window.  This
+ * abstract class contains the state of the window and its relation to other
+ * windows, such as which window opened it.
  *
  * **Note:** This class represents any window, whereas [Window] is
- * used to access the properties and content of the current window.
+ * used to access the properties and content of the current window or tab.
  *
- * See also:
+ * ## Other resources
  *
  * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
  * * [Window](http://www.w3.org/TR/Window/) from the W3C.
@@ -28222,6 +28248,121 @@
 
 
 /**
+ * A factory to expose DOM events as Streams.
+ */
+class EventStreamProvider<T extends Event> {
+  final String _eventType;
+
+  const EventStreamProvider(this._eventType);
+
+  /**
+   * Gets a [Stream] for this event type, on the specified target.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
+   *
+   *     // Alternate method:
+   *     Element.keyDownEvent.forTarget(element).capture(...);
+   *
+   * Or for listening to an event which will bubble through the DOM tree:
+   *
+   *     MediaElement.pauseEvent.forTarget(document.body).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
+    new _EventStream(e, _eventType, useCapture);
+
+  /**
+   * Gets an [ElementEventStream] for this event type, on the specified element.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
+   *
+   *     // Alternate method:
+   *     Element.keyDownEvent.forElement(element).capture(...);
+   *
+   * Or for listening to an event which will bubble through the DOM tree:
+   *
+   *     MediaElement.pauseEvent.forElement(document.body).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
+    return new _ElementEventStreamImpl(e, _eventType, useCapture);
+  }
+
+  /**
+   * Gets an [ElementEventStream] for this event type, on the list of elements.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
+    return new _ElementListEventStreamImpl(e, _eventType, useCapture);
+  }
+
+  /**
+   * Gets the type of the event which this would listen for on the specified
+   * event target.
+   *
+   * The target is necessary because some browsers may use different event names
+   * for the same purpose and the target allows differentiating browser support.
+   */
+  String getEventType(EventTarget target) {
+    return _eventType;
+  }
+}
+
+/** A specialized Stream available to [Element]s to enable event delegation. */
+abstract class ElementStream<T extends Event> implements Stream<T> {
+  /**
+   * Return a stream that only fires when the particular event fires for
+   * elements matching the specified CSS selector.
+   *
+   * This is the Dart equivalent to jQuery's
+   * [delegate](http://api.jquery.com/delegate/).
+   */
+  Stream<T> matches(String selector);
+
+  /**
+   * Adds a capturing subscription to this stream.
+   *
+   * If the target of the event is a descendant of the element from which this
+   * stream derives then [onData] is called before the event propagates down to
+   * the target. This is the opposite of bubbling behavior, where the event
+   * is first processed for the event target and then bubbles upward.
+   *
+   * ## Other resources
+   *
+   * * [Event Capture]
+   * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
+   * from the W3C DOM Events specification.
+   */
+  StreamSubscription<T> capture(void onData(T event));
+}
+
+/**
  * Adapter for exposing DOM events as Dart streams.
  */
 class _EventStream<T extends Event> extends Stream<T> {
@@ -28247,20 +28388,6 @@
   }
 }
 
-/** A specialized Stream available to [Element]s to enable event delegation. */
-abstract class ElementStream<T extends Event> implements Stream<T> {
-  /**
-   * Return a stream that only fires when the particular event fires for
-   * elements matching the specified CSS selector.
-   *
-   * This is the Dart equivalent to jQuery's
-   * [delegate](http://api.jquery.com/delegate/).
-   */
-  Stream<T> matches(String selector);
-
-  StreamSubscription<T> capture(void onData(T event));
-}
-
 /**
  * Adapter for exposing DOM Element events as streams, while also allowing
  * event delegation.
@@ -28327,6 +28454,83 @@
   bool get isBroadcast => true;
 }
 
+class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
+  int _pauseCount = 0;
+  EventTarget _target;
+  final String _eventType;
+  var _onData;
+  final bool _useCapture;
+
+  _EventStreamSubscription(this._target, this._eventType, onData,
+      this._useCapture) : _onData = _wrapZone(onData) {
+    _tryResume();
+  }
+
+  void cancel() {
+    if (_canceled) return;
+
+    _unlisten();
+    // Clear out the target to indicate this is complete.
+    _target = null;
+    _onData = null;
+  }
+
+  bool get _canceled => _target == null;
+
+  void onData(void handleData(T event)) {
+    if (_canceled) {
+      throw new StateError("Subscription has been canceled.");
+    }
+    // Remove current event listener.
+    _unlisten();
+
+    _onData = _wrapZone(handleData);
+    _tryResume();
+  }
+
+  /// Has no effect.
+  void onError(Function handleError) {}
+
+  /// Has no effect.
+  void onDone(void handleDone()) {}
+
+  void pause([Future resumeSignal]) {
+    if (_canceled) return;
+    ++_pauseCount;
+    _unlisten();
+
+    if (resumeSignal != null) {
+      resumeSignal.whenComplete(resume);
+    }
+  }
+
+  bool get isPaused => _pauseCount > 0;
+
+  void resume() {
+    if (_canceled || !isPaused) return;
+    --_pauseCount;
+    _tryResume();
+  }
+
+  void _tryResume() {
+    if (_onData != null && !isPaused) {
+      _target.addEventListener(_eventType, _onData, _useCapture);
+    }
+  }
+
+  void _unlisten() {
+    if (_onData != null) {
+      _target.removeEventListener(_eventType, _onData, _useCapture);
+    }
+  }
+
+  Future asFuture([var futureValue]) {
+    // We just need a future that will never succeed or fail.
+    Completer completer = new Completer();
+    return completer.future;
+  }
+}
+
 /**
  * A stream of custom events, which enables the user to "fire" (add) their own
  * custom events to a stream.
@@ -28440,160 +28644,6 @@
   }
 }
 
-class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
-  int _pauseCount = 0;
-  EventTarget _target;
-  final String _eventType;
-  var _onData;
-  final bool _useCapture;
-
-  _EventStreamSubscription(this._target, this._eventType, onData,
-      this._useCapture) : _onData = _wrapZone(onData) {
-    _tryResume();
-  }
-
-  void cancel() {
-    if (_canceled) return;
-
-    _unlisten();
-    // Clear out the target to indicate this is complete.
-    _target = null;
-    _onData = null;
-  }
-
-  bool get _canceled => _target == null;
-
-  void onData(void handleData(T event)) {
-    if (_canceled) {
-      throw new StateError("Subscription has been canceled.");
-    }
-    // Remove current event listener.
-    _unlisten();
-
-    _onData = _wrapZone(handleData);
-    _tryResume();
-  }
-
-  /// Has no effect.
-  void onError(Function handleError) {}
-
-  /// Has no effect.
-  void onDone(void handleDone()) {}
-
-  void pause([Future resumeSignal]) {
-    if (_canceled) return;
-    ++_pauseCount;
-    _unlisten();
-
-    if (resumeSignal != null) {
-      resumeSignal.whenComplete(resume);
-    }
-  }
-
-  bool get isPaused => _pauseCount > 0;
-
-  void resume() {
-    if (_canceled || !isPaused) return;
-    --_pauseCount;
-    _tryResume();
-  }
-
-  void _tryResume() {
-    if (_onData != null && !isPaused) {
-      _target.addEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  void _unlisten() {
-    if (_onData != null) {
-      _target.removeEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  Future asFuture([var futureValue]) {
-    // We just need a future that will never succeed or fail.
-    Completer completer = new Completer();
-    return completer.future;
-  }
-}
-
-/**
- * A factory to expose DOM events as Streams.
- */
-class EventStreamProvider<T extends Event> {
-  final String _eventType;
-
-  const EventStreamProvider(this._eventType);
-
-  /**
-   * Gets a [Stream] for this event type, on the specified target.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
-   *
-   * Or for listening to an event which will bubble through the DOM tree:
-   *
-   *     MediaElement.pauseEvent.forTarget(document.body).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
-    new _EventStream(e, _eventType, useCapture);
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the specified element.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the list of elements.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets the type of the event which this would listen for on the specified
-   * event target.
-   *
-   * The target is necessary because some browsers may use different event names
-   * for the same purpose and the target allows differentiating browser support.
-   */
-  String getEventType(EventTarget target) {
-    return _eventType;
-  }
-}
-
 /**
  * A factory to expose DOM events as streams, where the DOM event name has to
  * be determined on the fly (for example, mouse wheel events).
@@ -31788,7 +31838,7 @@
 
   /** Helper to statically create the dispatch record. */
   static _makeRecord() {
-    var interceptor = findInterceptorForType(KeyboardEvent);
+    var interceptor = JS_INTERCEPTOR_CONSTANT(KeyboardEvent);
     return makeLeafDispatchRecord(interceptor);
   }
 
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 3af252e..7d5d233 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -8149,7 +8149,7 @@
 
 @DocsEditable()
 @DomName('DOMStringList')
-class DomStringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List {
+class DomStringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List<String> {
   // To suppress missing implicit constructor warnings.
   factory DomStringList._() { throw new UnsupportedError("Not supported"); }
 
@@ -8765,7 +8765,7 @@
 // ElementList as there are valid cases where a NodeList JavaScript object
 // contains Node objects that are not Elements.
 class _FrozenElementList<T extends Element> extends ListBase<T>
-    implements ElementList, NodeListWrapper {
+    implements ElementList<T>, NodeListWrapper {
   final List<Node> _nodeList;
   // The subset of _nodeList that are Elements.
   List<Element> _elementList;
@@ -11490,7 +11490,7 @@
 
 @DocsEditable()
 @DomName('FileList')
-class FileList extends NativeFieldWrapperClass2 with ListMixin<File>, ImmutableListMixin<File> implements List {
+class FileList extends NativeFieldWrapperClass2 with ListMixin<File>, ImmutableListMixin<File> implements List<File> {
   // To suppress missing implicit constructor warnings.
   factory FileList._() { throw new UnsupportedError("Not supported"); }
 
@@ -12619,7 +12619,7 @@
 
 @DocsEditable()
 @DomName('HTMLCollection')
-class HtmlCollection extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class HtmlCollection extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List<Node> {
   // To suppress missing implicit constructor warnings.
   factory HtmlCollection._() { throw new UnsupportedError("Not supported"); }
 
@@ -13171,7 +13171,7 @@
  * * [Using XMLHttpRequest](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest)
  */
 @DomName('XMLHttpRequest')
-class HttpRequest extends XmlHttpRequestEventTarget {
+class HttpRequest extends HttpRequestEventTarget {
 
   /**
    * Creates a URL get request for the specified [url].
@@ -13707,10 +13707,118 @@
 
 
 @DocsEditable()
+@DomName('XMLHttpRequestEventTarget')
+@Experimental() // untriaged
+class HttpRequestEventTarget extends EventTarget {
+  // To suppress missing implicit constructor warnings.
+  factory HttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('XMLHttpRequestEventTarget.abortEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
+
+  @DomName('XMLHttpRequestEventTarget.errorEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
+
+  @DomName('XMLHttpRequestEventTarget.loadEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
+
+  @DomName('XMLHttpRequestEventTarget.loadendEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
+
+  @DomName('XMLHttpRequestEventTarget.loadstartEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
+
+  @DomName('XMLHttpRequestEventTarget.progressEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
+
+  @DomName('XMLHttpRequestEventTarget.timeoutEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
+
+  @DomName('XMLHttpRequestEventTarget.addEventListener')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_addEventListener_Callback";
+
+  @DomName('XMLHttpRequestEventTarget.dispatchEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool dispatchEvent(Event event) native "XMLHttpRequestEventTarget_dispatchEvent_Callback";
+
+  @DomName('XMLHttpRequestEventTarget.removeEventListener')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_removeEventListener_Callback";
+
+  @DomName('XMLHttpRequestEventTarget.onabort')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onerror')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onload')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onloadend')
+  @DocsEditable()
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.IE, '10')
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onloadstart')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.onprogress')
+  @DocsEditable()
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.IE, '10')
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
+
+  @DomName('XMLHttpRequestEventTarget.ontimeout')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
+
+}
+// Copyright (c) 2012, 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
 @DomName('XMLHttpRequestUpload')
 // http://xhr.spec.whatwg.org/#xmlhttprequestupload
 @Experimental()
-class HttpRequestUpload extends XmlHttpRequestEventTarget {
+class HttpRequestUpload extends HttpRequestEventTarget {
   // To suppress missing implicit constructor warnings.
   factory HttpRequestUpload._() { throw new UnsupportedError("Not supported"); }
 
@@ -17692,7 +17800,7 @@
 @DocsEditable()
 @DomName('MimeTypeArray')
 @Experimental() // non-standard
-class MimeTypeArray extends NativeFieldWrapperClass2 with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements List {
+class MimeTypeArray extends NativeFieldWrapperClass2 with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements List<MimeType> {
   // To suppress missing implicit constructor warnings.
   factory MimeTypeArray._() { throw new UnsupportedError("Not supported"); }
 
@@ -19012,7 +19120,7 @@
 
 @DocsEditable()
 @DomName('NodeList')
-class NodeList extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class NodeList extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List<Node> {
   // To suppress missing implicit constructor warnings.
   factory NodeList._() { throw new UnsupportedError("Not supported"); }
 
@@ -20271,7 +20379,7 @@
 @DocsEditable()
 @DomName('PluginArray')
 @Experimental() // non-standard
-class PluginArray extends NativeFieldWrapperClass2 with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements List {
+class PluginArray extends NativeFieldWrapperClass2 with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements List<Plugin> {
   // To suppress missing implicit constructor warnings.
   factory PluginArray._() { throw new UnsupportedError("Not supported"); }
 
@@ -22395,7 +22503,7 @@
 @DomName('SourceBufferList')
 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebufferlist
 @Experimental()
-class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements List {
+class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements List<SourceBuffer> {
   // To suppress missing implicit constructor warnings.
   factory SourceBufferList._() { throw new UnsupportedError("Not supported"); }
 
@@ -22624,7 +22732,7 @@
 @DomName('SpeechGrammarList')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-speechgrammarlist
 @Experimental()
-class SpeechGrammarList extends NativeFieldWrapperClass2 with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements List {
+class SpeechGrammarList extends NativeFieldWrapperClass2 with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements List<SpeechGrammar> {
   // To suppress missing implicit constructor warnings.
   factory SpeechGrammarList._() { throw new UnsupportedError("Not supported"); }
 
@@ -24695,7 +24803,7 @@
 @DomName('TextTrackCueList')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcuelist
 @Experimental()
-class TextTrackCueList extends NativeFieldWrapperClass2 with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List {
+class TextTrackCueList extends NativeFieldWrapperClass2 with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List<TextTrackCue> {
   // To suppress missing implicit constructor warnings.
   factory TextTrackCueList._() { throw new UnsupportedError("Not supported"); }
 
@@ -24768,7 +24876,7 @@
 @DomName('TextTrackList')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttracklist
 @Experimental()
-class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements List {
+class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements List<TextTrack> {
   // To suppress missing implicit constructor warnings.
   factory TextTrackList._() { throw new UnsupportedError("Not supported"); }
 
@@ -25075,7 +25183,7 @@
 @DomName('TouchList')
 // http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
 @Experimental()
-class TouchList extends NativeFieldWrapperClass2 with ListMixin<Touch>, ImmutableListMixin<Touch> implements List {
+class TouchList extends NativeFieldWrapperClass2 with ListMixin<Touch>, ImmutableListMixin<Touch> implements List<Touch> {
   /// NB: This constructor likely does not work as you might expect it to! This
   /// constructor will simply fail (returning null) if you are not on a device
   /// with touch enabled. See dartbug.com/8314.
@@ -25499,13 +25607,13 @@
     if ((blob_OR_source_OR_stream is Blob || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_1(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) {
+    if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_2(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) {
+    if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_3(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) {
+    if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_4(blob_OR_source_OR_stream);
     }
     throw new ArgumentError("Incorrect number or type of arguments");
@@ -26022,6 +26130,33 @@
 
 
 @DocsEditable()
+/**
+ * Top-level container for the current browser tab or window.
+ *
+ * In a web browser, each window has a [Window] object, but within the context
+ * of a script, a [Window] object represents only the current window. In
+ * addition to the open window, each window, tab, and iframe has its own
+ * [Window] object. A [Window] contains a [Document] object, which contains this
+ * web page's content.
+ *
+ * Use `window` to access properties of the current window. For example:
+ *
+ *     // Draw a scene when the window repaints.
+ *     drawScene(num delta) {...}
+ *     window.animationFrame.then(drawScene);.
+ *
+ *     // Write to the console.
+ *     window.console.log('Jinkies!');
+ *     window.console.error('Jeepers!');
+ *
+ * **Note:** This class represents the current window, whereas [WindowBase] is
+ * a representation of any window, including other tabs, windows, and frames.
+ *
+ * ## Other resources
+ *
+ * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
+ * * [Window](http://www.w3.org/TR/Window/) from the W3C.
+ */
 @DomName('Window')
 class Window extends EventTarget implements WindowBase, _WindowTimers, WindowBase64 {
 
@@ -27439,114 +27574,6 @@
 
 
 @DocsEditable()
-@DomName('XMLHttpRequestEventTarget')
-@Experimental() // untriaged
-class XmlHttpRequestEventTarget extends EventTarget {
-  // To suppress missing implicit constructor warnings.
-  factory XmlHttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('XMLHttpRequestEventTarget.abortEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
-
-  @DomName('XMLHttpRequestEventTarget.errorEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
-
-  @DomName('XMLHttpRequestEventTarget.loadEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
-
-  @DomName('XMLHttpRequestEventTarget.loadendEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
-
-  @DomName('XMLHttpRequestEventTarget.loadstartEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
-
-  @DomName('XMLHttpRequestEventTarget.progressEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
-
-  @DomName('XMLHttpRequestEventTarget.timeoutEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
-
-  @DomName('XMLHttpRequestEventTarget.addEventListener')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void addEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_addEventListener_Callback";
-
-  @DomName('XMLHttpRequestEventTarget.dispatchEvent')
-  @DocsEditable()
-  @Experimental() // untriaged
-  bool dispatchEvent(Event event) native "XMLHttpRequestEventTarget_dispatchEvent_Callback";
-
-  @DomName('XMLHttpRequestEventTarget.removeEventListener')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_removeEventListener_Callback";
-
-  @DomName('XMLHttpRequestEventTarget.onabort')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onerror')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onload')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onloadend')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.FIREFOX)
-  @SupportedBrowser(SupportedBrowser.IE, '10')
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onloadstart')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.onprogress')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.FIREFOX)
-  @SupportedBrowser(SupportedBrowser.IE, '10')
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
-
-  @DomName('XMLHttpRequestEventTarget.ontimeout')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
-
-}
-// Copyright (c) 2012, 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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable()
 @DomName('XMLSerializer')
 // http://domparsing.spec.whatwg.org/#the-xmlserializer-interface
 @deprecated // stable
@@ -27889,7 +27916,7 @@
 
 @DocsEditable()
 @DomName('ClientRectList')
-class _ClientRectList extends NativeFieldWrapperClass2 with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List {
+class _ClientRectList extends NativeFieldWrapperClass2 with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List<Rectangle> {
   // To suppress missing implicit constructor warnings.
   factory _ClientRectList._() { throw new UnsupportedError("Not supported"); }
 
@@ -27972,7 +27999,7 @@
 
 @DocsEditable()
 @DomName('CSSRuleList')
-class _CssRuleList extends NativeFieldWrapperClass2 with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements List {
+class _CssRuleList extends NativeFieldWrapperClass2 with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements List<CssRule> {
   // To suppress missing implicit constructor warnings.
   factory _CssRuleList._() { throw new UnsupportedError("Not supported"); }
 
@@ -28041,7 +28068,7 @@
 @DomName('CSSValueList')
 // http://dev.w3.org/csswg/cssom/
 @deprecated // deprecated
-class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements List {
+class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements List<_CSSValue> {
   // To suppress missing implicit constructor warnings.
   factory _CssValueList._() { throw new UnsupportedError("Not supported"); }
 
@@ -28311,7 +28338,7 @@
 @DomName('GamepadList')
 // https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html
 @Experimental()
-class _GamepadList extends NativeFieldWrapperClass2 with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements List {
+class _GamepadList extends NativeFieldWrapperClass2 with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements List<Gamepad> {
   // To suppress missing implicit constructor warnings.
   factory _GamepadList._() { throw new UnsupportedError("Not supported"); }
 
@@ -28579,7 +28606,7 @@
 @DomName('NamedNodeMap')
 // http://dom.spec.whatwg.org/#namednodemap
 @deprecated // deprecated
-class _NamedNodeMap extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class _NamedNodeMap extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List<Node> {
   // To suppress missing implicit constructor warnings.
   factory _NamedNodeMap._() { throw new UnsupportedError("Not supported"); }
 
@@ -28797,7 +28824,7 @@
 @DomName('SpeechInputResultList')
 // http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#speech_input_result_list_interface
 @Experimental()
-class _SpeechInputResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements List {
+class _SpeechInputResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements List<SpeechInputResult> {
   // To suppress missing implicit constructor warnings.
   factory _SpeechInputResultList._() { throw new UnsupportedError("Not supported"); }
 
@@ -28866,7 +28893,7 @@
 @DomName('SpeechRecognitionResultList')
 // https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechrecognitionresultlist
 @Experimental()
-class _SpeechRecognitionResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements List {
+class _SpeechRecognitionResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements List<SpeechRecognitionResult> {
   // To suppress missing implicit constructor warnings.
   factory _SpeechRecognitionResultList._() { throw new UnsupportedError("Not supported"); }
 
@@ -28933,7 +28960,7 @@
 
 @DocsEditable()
 @DomName('StyleSheetList')
-class _StyleSheetList extends NativeFieldWrapperClass2 with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements List {
+class _StyleSheetList extends NativeFieldWrapperClass2 with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements List<StyleSheet> {
   // To suppress missing implicit constructor warnings.
   factory _StyleSheetList._() { throw new UnsupportedError("Not supported"); }
 
@@ -29525,17 +29552,16 @@
 
 
 /**
- * An object representing the top-level context object for web scripting.
+ * Top-level container for a browser tab or window.
  *
- * In a web browser, a [Window] object represents the actual browser window.
- * In a multi-tabbed browser, each tab has its own [Window] object. A [Window]
- * is the container that displays a [Document]'s content. All web scripting
- * happens within the context of a [Window] object.
+ * In a web browser, a [WindowBase] object represents any browser window.  This
+ * abstract class contains the state of the window and its relation to other
+ * windows, such as which window opened it.
  *
  * **Note:** This class represents any window, whereas [Window] is
- * used to access the properties and content of the current window.
+ * used to access the properties and content of the current window or tab.
  *
- * See also:
+ * ## Other resources
  *
  * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
  * * [Window](http://www.w3.org/TR/Window/) from the W3C.
@@ -30167,6 +30193,121 @@
 
 
 /**
+ * A factory to expose DOM events as Streams.
+ */
+class EventStreamProvider<T extends Event> {
+  final String _eventType;
+
+  const EventStreamProvider(this._eventType);
+
+  /**
+   * Gets a [Stream] for this event type, on the specified target.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
+   *
+   *     // Alternate method:
+   *     Element.keyDownEvent.forTarget(element).capture(...);
+   *
+   * Or for listening to an event which will bubble through the DOM tree:
+   *
+   *     MediaElement.pauseEvent.forTarget(document.body).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
+    new _EventStream(e, _eventType, useCapture);
+
+  /**
+   * Gets an [ElementEventStream] for this event type, on the specified element.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
+   *
+   *     // Alternate method:
+   *     Element.keyDownEvent.forElement(element).capture(...);
+   *
+   * Or for listening to an event which will bubble through the DOM tree:
+   *
+   *     MediaElement.pauseEvent.forElement(document.body).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
+    return new _ElementEventStreamImpl(e, _eventType, useCapture);
+  }
+
+  /**
+   * Gets an [ElementEventStream] for this event type, on the list of elements.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
+    return new _ElementListEventStreamImpl(e, _eventType, useCapture);
+  }
+
+  /**
+   * Gets the type of the event which this would listen for on the specified
+   * event target.
+   *
+   * The target is necessary because some browsers may use different event names
+   * for the same purpose and the target allows differentiating browser support.
+   */
+  String getEventType(EventTarget target) {
+    return _eventType;
+  }
+}
+
+/** A specialized Stream available to [Element]s to enable event delegation. */
+abstract class ElementStream<T extends Event> implements Stream<T> {
+  /**
+   * Return a stream that only fires when the particular event fires for
+   * elements matching the specified CSS selector.
+   *
+   * This is the Dart equivalent to jQuery's
+   * [delegate](http://api.jquery.com/delegate/).
+   */
+  Stream<T> matches(String selector);
+
+  /**
+   * Adds a capturing subscription to this stream.
+   *
+   * If the target of the event is a descendant of the element from which this
+   * stream derives then [onData] is called before the event propagates down to
+   * the target. This is the opposite of bubbling behavior, where the event
+   * is first processed for the event target and then bubbles upward.
+   *
+   * ## Other resources
+   *
+   * * [Event Capture]
+   * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
+   * from the W3C DOM Events specification.
+   */
+  StreamSubscription<T> capture(void onData(T event));
+}
+
+/**
  * Adapter for exposing DOM events as Dart streams.
  */
 class _EventStream<T extends Event> extends Stream<T> {
@@ -30192,20 +30333,6 @@
   }
 }
 
-/** A specialized Stream available to [Element]s to enable event delegation. */
-abstract class ElementStream<T extends Event> implements Stream<T> {
-  /**
-   * Return a stream that only fires when the particular event fires for
-   * elements matching the specified CSS selector.
-   *
-   * This is the Dart equivalent to jQuery's
-   * [delegate](http://api.jquery.com/delegate/).
-   */
-  Stream<T> matches(String selector);
-
-  StreamSubscription<T> capture(void onData(T event));
-}
-
 /**
  * Adapter for exposing DOM Element events as streams, while also allowing
  * event delegation.
@@ -30272,6 +30399,83 @@
   bool get isBroadcast => true;
 }
 
+class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
+  int _pauseCount = 0;
+  EventTarget _target;
+  final String _eventType;
+  var _onData;
+  final bool _useCapture;
+
+  _EventStreamSubscription(this._target, this._eventType, onData,
+      this._useCapture) : _onData = _wrapZone(onData) {
+    _tryResume();
+  }
+
+  void cancel() {
+    if (_canceled) return;
+
+    _unlisten();
+    // Clear out the target to indicate this is complete.
+    _target = null;
+    _onData = null;
+  }
+
+  bool get _canceled => _target == null;
+
+  void onData(void handleData(T event)) {
+    if (_canceled) {
+      throw new StateError("Subscription has been canceled.");
+    }
+    // Remove current event listener.
+    _unlisten();
+
+    _onData = _wrapZone(handleData);
+    _tryResume();
+  }
+
+  /// Has no effect.
+  void onError(Function handleError) {}
+
+  /// Has no effect.
+  void onDone(void handleDone()) {}
+
+  void pause([Future resumeSignal]) {
+    if (_canceled) return;
+    ++_pauseCount;
+    _unlisten();
+
+    if (resumeSignal != null) {
+      resumeSignal.whenComplete(resume);
+    }
+  }
+
+  bool get isPaused => _pauseCount > 0;
+
+  void resume() {
+    if (_canceled || !isPaused) return;
+    --_pauseCount;
+    _tryResume();
+  }
+
+  void _tryResume() {
+    if (_onData != null && !isPaused) {
+      _target.addEventListener(_eventType, _onData, _useCapture);
+    }
+  }
+
+  void _unlisten() {
+    if (_onData != null) {
+      _target.removeEventListener(_eventType, _onData, _useCapture);
+    }
+  }
+
+  Future asFuture([var futureValue]) {
+    // We just need a future that will never succeed or fail.
+    Completer completer = new Completer();
+    return completer.future;
+  }
+}
+
 /**
  * A stream of custom events, which enables the user to "fire" (add) their own
  * custom events to a stream.
@@ -30385,160 +30589,6 @@
   }
 }
 
-class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
-  int _pauseCount = 0;
-  EventTarget _target;
-  final String _eventType;
-  var _onData;
-  final bool _useCapture;
-
-  _EventStreamSubscription(this._target, this._eventType, onData,
-      this._useCapture) : _onData = _wrapZone(onData) {
-    _tryResume();
-  }
-
-  void cancel() {
-    if (_canceled) return;
-
-    _unlisten();
-    // Clear out the target to indicate this is complete.
-    _target = null;
-    _onData = null;
-  }
-
-  bool get _canceled => _target == null;
-
-  void onData(void handleData(T event)) {
-    if (_canceled) {
-      throw new StateError("Subscription has been canceled.");
-    }
-    // Remove current event listener.
-    _unlisten();
-
-    _onData = _wrapZone(handleData);
-    _tryResume();
-  }
-
-  /// Has no effect.
-  void onError(Function handleError) {}
-
-  /// Has no effect.
-  void onDone(void handleDone()) {}
-
-  void pause([Future resumeSignal]) {
-    if (_canceled) return;
-    ++_pauseCount;
-    _unlisten();
-
-    if (resumeSignal != null) {
-      resumeSignal.whenComplete(resume);
-    }
-  }
-
-  bool get isPaused => _pauseCount > 0;
-
-  void resume() {
-    if (_canceled || !isPaused) return;
-    --_pauseCount;
-    _tryResume();
-  }
-
-  void _tryResume() {
-    if (_onData != null && !isPaused) {
-      _target.addEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  void _unlisten() {
-    if (_onData != null) {
-      _target.removeEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  Future asFuture([var futureValue]) {
-    // We just need a future that will never succeed or fail.
-    Completer completer = new Completer();
-    return completer.future;
-  }
-}
-
-/**
- * A factory to expose DOM events as Streams.
- */
-class EventStreamProvider<T extends Event> {
-  final String _eventType;
-
-  const EventStreamProvider(this._eventType);
-
-  /**
-   * Gets a [Stream] for this event type, on the specified target.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
-   *
-   * Or for listening to an event which will bubble through the DOM tree:
-   *
-   *     MediaElement.pauseEvent.forTarget(document.body).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
-    new _EventStream(e, _eventType, useCapture);
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the specified element.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the list of elements.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets the type of the event which this would listen for on the specified
-   * event target.
-   *
-   * The target is necessary because some browsers may use different event names
-   * for the same purpose and the target allows differentiating browser support.
-   */
-  String getEventType(EventTarget target) {
-    return _eventType;
-  }
-}
-
 /**
  * A factory to expose DOM events as streams, where the DOM event name has to
  * be determined on the fly (for example, mouse wheel events).
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index af7fe54..10b6068 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -292,6 +292,7 @@
   bool canceled = false;
   bool nextRunning = false;
   bool closed = false;
+  Completer closeCompleter = new Completer();
 
   _AsyncDirectoryLister(String this.path,
                         bool this.recursive,
@@ -312,7 +313,7 @@
             next();
           } else {
             error(response);
-            controller.close();
+            close();
           }
         });
   }
@@ -321,12 +322,14 @@
     if (!nextRunning) next();
   }
 
-  void onCancel() {
+  Future onCancel() {
     canceled = true;
     // If we are active, but not requesting, close.
     if (!nextRunning) {
       close();
     }
+
+    return closeCompleter.future;
   }
 
   void next() {
@@ -336,10 +339,12 @@
     }
     if (id == null) return;
     if (controller.isPaused) return;
-    assert(!nextRunning);
+    if (nextRunning) return;
     nextRunning = true;
     _IOService.dispatch(_DIRECTORY_LIST_NEXT, [id]).then((result) {
+      nextRunning = false;
       if (result is List) {
+        next();
         assert(result.length % 2 == 0);
         for (int i = 0; i < result.length; i++) {
           assert(i % 2 == 0);
@@ -357,25 +362,29 @@
               error(result[i]);
               break;
             case LIST_DONE:
-              close();
+              canceled = true;
               return;
           }
         }
       } else {
         controller.addError(new FileSystemException("Internal error"));
       }
-      nextRunning = false;
-      next();
     });
   }
 
   void close() {
     if (closed) return;
-    if (id == null) return;
-    closed = true;
-    _IOService.dispatch(_DIRECTORY_LIST_STOP, [id]).then((_) {
+    if (nextRunning) return;
+    void cleanup() {
       controller.close();
-    });
+      closeCompleter.complete();
+    }
+    closed = true;
+    if (id != null) {
+      _IOService.dispatch(_DIRECTORY_LIST_STOP, [id]).whenComplete(cleanup);
+    } else {
+      cleanup();
+    }
   }
 
   void error(message) {
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 16fb764..81d406d 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -349,6 +349,8 @@
    *     supports watching directories. Recursive watching is supported.
    *   * `Linux`: Uses `inotify`. The implementation supports watching both
    *     files and directories. Recursive watching is not supported.
+   *     Note: When watching files directly, delete events might not happen
+   *     as expected.
    *   * `Mac OS`: Uses `FSEvents`. The implementation supports watching both
    *     files and directories. Recursive watching is supported.
    *     Note: events happened slightly before calling [watch], may be part of
@@ -656,6 +658,7 @@
 
   static const int _MODIFY_ATTRIBUTES = 1 << 4;
   static const int _DELETE_SELF = 1 << 5;
+  static const int _IS_DIR = 1 << 6;
 
   /**
    * The type of event. See [FileSystemEvent] for a list of events.
@@ -668,7 +671,12 @@
    */
   final String path;
 
-  FileSystemEvent._(this.type, this.path);
+  /**
+   * Is `true` if the event target was a directory.
+   */
+  final bool isDirectory;
+
+  FileSystemEvent._(this.type, this.path, this.isDirectory);
 }
 
 
@@ -676,8 +684,8 @@
  * File system event for newly created file system objects.
  */
 class FileSystemCreateEvent extends FileSystemEvent {
-  FileSystemCreateEvent._(path)
-      : super._(FileSystemEvent.CREATE, path);
+  FileSystemCreateEvent._(path, isDirectory)
+      : super._(FileSystemEvent.CREATE, path, isDirectory);
 
   String toString() => "FileSystemCreateEvent('$path')";
 }
@@ -693,8 +701,8 @@
    */
   final bool contentChanged;
 
-  FileSystemModifyEvent._(path, this.contentChanged)
-      : super._(FileSystemEvent.MODIFY, path);
+  FileSystemModifyEvent._(path, isDirectory, this.contentChanged)
+      : super._(FileSystemEvent.MODIFY, path, isDirectory);
 
   String toString() =>
       "FileSystemModifyEvent('$path', contentChanged=$contentChanged)";
@@ -705,8 +713,8 @@
  * File system event for deletion of file system objects.
  */
 class FileSystemDeleteEvent extends FileSystemEvent {
-  FileSystemDeleteEvent._(path)
-      : super._(FileSystemEvent.DELETE, path);
+  FileSystemDeleteEvent._(path, isDirectory)
+      : super._(FileSystemEvent.DELETE, path, isDirectory);
 
   String toString() => "FileSystemDeleteEvent('$path')";
 }
@@ -722,8 +730,8 @@
    */
   final String destination;
 
-  FileSystemMoveEvent._(path, this.destination)
-      : super._(FileSystemEvent.MOVE, path);
+  FileSystemMoveEvent._(path, isDirectory, this.destination)
+      : super._(FileSystemEvent.MOVE, path, isDirectory);
 
   String toString() {
     var buffer = new StringBuffer();
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 42b8d6f..c1ec1bf 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -460,8 +460,8 @@
     _dataSink.add(data);
   }
 
-  void addError(error) {
-    _dataSink.addError(error);
+  void addError(error, [StackTrace stackTrace]) {
+    _dataSink.addError(error, stackTrace);
   }
 
   Future<T> addStream(Stream<List<int>> stream) {
@@ -697,7 +697,7 @@
 
 class _HttpResponse extends _HttpOutboundMessage<HttpResponse>
     implements HttpResponse {
-  int statusCode = 200;
+  int _statusCode = 200;
   String _reasonPhrase;
   List<Cookie> _cookies;
   _HttpRequest _httpRequest;
@@ -717,6 +717,12 @@
     return _cookies;
   }
 
+  int get statusCode => _statusCode;
+  void set statusCode(int statusCode) {
+    if (_headersWritten) throw new StateError("Header already sent");
+    _statusCode = statusCode;
+  }
+
   String get reasonPhrase => _findReasonPhrase(statusCode);
   void set reasonPhrase(String reasonPhrase) {
     if (_headersWritten) throw new StateError("Header already sent");
@@ -2094,8 +2100,9 @@
   // Indicated if the http server has been closed.
   bool closed = false;
 
-  // The server listen socket.
-  final ServerSocket _serverSocket;
+  // The server listen socket. Untyped as it can be both ServerSocket and
+  // SecureServerSocket.
+  final _serverSocket;
   final bool _closeServer;
 
   // Set of currently connected clients.
@@ -2238,7 +2245,8 @@
 
   void add(List<int> bytes) => _socket.add(bytes);
 
-  void addError(error) => _socket.addError(error);
+  void addError(error, [StackTrace stackTrace]) =>
+      _socket.addError(error, stackTrace);
 
   Future<Socket> addStream(Stream<List<int>> stream) {
     return _socket.addStream(stream);
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index ac4ce0a..042a469 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -38,7 +38,7 @@
   /**
    * Writes an error to the consumer.
    */
-  void addError(error);
+  void addError(error, [StackTrace stackTrace]);
 
   /**
    * Adds all elements of the given [stream] to `this`.
@@ -76,8 +76,8 @@
     _controller.add(data);
   }
 
-  void addError(error) {
-    _controller.addError(error);
+  void addError(error, [StackTrace stackTrace]) {
+    _controller.addError(error, stackTrace);
   }
 
   Future addStream(Stream<T> stream) {
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index 1053d37..11dee79 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.dart
@@ -5,19 +5,8 @@
 part of dart.io;
 
 /**
- * Deprecated: the [Platform] class exposes details of the machine and operating
+ * The [Platform] class exposes details of the machine and operating
  * system.
- *
- * This class has been replaced by adding the dart:platform library to Dart.
- * dart:platform is available on all browser and standalone platforms,
- * including Dart code that has been compiled to javascript.
- *
- * The dart:platform class has
- * the same top-level getters as the members of [Platform], except that the
- * [isWindows], [isLinux], [isAndroid], and [isMacOS] getters
- * have been removed. On platforms supporting dart:io, the getters of
- * dart:platform have the same values as the Platform class members, except
- * that [script] has been changed from a [String] to a file [Uri].
  */
 @deprecated
 class Platform {
diff --git a/sdk/lib/io/secure_server_socket.dart b/sdk/lib/io/secure_server_socket.dart
index eca89d3..affa57c 100644
--- a/sdk/lib/io/secure_server_socket.dart
+++ b/sdk/lib/io/secure_server_socket.dart
@@ -10,7 +10,7 @@
  *
  * See [SecureSocket] for more info.
  */
-class SecureServerSocket extends Stream<SecureSocket> implements ServerSocket {
+class SecureServerSocket extends Stream<SecureSocket> {
   final RawSecureServerSocket _socket;
 
   SecureServerSocket._(RawSecureServerSocket this._socket);
@@ -95,6 +95,11 @@
   int get port => _socket.port;
 
   /**
+   * Returns the address used by this socket.
+   */
+  InternetAddress get address => _socket.address;
+
+  /**
    * Closes the socket. The returned future completes when the socket
    * is fully closed and is no longer bound.
    */
@@ -205,6 +210,11 @@
   int get port => _socket.port;
 
   /**
+   * Returns the address used by this socket.
+   */
+  InternetAddress get address => _socket.address;
+
+  /**
    * Closes the socket. The returned future completes when the socket
    * is fully closed and is no longer bound.
    */
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index 073903d..76abe05 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -162,7 +162,8 @@
   void writeln([object = "" ]) => _sink.writeln(object);
   void writeAll(objects, [sep = ""]) => _sink.writeAll(objects, sep);
   void add(List<int> data) => _sink.add(data);
-  void addError(error) => _sink.addError(error);
+  void addError(error, [StackTrace stackTrace]) =>
+      _sink.addError(error, stackTrace);
   void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
   Future addStream(Stream<List<int>> stream) => _sink.addStream(stream);
   Future close() => _sink.close();
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index 9178757..dafd2bd 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -13,6 +13,8 @@
 class SystemEncoding extends Encoding {
   const SystemEncoding();
 
+  String get name => 'system';
+
   List<int> encode(String input) => encoder.convert(input);
   String decode(List<int> encoded) => decoder.convert(encoded);
 
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index cb6d099..6a62609 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -898,7 +898,8 @@
   String get closeReason => _closeReason;
 
   void add(data) => _sink.add(data);
-  void addError(error) => _sink.addError(error);
+  void addError(error, [StackTrace stackTrace]) =>
+      _sink.addError(error, stackTrace);
   Future addStream(Stream stream) => _sink.addStream(stream);
   Future get done => _sink.done;
 
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 9dbc193..b5b13c8 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -43,7 +43,7 @@
  *       context['console'].callMethod('log', [message]);
  *     }
  *
- * ## Proxying and Automatic Conversion
+ * ## Proxying and automatic conversion
  * 
  * When setting properties on a JsObject or passing arguments to a Javascript
  * method or function, Dart objects are automatically converted or proxied to
@@ -84,7 +84,7 @@
 library dart.js;
 
 import 'dart:html' show Blob, ImageData, Node;
-import 'dart:collection' show HashMap;
+import 'dart:collection' show HashMap, ListMixin;
 import 'dart:indexed_db' show KeyRange;
 import 'dart:typed_data' show TypedData;
 
@@ -92,7 +92,7 @@
 import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject;
 import 'dart:_js_helper' show Primitives, convertDartClosureToJS;
 
-final JsObject context = new JsObject._fromJs(Primitives.computeGlobalThis());
+final JsObject context = _wrapToDart(Primitives.computeGlobalThis());
 
 _convertDartFunction(Function f, {bool captureThis: false}) {
   return JS('',
@@ -108,7 +108,7 @@
   if (captureThis) {
     arguments = [self]..addAll(arguments);
   }
-  var dartArgs = arguments.map(_convertToDart).toList();
+  var dartArgs = new List.from(arguments.map(_convertToDart));
   return _convertToJS(Function.apply(callback, dartArgs));
 }
 
@@ -122,10 +122,9 @@
   // The wrapped JS object.
   final dynamic _jsObject;
 
+  // This shoud only be called from _wrapToDart
   JsObject._fromJs(this._jsObject) {
     assert(_jsObject != null);
-    // Remember this proxy for the JS object
-    _getDartProxy(_jsObject, _DART_OBJECT_PROPERTY_NAME, (o) => this);
   }
 
   /**
@@ -135,7 +134,7 @@
   factory JsObject(JsFunction constructor, [List arguments]) {
     var constr = _convertToJS(constructor);
     if (arguments == null) {
-      return new JsObject._fromJs(JS('', 'new #()', constr));
+      return _wrapToDart(JS('', 'new #()', constr));
     }
     // The following code solves the problem of invoking a JavaScript
     // constructor with an unknown number arguments.
@@ -151,7 +150,8 @@
     // This could return an UnknownJavaScriptObject, or a native
     // object for which there is an interceptor
     var jsObj = JS('JavaScriptObject', 'new #()', factoryFunction);
-    return new JsObject._fromJs(jsObj);
+
+    return _wrapToDart(jsObj);
   }
 
   /**
@@ -170,7 +170,7 @@
       throw new ArgumentError(
         "object cannot be a num, string, bool, or null");
     }
-    return new JsObject._fromJs(_convertToJS(object));
+    return _wrapToDart(_convertToJS(object));
   }
 
   /**
@@ -186,7 +186,7 @@
     if ((object is! Map) && (object is! Iterable)) {
       throw new ArgumentError("object must be a Map or Iterable");
     }
-    return new JsObject._fromJs(_convertDataTree(object));
+    return _wrapToDart(_convertDataTree(object));
   }
 
   static _convertDataTree(data) {
@@ -304,7 +304,7 @@
     }
     return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, method,
         _jsObject,
-        args == null ? null : args.map(_convertToJS).toList()));
+        args == null ? null : new List.from(args.map(_convertToJS))));
   }
 }
 
@@ -331,7 +331,119 @@
   dynamic apply(List args, { thisArg }) =>
       _convertToDart(JS('', '#.apply(#, #)', _jsObject,
           _convertToJS(thisArg),
-          args == null ? null : args.map(_convertToJS).toList()));
+          args == null ? null : new List.from(args.map(_convertToJS))));
+}
+
+/**
+ * A [List] that proxies a JavaScript array.
+ */
+class JsArray<E> extends JsObject with ListMixin<E> {
+
+  /**
+   * Creates a new JavaScript array.
+   */
+  JsArray() : super._fromJs([]);
+
+  /**
+   * Creates a new JavaScript array and initializes it to the contents of
+   * [other].
+   */
+  JsArray.from(Iterable<E> other)
+      : super._fromJs([]..addAll(other.map(_convertToJS)));
+
+  JsArray._fromJs(jsObject) : super._fromJs(jsObject);
+
+  _checkIndex(int index) {
+    if (index is int && (index < 0 || index >= length)) {
+      throw new RangeError.range(index, 0, length);
+    }
+  }
+
+  _checkInsertIndex(int index) {
+    if (index is int && (index < 0 || index >= length + 1)) {
+      throw new RangeError.range(index, 0, length);
+    }
+  }
+
+  _checkRange(int start, int end) {
+    if (start < 0 || start > this.length) {
+      throw new RangeError.range(start, 0, this.length);
+    }
+    if (end < start || end > this.length) {
+      throw new RangeError.range(end, start, this.length);
+    }
+  }
+
+  // Methods required by ListMixin
+
+  E operator [](index) {
+    // TODO(justinfagnani): fix the semantics for non-ints
+    // dartbug.com/14605
+    if (index is num && index == index.toInt()) {
+      _checkIndex(index);
+    }
+    return super[index];
+  }
+
+  void operator []=(index, E value) {
+    // TODO(justinfagnani): fix the semantics for non-ints
+    // dartbug.com/14605
+    if (index is num && index == index.toInt()) {
+      _checkIndex(index);
+    }
+    super[index] = value;
+  }
+
+  int get length => super['length'];
+
+  void set length(int length) { super['length'] = length; }
+
+
+  // Methods overriden for better performance
+
+  void add(E value) {
+    callMethod('push', [value]);
+  }
+
+  void addAll(Iterable<E> iterable) {
+    var list = (JS('bool', '# instanceof Array', iterable)) 
+        ? iterable
+        : new List.from(iterable);
+    callMethod('push', list);
+  }
+
+  void insert(int index, E element) {
+    _checkInsertIndex(index);
+    callMethod('splice', [index, 0, element]);
+  }
+
+  E removeAt(int index) {
+    _checkIndex(index);
+    return callMethod('splice', [index, 1])[0];
+  }
+
+  E removeLast() {
+    if (length == 0) throw new RangeError(-1);
+    return callMethod('pop');
+  }
+
+  void removeRange(int start, int end) {
+    _checkRange(start, end);
+    callMethod('splice', [start, end - start]);
+  }
+
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+    _checkRange(start, end);
+    int length = end - start;
+    if (length == 0) return;
+    if (skipCount < 0) throw new ArgumentError(skipCount);
+    var args = [start, length]..addAll(iterable.skip(skipCount).take(length));
+    callMethod('splice', args);
+  }
+
+  void sort([int compare(E a, E b)]) {
+    callMethod('sort', [compare]);
+  }
 }
 
 // property added to a Dart object referencing its JS-side DartObject proxy
@@ -359,8 +471,8 @@
   if (o == null) {
     return null;
   } else if (o is String || o is num || o is bool
-    || o is Blob || o is KeyRange || o is ImageData || o is Node 
-    || o is TypedData) {
+      || o is Blob || o is KeyRange || o is ImageData || o is Node
+      || o is TypedData) {
     return o;
   } else if (o is DateTime) {
     return Primitives.lazyAsJsDate(o);
@@ -391,23 +503,33 @@
 // converts a Dart object to a reference to a native JS object
 // which might be a DartObject JS->Dart proxy
 Object _convertToDart(o) {
+  var isArray = JS('bool', '# instanceof Array', o);
   if (JS('bool', '# == null', o) ||
       JS('bool', 'typeof # == "string"', o) ||
       JS('bool', 'typeof # == "number"', o) ||
       JS('bool', 'typeof # == "boolean"', o)) {
     return o;
   } else if (o is Blob || o is KeyRange || o is ImageData || o is Node
-    || o is TypedData) {
+      || o is TypedData) {
     return JS('Blob|KeyRange|ImageData|Node|TypedData', '#', o);
   } else if (JS('bool', '# instanceof Date', o)) {
     var ms = JS('num', '#.getMilliseconds()', o);
     return new DateTime.fromMillisecondsSinceEpoch(ms);
-  } else if (JS('bool', 'typeof # == "function"', o)) {
-    return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME,
-        (o) => new JsFunction._fromJs(o));
   } else if (JS('bool', '#.constructor === DartObject', o)) {
     return JS('', '#.o', o);
   } else {
+    return _wrapToDart(o);
+  }
+}
+
+JsObject _wrapToDart(o) {
+  if (JS('bool', 'typeof # == "function"', o)) {
+    return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME,
+        (o) => new JsFunction._fromJs(o));
+  } else if (JS('bool', '# instanceof Array', o)) {
+    return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME,
+        (o) => new JsArray._fromJs(o));
+  } else {
     return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME,
         (o) => new JsObject._fromJs(o));
   }
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index af3df6c..03df4a4 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -43,7 +43,7 @@
  *       context['console'].callMethod('log', [message]);
  *     }
  *
- * ## Proxying and Automatic Conversion
+ * ## Proxying and automatic conversion
  * 
  * When setting properties on a JsObject or passing arguments to a Javascript
  * method or function, Dart objects are automatically converted or proxied to
@@ -83,6 +83,7 @@
  */
 library dart.js;
 
+import 'dart:collection' show ListMixin;
 import 'dart:nativewrappers';
 
 JsObject _cachedContext;
@@ -260,6 +261,101 @@
 }
 
 /**
+ * A [List] proxying a JavaScript Array.
+ */
+class JsArray<E> extends JsObject with ListMixin<E> {
+
+  factory JsArray() => _newJsArray();
+
+  static JsArray _newJsArray() native "JsArray_newJsArray";
+
+  factory JsArray.from(Iterable<E> other) => _newJsArrayFromSafeList(new List.from(other));
+
+  static JsArray _newJsArrayFromSafeList(List list) native "JsArray_newJsArrayFromSafeList";
+
+  _checkIndex(int index, {bool insert: false}) {
+    int length = insert ? this.length + 1 : this.length;
+    if (index is int && (index < 0 || index >= length)) {
+      throw new RangeError.range(index, 0, length);
+    }
+  }
+
+  _checkRange(int start, int end) {
+    int cachedLength = this.length;
+    if (start < 0 || start > cachedLength) {
+      throw new RangeError.range(start, 0, cachedLength);
+    }
+    if (end < start || end > cachedLength) {
+      throw new RangeError.range(end, start, cachedLength);
+    }
+  }
+
+  // Methods required by ListMixin
+
+  E operator [](index) {
+    if (index is int) {
+      _checkIndex(index);
+    }
+    return super[index];
+  }
+
+  void operator []=(index, E value) {
+    if(index is int) {
+      _checkIndex(index);
+    }
+    super[index] = value;
+  }
+
+  int get length native "JsArray_length";
+
+  void set length(int length) { super['length'] = length; }
+
+  // Methods overriden for better performance
+
+  void add(E value) {
+    callMethod('push', [value]);
+  }
+
+  void addAll(Iterable<E> iterable) {
+    // TODO(jacobr): this can be optimized slightly.
+    callMethod('push', new List.from(iterable));
+  }
+
+  void insert(int index, E element) {
+    _checkIndex(index, insert:true);
+    callMethod('splice', [index, 0, element]);
+  }
+
+  E removeAt(int index) {
+    _checkIndex(index);
+    return callMethod('splice', [index, 1])[0];
+  }
+
+  E removeLast() {
+    if (length == 0) throw new RangeError(-1);
+    return callMethod('pop');
+  }
+
+  void removeRange(int start, int end) {
+    _checkRange(start, end);
+    callMethod('splice', [start, end - start]);
+  }
+
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+    _checkRange(start, end);
+    int length = end - start;
+    if (length == 0) return;
+    if (skipCount < 0) throw new ArgumentError(skipCount);
+    var args = [start, length]..addAll(iterable.skip(skipCount).take(length));
+    callMethod('splice', args);
+  }
+
+  void sort([int compare(E a, E b)]) {
+    callMethod('sort', [compare]);
+  }
+}
+
+/**
  * Placeholder object for cases where we need to determine exactly how many
  * args were passed to a function.
  */
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 109f832..678348d 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -125,12 +125,6 @@
 external MirrorSystem currentMirrorSystem();
 
 /**
- * Creates a [MirrorSystem] for the isolate which is listening on
- * the [SendPort].
- */
-external Future<MirrorSystem> mirrorSystemOf(SendPort port);
-
-/**
  * Reflects an instance.
  * Returns an [InstanceMirror] reflecting [reflectee].
  * If [reflectee] is a function or an instance of a class
@@ -177,12 +171,7 @@
  *
  * Every [Mirror] originates from some [MirrorSystem].
  */
-abstract class Mirror {
-  /**
-   * The [MirrorSystem] that contains this mirror.
-   */
-  MirrorSystem get mirrors;
-}
+abstract class Mirror {}
 
 /**
  * An [IsolateMirror] reflects an isolate.
@@ -419,106 +408,6 @@
    */
   /* TODO(turnidge): Handle ambiguous names.*/
   InstanceMirror setField(Symbol fieldName, Object value);
-
-  /**
-   * Invokes the named function and returns a mirror on the result.
-   * The arguments must be instances of [InstanceMirror], or of
-   * a type that is serializable across isolates (currently [num],
-   * [String], or [bool]).
-   *
-   * Let *o* be the object reflected by this mirror, let
-   * *f* be the simple name of the member denoted by [memberName],
-   * let *a1, ..., an* be the elements of [positionalArguments]
-   * let *k1, ..., km* be the identifiers denoted by the elements of
-   * [namedArguments.keys]
-   * and let *v1, ..., vm* be the elements of [namedArguments.values].
-   * For each *ai*, if *ai* is an instance of [InstanceMirror], let *pi*
-   * be the object reflected by *ai*; otherwise let *pi = ai,  i in 1 ...n*.
-   * Likewise, for each *vj*, if *vj* is an instance of [InstanceMirror], let *qj*
-   * be the object reflected by *vj*; otherwise let *qj = vj,  j in 1 ...m*.
-   * If any of the *pi, qj* is not an instance of [InstanceMirror] and
-   * is not serializable across isolates, an exception is thrown.
-   * Then this method will perform the method invocation
-   *  *o.f(p1, ..., pn, k1: q1, ..., km: qm)*
-   * in a scope that has access to the private members
-   * of *o* (if *o* is a class or library) or the private members of the
-   * class of *o*(otherwise).
-   * The method returns a future *k*.
-   * If the invocation returns a result *r*, *k* will be completed
-   * with the result of calling [reflect](*r*).
-   * If the invocation throws an exception *e* (that it does not catch)
-   * then *k* is completed with a [MirrorError] wrapping *e*.
-   */
-  /*
-   * TODO(turnidge): Handle ambiguous names.
-   * TODO(turnidge): Handle optional & named arguments.
-   */
-  Future<InstanceMirror> invokeAsync(Symbol memberName,
-                                     List positionalArguments,
-                                     [Map<Symbol, dynamic> namedArguments]);
-
-  /**
-   * Invokes a getter and returns a mirror on the result. The getter
-   * can be the implicit getter for a field or a user-defined getter
-   * method.
-   *
-   * Let *o* be the object reflected by this mirror, let
-   * *f* be the simple name of the getter denoted by [fieldName],
-   * Then this method will perform the getter invocation
-   *  *o.f*
-   * in a scope that has access to the private members
-   * of *o* (if *o* is a class or library) or the private members of the
-   * class of *o*(otherwise).
-   *
-   * If this mirror is an [InstanceMirror], and [fieldName] denotes an instance
-   * method on its reflectee, the result of the invocation is an instance
-   * mirror on a closure corresponding to that method.
-   *
-   * If this mirror is a [LibraryMirror], and [fieldName] denotes a top-level
-   * method in the corresponding library, the result of the invocation is an
-   * instance mirror on a closure corresponding to that method.
-   *
-   * If this mirror is a [ClassMirror], and [fieldName] denotes a static method
-   * in the corresponding class, the result of the invocation is an instance
-   * mirror on a closure corresponding to that method.
-   *
-   * The method returns a future *k*.
-   * If the invocation returns a result *r*, *k* will be completed
-   * with the result of calling [reflect](*r*).
-   * If the invocation throws an exception *e* (that it does not catch)
-   * then *k* is completed with a [MirrorError] wrapping *e*.
-   */
-  /* TODO(turnidge): Handle ambiguous names.*/
-  Future<InstanceMirror> getFieldAsync(Symbol fieldName);
-
-  /**
-   * Invokes a setter and returns a mirror on the result. The setter
-   * may be either the implicit setter for a non-final field or a
-   * user-defined setter method.
-   * The second argument must be an instance of [InstanceMirror], or of
-   * a type that is serializable across isolates (currently [num],
-   * [String], or [bool]).
-   *
-   * Let *o* be the object reflected by this mirror, let
-   * *f* be the simple name of the getter denoted by [fieldName],
-   * and let a be the object bound to [value]. If *a* is an instance of
-   * [InstanceMirror]  let *p* be the object
-   * reflected by *a*, otherwise let *p =a*.
-   * If *p* is not an instance of [InstanceMirror], *p* must be
-   * serializable across isolates or an exception is thrown.
-   * Then this method will perform the setter invocation
-   *  *o.f = a*
-   * in a scope that has access to the private members
-   * of *o* (if *o* is a class or library) or the private members of the
-   * class of *o*(otherwise).
-   * The method returns a future *k*.
-   * If the invocation returns a result *r*, *k* will be completed
-   * with the result of calling [reflect](*r*).
-   * If the invocation throws an exception *e* (that it does not catch)
-   * then *k* is completed with a [MirrorError} wrapping *e*.
-   */
-  /* TODO(turnidge): Handle ambiguous names.*/
-  Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value);
 }
 
 /**
@@ -616,36 +505,6 @@
                        [Map<Symbol, dynamic> namedArguments]);
 
   /**
-   * Executes the closure and returns a mirror on the result.
-   *
-   * Let *f* be the closure reflected by this mirror,
-   * let *a1, ..., an* be the elements of [positionalArguments]
-   * let *k1, ..., km* be the identifiers denoted by the elements of
-   * [namedArguments.keys]
-   * and let *v1, ..., vm* be the elements of [namedArguments.values].
-   * For each *ai*, if *ai* is an instance of [InstanceMirror], let *pi*
-   * be the object reflected by *ai*; otherwise let *pi = ai,  i in 1 ...n*.
-   * Likewise, for each *vj*, if *vj* is an instance of [InstanceMirror], let
-   * *qj*
-   * be the object reflected by *vj*; otherwise let *qj = vj,  j in 1 ...m*.
-   * If any of the *pi, qj* is not an instance of [InstanceMirror] and
-   * is not serializable across isolates, an exception is thrown.
-   * Then this method will perform the function invocation
-   *  *f(p1, ..., pn, k1: q1, ..., km: qm)*
-   * The method returns a future *k*.
-   * If the invocation returns a result *r*, *k* will be completed
-   * with the result of calling [reflect](*r*).
-   * If the invocation throws an exception *e* (that it does not catch)
-   * then *k* is completed with a [MirrorError] wrapping *e*.
-   *
-   * The arguments must be instances of [InstanceMirror], or of
-   * a type that is serializable across isolates (currently [num],
-   * [String], or [bool]).
-   */
-  Future<InstanceMirror> applyAsync(List positionalArguments,
-                                    [Map<Symbol, dynamic> namedArguments]);
-
-  /**
    * Looks up the value of a name in the scope of the closure. The
    * result is a mirror on that value.
    *
@@ -921,45 +780,6 @@
                              List positionalArguments,
                              [Map<Symbol,dynamic> namedArguments]);
 
- /**
-   * Invokes the named function and returns a mirror on the result.
-   * The arguments must be instances of [InstanceMirror], or of
-   * a type that is serializable across isolates (currently [num],
-   * [String], or [bool]).
-   *
-   * Let *c* be the class reflected by this mirror,
-   * let *a1, ..., an* be the elements of [positionalArguments]
-   * let *k1, ..., km* be the identifiers denoted by the elements of
-   * [namedArguments.keys]
-   * and let *v1, ..., vm* be the elements of [namedArguments.values].
-   * For each *ai*, if *ai* is an instance of [InstanceMirror], let *pi*
-   * be the object reflected by *ai*; otherwise let *pi = ai,  i in 1 ...n*.
-   * Likewise, for each *vj*, if *vj* is an instance of [InstanceMirror], let
-   * *qj*
-   * be the object reflected by *vj*; otherwise let *qj = vj,  j in 1 ...m*.
-   * If any of the *pi, qj* is not an instance of [InstanceMirror] and
-   * is not serializable across isolates, an exception is thrown.
-   * If [constructorName] was created from the empty string
-   * Then this method will execute the instance creation expression
-   * *new c(a1, ..., an, k1: v1, ..., km: vm)*
-   * in a scope that has access to the private members
-   * of *c*. Otherwise, let
-   * *f* be the simple name of the constructor denoted by [constructorName]
-   * Then this method will execute the instance creation expression
-   *  *new c.f(a1, ..., an, k1: v1, ..., km: vm)*
-   * in a scope that has access to the private members
-   * of *c*.
-   * In either case:
-   * The method returns a future *k*.
-   * If the invocation returns a result *r*, *k* will be completed
-   * with the result of calling [reflect](*r*).
-   * If the invocation throws an exception *e* (that it does not catch)
-   * then *k* is completed with a [MirrorError] wrapping *e*.
-*/
-  Future<InstanceMirror> newInstanceAsync(Symbol constructorName,
-                                          List positionalArguments,
-                                          [Map<Symbol, dynamic> namedArguments]);
-
   /**
    * Returns [:true:] if this mirror is equal to [other].
    * Otherwise returns [:false:].
@@ -1029,7 +849,7 @@
    *
    * For instance [:void f(int):] is the referent for [:typedef void f(int):].
    */
-  TypeMirror get referent;
+  FunctionTypeMirror get referent;
 }
 
 /**
diff --git a/sdk/lib/platform/platform.dart b/sdk/lib/platform/platform.dart
deleted file mode 100644
index ee8658e..0000000
--- a/sdk/lib/platform/platform.dart
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2013, 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.
-
-/**
- * Runtime information about the current platform.
- */
-library dart.platform;
-
-/**
- * The number of processors of the platform.
- *
- * Returns null if no information is available.
- *
- * Supported on the standalone Dart executable.
- */
-external int get numberOfProcessors;
-
-/**
- * The path separator used on the platform to separate
- * components in file paths.
- *
- * Returns null if the path separator is unknown or not valid.
- *
- * Supported on the standalone Dart executable and on dart2js.
- */
-external String get pathSeparator;
-
-/**
- * A string (`linux`, `macos`, `windows` or `android`)
- * representing the operating system.
- *
- * Returns null if the operating system could not be determined.
- */
-external String get operatingSystem;
-
-/**
- * The local hostname for the system.
- *
- * Returns null if the local hostname is not available.
- *
- * Supported on the standalone Dart executable.
- */
-external String get localHostname;
-
-/**
- * The version of the current Dart runtime.
- *
- * Returns null if not running a Dart runtime.
- *
- * Supported on the standalone Dart executable.
- */
-external String get version;
-
-/**
- * The environment for this instance of the platform.
- *
- * If environment variables are not supported on this platform, or not
- * available, null is returned.
- *
- * Environment variables on Windows are case-insensitive. The map
- * returned on Windows is therefore case-insensitive and converts
- * all keys and key arguments to its methods to upper case.
- * On other platforms the returned map is
- * a standard case-sensitive map.
- *
- * Supported on the standalone Dart executable.
- */
-external Map<String, String> get environment;
-
-/**
- * The path of the executable this Dart isolate is running on.
- *
- * Returns null if the execution environment does not make the information
- * available.
- *
- * Supported on the standalone Dart executable.
- */
-external String get executable;
-
-/**
- * The URI of the script being run in this isolate.
- *
- * If the URI is relative it is relative to the file URI of
- * the working directory of the VM when it was started.
- *
- * Returns null if the executable environment does not make the information
- * available.
- *
- * Supported on the standalone Dart executable.
- */
-external Uri get script;
-
-/**
- * The flags passed to the executable used to run the script in this
- * isolate. These are the command-line flags between the executable name
- * and the script name.
- *
- * Returns the empty list if [executableArguments] is not supported.
- *
- * Supported on the standalone Dart executable.
- */
-external List<String> get executableArguments;
-
-/**
- * The value of the --package-root flag passed to the executable
- * used to run the script in this isolate.  This is the directory in which
- * Dart packages are looked up.
- *
- * If there is no --package-root flag, then the empty string is returned.
- *
- * Returns null if the information is not available on this platform.
- *
- * Supported on the standalone Dart executable.
- */
-external String get packageRoot;
diff --git a/sdk/lib/platform/platform_sources.gypi b/sdk/lib/platform/platform_sources.gypi
deleted file mode 100644
index 6bca2b3..0000000
--- a/sdk/lib/platform/platform_sources.gypi
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2013, 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.
-
-# This file contains all sources for the dart:platform library.
-{
-  'sources': [
-    'platform.dart',
-    # The above file needs to be first as it lists the parts below.
-  ],
-}
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index c837f1f..1d51c92 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -3041,7 +3041,7 @@
 @DocsEditable()
 @DomName('SVGLengthList')
 @Unstable()
-class LengthList extends Interceptor with ListMixin<Length>, ImmutableListMixin<Length> implements List native "SVGLengthList" {
+class LengthList extends Interceptor with ListMixin<Length>, ImmutableListMixin<Length> implements List<Length> native "SVGLengthList" {
   // To suppress missing implicit constructor warnings.
   factory LengthList._() { throw new UnsupportedError("Not supported"); }
 
@@ -3495,7 +3495,7 @@
 @DocsEditable()
 @DomName('SVGNumberList')
 @Unstable()
-class NumberList extends Interceptor with ListMixin<Number>, ImmutableListMixin<Number> implements List native "SVGNumberList" {
+class NumberList extends Interceptor with ListMixin<Number>, ImmutableListMixin<Number> implements List<Number> native "SVGNumberList" {
   // To suppress missing implicit constructor warnings.
   factory NumberList._() { throw new UnsupportedError("Not supported"); }
 
@@ -4260,7 +4260,7 @@
 @DocsEditable()
 @DomName('SVGPathSegList')
 @Unstable()
-class PathSegList extends Interceptor with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List native "SVGPathSegList" {
+class PathSegList extends Interceptor with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List<PathSeg> native "SVGPathSegList" {
   // To suppress missing implicit constructor warnings.
   factory PathSegList._() { throw new UnsupportedError("Not supported"); }
 
@@ -4951,7 +4951,7 @@
 @DocsEditable()
 @DomName('SVGStringList')
 @Unstable()
-class StringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements List native "SVGStringList" {
+class StringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements List<String> native "SVGStringList" {
   // To suppress missing implicit constructor warnings.
   factory StringList._() { throw new UnsupportedError("Not supported"); }
 
@@ -5906,7 +5906,7 @@
 @DocsEditable()
 @DomName('SVGTransformList')
 @Unstable()
-class TransformList extends Interceptor with ListMixin<Transform>, ImmutableListMixin<Transform> implements List native "SVGTransformList" {
+class TransformList extends Interceptor with ListMixin<Transform>, ImmutableListMixin<Transform> implements List<Transform> native "SVGTransformList" {
   // To suppress missing implicit constructor warnings.
   factory TransformList._() { throw new UnsupportedError("Not supported"); }
 
@@ -6278,7 +6278,7 @@
 @DocsEditable()
 @DomName('SVGElementInstanceList')
 @Unstable()
-class _ElementInstanceList extends Interceptor with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List native "SVGElementInstanceList" {
+class _ElementInstanceList extends Interceptor with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List<ElementInstance> native "SVGElementInstanceList" {
   // To suppress missing implicit constructor warnings.
   factory _ElementInstanceList._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index f25ee0a..7e348f0 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -3217,7 +3217,7 @@
 @DocsEditable()
 @DomName('SVGLengthList')
 @Unstable()
-class LengthList extends NativeFieldWrapperClass2 with ListMixin<Length>, ImmutableListMixin<Length> implements List {
+class LengthList extends NativeFieldWrapperClass2 with ListMixin<Length>, ImmutableListMixin<Length> implements List<Length> {
   // To suppress missing implicit constructor warnings.
   factory LengthList._() { throw new UnsupportedError("Not supported"); }
 
@@ -3713,7 +3713,7 @@
 @DocsEditable()
 @DomName('SVGNumberList')
 @Unstable()
-class NumberList extends NativeFieldWrapperClass2 with ListMixin<Number>, ImmutableListMixin<Number> implements List {
+class NumberList extends NativeFieldWrapperClass2 with ListMixin<Number>, ImmutableListMixin<Number> implements List<Number> {
   // To suppress missing implicit constructor warnings.
   factory NumberList._() { throw new UnsupportedError("Not supported"); }
 
@@ -4733,7 +4733,7 @@
 @DocsEditable()
 @DomName('SVGPathSegList')
 @Unstable()
-class PathSegList extends NativeFieldWrapperClass2 with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List {
+class PathSegList extends NativeFieldWrapperClass2 with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List<PathSeg> {
   // To suppress missing implicit constructor warnings.
   factory PathSegList._() { throw new UnsupportedError("Not supported"); }
 
@@ -5505,7 +5505,7 @@
 @DocsEditable()
 @DomName('SVGStringList')
 @Unstable()
-class StringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List {
+class StringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List<String> {
   // To suppress missing implicit constructor warnings.
   factory StringList._() { throw new UnsupportedError("Not supported"); }
 
@@ -6529,7 +6529,7 @@
 @DocsEditable()
 @DomName('SVGTransformList')
 @Unstable()
-class TransformList extends NativeFieldWrapperClass2 with ListMixin<Transform>, ImmutableListMixin<Transform> implements List {
+class TransformList extends NativeFieldWrapperClass2 with ListMixin<Transform>, ImmutableListMixin<Transform> implements List<Transform> {
   // To suppress missing implicit constructor warnings.
   factory TransformList._() { throw new UnsupportedError("Not supported"); }
 
@@ -6927,7 +6927,7 @@
 @DocsEditable()
 @DomName('SVGElementInstanceList')
 @Unstable()
-class _ElementInstanceList extends NativeFieldWrapperClass2 with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List {
+class _ElementInstanceList extends NativeFieldWrapperClass2 with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List<ElementInstance> {
   // To suppress missing implicit constructor warnings.
   factory _ElementInstanceList._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
index f43139e..668bdef 100644
--- a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -203,7 +203,7 @@
 @DomName('SQLResultSetRowList')
 // http://www.w3.org/TR/webdatabase/#sqlresultsetrowlist
 @Experimental() // deprecated
-class SqlResultSetRowList extends Interceptor with ListMixin<Map>, ImmutableListMixin<Map> implements List native "SQLResultSetRowList" {
+class SqlResultSetRowList extends Interceptor with ListMixin<Map>, ImmutableListMixin<Map> implements List<Map> native "SQLResultSetRowList" {
   // To suppress missing implicit constructor warnings.
   factory SqlResultSetRowList._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/web_sql/dartium/web_sql_dartium.dart b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
index 81f384d..62f2497 100644
--- a/sdk/lib/web_sql/dartium/web_sql_dartium.dart
+++ b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
@@ -212,7 +212,7 @@
 @DomName('SQLResultSetRowList')
 // http://www.w3.org/TR/webdatabase/#sqlresultsetrowlist
 @Experimental() // deprecated
-class SqlResultSetRowList extends NativeFieldWrapperClass2 with ListMixin<Map>, ImmutableListMixin<Map> implements List {
+class SqlResultSetRowList extends NativeFieldWrapperClass2 with ListMixin<Map>, ImmutableListMixin<Map> implements List<Map> {
   // To suppress missing implicit constructor warnings.
   factory SqlResultSetRowList._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 426e16e..267d3d0 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -15,6 +15,22 @@
 # TBF: malformed or malbounded type in "conts" is static warning
 Language/12_Expressions/12_Instance_Creation_A01_t08: Fail
 
+# TBF: it seems that "12.15.3 Unqualied Invocation" was changed, so it may be not an error anymore to call unknown function from top-level
+Language/13_Statements/04_Local_Function_Declaration_A04_t02: Fail # co19-roll r641: Please triage this failure
+
+# TBF: when we override "foo([x = 0]) {}" with "foo([x]) {}" we should report warning - different default value
+Language/07_Classes/1_Instance_Methods_A04_t02: MissingStaticWarning
+Language/07_Classes/4_Abstract_Instance_Members_A07_t04: MissingStaticWarning
+
+# TBF: It is a static warning if a class C declares an instance method named n and has a setter named n=.
+Language/07_Classes/1_Instance_Methods_A07_t01: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A07_t02: MissingStaticWarning
+
+# TBF: Static members should not be accessible via subclasses.
+Language/07_Classes/7_Static_Methods_A01_t03: MissingStaticWarning
+Language/07_Classes/9_Superclasses/1_Inheritance_and_Overriding_A01_t05: MissingStaticWarning
+Language/08_Interfaces/5_Superinterfaces/1_Inheritance_and_Overriding_A01_t02: MissingStaticWarning
+
 
 
 # co19 issue #442, undefined name "Expect"
@@ -227,15 +243,53 @@
 
 Language/13_Statements/09_Switch_A02_t04: Fail  # Issue 629
 
-Language/12_Expressions/05_Strings_A20_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/collection/DoubleLinkedQueue/DoubleLinkedQueue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/collection/ListQueue/ListQueue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/collection/Queue/Queue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/core/Iterable/Iterable.generate_A01_t01: Fail # co19-roll r623: Please triage this failure
 
-Language/13_Statements/04_Local_Function_Declaration_A04_t02: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/HashMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/LinkedHashMap/LinkedHashMap_class_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/LinkedHashMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/SplayTreeMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/core/Map/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
+
+
+# co19 issue 642, The argument type 'int' cannot be assigned to the parameter type 'Iterable'
+LibTest/collection/DoubleLinkedQueue/DoubleLinkedQueue_class_A01_t01: Fail, OK
+LibTest/collection/ListQueue/ListQueue_class_A01_t01: Fail, OK
+LibTest/collection/Queue/Queue_class_A01_t01: Fail, OK
+
+# co19 issue 643, A value of type 'Iterable' cannot be assigned to a variable of type 'Iterator'
+LibTest/core/Iterable/Iterable.generate_A01_t01: Fail, OK
+
+# co19 issue 644, The argument type 'int' cannot be assigned to the parameter type '(String, Object) -> void'
+LibTest/collection/HashMap/allTests_A01_t01: Fail, OK
+LibTest/collection/LinkedHashMap/LinkedHashMap_class_A01_t01: Fail, OK
+LibTest/collection/LinkedHashMap/allTests_A01_t01: Fail, OK
+LibTest/collection/SplayTreeMap/allTests_A01_t01: Fail, OK
+LibTest/core/Map/allTests_A01_t01: Fail, OK
+
+# co19 issue 645, "15.7 Type Void". Likewise, passing the result of a void method as a parameter or assigning it to a variable will cause a warning unless the variable/formal parameter has type dynamic.
+Language/06_Functions/06_Functions_A04_t01: Fail, OK
+
+# co19 issue 646, I don't see where Spec requires any warning for boolean conversion
+Language/12_Expressions/04_Booleans/1_Boolean_Conversion_A01_t02: MissingStaticWarning
+
+Language/12_Expressions/15_Method_Invocation/2_Cascaded_Invocation_A01_t19: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t02: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: MissingStaticWarning
+Language/12_Expressions/19_Conditional_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t10: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t11: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t12: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t13: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t15: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A02_t02: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t01: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t02: MissingStaticWarning
+Language/12_Expressions/21_Bitwise_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/23_Relational_Expressions_A01_t23: MissingStaticWarning
+Language/12_Expressions/24_Shift_A01_t14: MissingStaticWarning
+Language/12_Expressions/25_Additive_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/26_Multiplicative_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/27_Unary_Expressions_A01_t21: MissingStaticWarning
+Language/12_Expressions/29_Assignable_Expressions_A01_t09: MissingStaticWarning
+Language/12_Expressions/30_Identifier_Reference_A07_t01: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t07: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t08: MissingStaticWarning
+Language/13_Statements/09_Switch_A10_t03: MissingStaticWarning
+Language/13_Statements/15_Assert_A04_t04: MissingStaticWarning
+LibTest/collection/IterableMixin/IterableMixin_class_A01_t01: MissingStaticWarning
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 4a4cb2a..db7d1f1 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -146,6 +146,80 @@
 LibTest/async/StreamEventTransformer/handleDone_A01_t01: Fail
 LibTest/async/StreamEventTransformer/handleError_A01_t01: Fail
 
+# co19 issue 639.
+Language/12_Expressions/12_Spawning_an_Isolate_A01_t01: Fail
+LibTest/isolate/IsolateSink/add_A01_t01: Fail
+LibTest/isolate/IsolateSink/add_A01_t02: Fail
+LibTest/isolate/IsolateSink/add_A02_t01: Fail
+LibTest/isolate/IsolateSink/close_A01_t01: Fail
+LibTest/isolate/IsolateSink/close_A01_t02: Fail
+LibTest/isolate/IsolateSink/close_A01_t03: Fail
+LibTest/isolate/IsolateSink/close_A01_t04: Fail
+LibTest/isolate/IsolateSink/operator_equality_A01_t01: Fail
+LibTest/isolate/IsolateStream/any_A01_t01: Fail
+LibTest/isolate/IsolateStream/asBroadcastStream_A01_t01: Fail
+LibTest/isolate/IsolateStream/contains_A01_t01: Fail
+LibTest/isolate/IsolateStream/first_A01_t01: Fail
+LibTest/isolate/IsolateStream/first_A02_t01: Fail
+LibTest/isolate/IsolateStream/first_A02_t02: Fail
+LibTest/isolate/IsolateStream/isBroadcast_A01_t01: Fail
+LibTest/isolate/IsolateStream/isBroadcast_A01_t02: Fail
+LibTest/isolate/IsolateStream/isEmpty_A01_t01: Fail
+LibTest/isolate/IsolateStream/last_A01_t01: Fail
+LibTest/isolate/IsolateStream/last_A02_t01: Fail
+LibTest/isolate/IsolateStream/length_A01_t01: Fail
+LibTest/isolate/IsolateStream/single_A01_t01: Fail
+LibTest/isolate/IsolateStream/single_A02_t01: Fail
+LibTest/isolate/ReceivePort/close_A01_t01: Fail
+LibTest/isolate/ReceivePort/close_A02_t01: Fail
+LibTest/isolate/ReceivePort/receive_A01_t01: Fail
+LibTest/isolate/ReceivePort/receive_A01_t03: Fail
+LibTest/isolate/ReceivePort/toSendPort_A01_t01: Fail
+LibTest/isolate/ReceivePort/toSendPort_A01_t03: Fail
+LibTest/isolate/SendPort/call_A01_t01: Fail
+LibTest/isolate/SendPort/hashCode_A01_t01: Fail
+LibTest/isolate/SendPort/operator_equality_A01_t01: Fail
+LibTest/isolate/SendPort/send_A01_t01: Pass
+LibTest/isolate/SendPort/send_A02_t01: Fail
+LibTest/isolate/SendPort/send_A02_t04: Fail
+LibTest/isolate/SendPort/send_A02_t05: Fail
+LibTest/isolate/SendPort/send_A02_t06: Fail
+LibTest/isolate/SendPort/send_A03_t01: Fail
+LibTest/isolate/SendPort/send_A03_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t01: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t03: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t04: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t05: Fail
+LibTest/isolate/isolate_api/spawnFunction_A02_t01: Fail
+LibTest/isolate/isolate_api/spawnFunction_A03_t01: Fail
+LibTest/isolate/isolate_api/spawnFunction_A04_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A04_t03: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t01: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t02: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t03: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t04: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t05: Fail
+LibTest/isolate/isolate_api/streamSpawnFunction_A01_t01: Fail
+LibTest/isolate/isolate_api/stream_A01_t01: Fail
+LibTest/isolate/isolate_api/port_A01_t01: Fail
+LibTest/isolate/IsolateSink/addError_A01_t01: Fail
+LibTest/isolate/IsolateSink/addError_A01_t02: Fail
+LibTest/isolate/IsolateStream/any_A02_t01: Fail
+LibTest/isolate/IsolateStream/contains_A02_t01: Fail
+LibTest/isolate/ReceivePort/receive_A01_t02: Fail
+LibTest/isolate/ReceivePort/toSendPort_A01_t02: Fail
+LibTest/isolate/SendPort/send_A01_t01: Fail
+LibTest/isolate/SendPort/send_A02_t02: Fail
+LibTest/isolate/SendPort/send_A02_t03: Fail
+LibTest/isolate/isolate_api/spawnFunction_A02_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A04_t01: Fail
+LibTest/isolate/isolate_api/spawnUri_A02_t01: Fail
+LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail
+LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail
+LibTest/isolate/isolate_api/streamSpawnFunction_A02_t01: Fail
+LibTest/isolate/isolate_api/streamSpawnFunction_A02_t02: Fail
+
 #co19 issue 631
 Language/12_Expressions/30_Identifier_Reference_A02_t01: Fail
 Language/13_Statements/03_Variable_Declaration_A01_t09: Fail
@@ -165,3 +239,45 @@
 LibTest/collection/LinkedHashMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
 LibTest/collection/SplayTreeMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
 LibTest/core/Map/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
+
+Language/06_Functions/06_Functions_A04_t01: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A04_t02: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A07_t01: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A07_t02: MissingStaticWarning
+Language/07_Classes/4_Abstract_Instance_Members_A07_t04: MissingStaticWarning
+Language/07_Classes/7_Static_Methods_A01_t03: MissingStaticWarning
+Language/07_Classes/9_Superclasses/1_Inheritance_and_Overriding_A01_t05: MissingStaticWarning
+Language/08_Interfaces/5_Superinterfaces/1_Inheritance_and_Overriding_A01_t02: MissingStaticWarning
+Language/12_Expressions/04_Booleans/1_Boolean_Conversion_A01_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A05_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A06_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A06_t06: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A07_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A08_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A04_t02: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/2_Cascaded_Invocation_A01_t19: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t02: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: MissingStaticWarning
+Language/12_Expressions/19_Conditional_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t10: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t11: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t12: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t13: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t15: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A02_t02: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t01: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t02: MissingStaticWarning
+Language/12_Expressions/21_Bitwise_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/23_Relational_Expressions_A01_t23: MissingStaticWarning
+Language/12_Expressions/24_Shift_A01_t14: MissingStaticWarning
+Language/12_Expressions/25_Additive_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/26_Multiplicative_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/27_Unary_Expressions_A01_t21: MissingStaticWarning
+Language/12_Expressions/29_Assignable_Expressions_A01_t09: MissingStaticWarning
+Language/12_Expressions/30_Identifier_Reference_A07_t01: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t07: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t08: MissingStaticWarning
+Language/13_Statements/09_Switch_A10_t03: MissingStaticWarning
+Language/13_Statements/15_Assert_A04_t04: MissingStaticWarning
+LibTest/collection/IterableMixin/IterableMixin_class_A01_t01: MissingStaticWarning
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 09b02e0..a998592 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -93,8 +93,7 @@
 LibTest/async/Stream/handleError_A04_t02: Fail # co19-roll r641: Please triage this failure
 LibTest/async/Stream/listen_A05_t02: Fail # co19-roll r641: Please triage this failure
 LibTest/async/StreamSink/addError_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/async/StreamSink/addStream_A01_t01: Timeout, Fail # co19-roll r641: Please triage this failure
-LibTest/async/StreamSink/addStream_A01_t02: Timeout, Fail # co19-roll r641: Please triage this failure
+LibTest/async/StreamSink/addStream_A01_t02: Timeout, Fail, OK # Dart issue 14334 - test is also incorrect.
 LibTest/collection/ListBase/ListBase_class_A01_t01: Fail, Timeout # co19-roll r641: Please triage this failure
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Fail, Timeout # co19-roll r641: Please triage this failure
 
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index f539402..7134716 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -31,8 +31,6 @@
 
 Language/03_Overview/1_Scoping_A02_t05: Fail # Inherited from dart2js
 Language/03_Overview/1_Scoping_A02_t06: Fail # inherited from dart2js
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Inherited from VM (circular initialization?).
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Inherited from dart2js
 Language/06_Functions/4_External_Functions_A01_t01: Fail # inherited from VM
 Language/07_Classes/3_Setters_A04_t01: Fail # inherited from VM
 Language/07_Classes/3_Setters_A04_t02: Fail # inherited from VM
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 357e7b6..862e381 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -14,9 +14,6 @@
 Language/13_Statements/03_Variable_Declaration_A04_t07: Fail # co19 issue 535
 Language/13_Statements/03_Variable_Declaration_A04_t08: Fail # co19 issue 535
 
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Dart issue 5802
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Dart issue 5894
-
 LibTest/core/RegExp/Pattern_semantics/firstMatch_Term_A03_t01: Fail # Issue 12508
 LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A02_t01: Fail # Issue 12508
 LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # Issue 12508
@@ -55,13 +52,11 @@
 LibTest/isolate/ReceivePort/receive_A01_t02: Fail # VM triage, check spec.
 LibTest/isolate/SendPort/send_A01_t01: fail # co19-roll r546: Please triage this failure
 
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: Fail # co19-roll r607: Please triage this failure
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: Fail # co19-roll r607: Please triage this failure
 LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # co19-roll r607: Please triage this failure
-LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # Issue 13106 
+LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # co19 issue 636
 
 [ $compiler == none && $runtime == vm ]
 LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13398
diff --git a/tests/compiler/dart2js/array_static_intercept_test.dart b/tests/compiler/dart2js/array_static_intercept_test.dart
index ca50ccf..23e88eb 100644
--- a/tests/compiler/dart2js/array_static_intercept_test.dart
+++ b/tests/compiler/dart2js/array_static_intercept_test.dart
@@ -17,5 +17,5 @@
   String generated = compile(TEST_ONE, entry: 'foo');
   Expect.isTrue(generated.contains(r'.add$1('));
   Expect.isTrue(generated.contains(r'.removeLast$0('));
-  Expect.isTrue(generated.contains(r'.get$length('));
+  Expect.isTrue(generated.contains(r'.length'));
 }
diff --git a/tests/compiler/dart2js/list_tracer_length_test.dart b/tests/compiler/dart2js/list_tracer_length_test.dart
index 6b039d8..89d3405 100644
--- a/tests/compiler/dart2js/list_tracer_length_test.dart
+++ b/tests/compiler/dart2js/list_tracer_length_test.dart
@@ -63,6 +63,14 @@
 }
 """;
 
+const String TEST7 = r"""
+var a = [42, 54];
+main() {
+  a[0]++;
+  return a[1];
+}
+""";
+
 void checkRangeError(String test, {bool hasRangeError}) {
   asyncTest(() => compileAll(test).then((generated) {
     Expect.equals(hasRangeError, generated.contains('ioore'));
@@ -79,4 +87,5 @@
   checkRangeError(TEST4, hasRangeError: true);
   checkRangeError(TEST5, hasRangeError: true);
   checkRangeError(TEST6, hasRangeError: true);
+  checkRangeError(TEST7, hasRangeError: false);
 }
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 27e412d..0099dc9 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -58,7 +58,7 @@
     // 2. Some code was refactored, and there are more methods.
     // Either situation could be problematic, but in situation 2, it is often
     // acceptable to increase [expectedMethodCount] a little.
-    int expectedMethodCount = 337;
+    int expectedMethodCount = 341;
     Expect.isTrue(
         generatedCode.length <= expectedMethodCount,
         'Too many compiled methods: '
diff --git a/tests/compiler/dart2js/subtype_test.dart b/tests/compiler/dart2js/subtype_test.dart
index 585659e..f755503 100644
--- a/tests/compiler/dart2js/subtype_test.dart
+++ b/tests/compiler/dart2js/subtype_test.dart
@@ -67,30 +67,30 @@
     expect(true, num_, Object_);
     expect(true, int_, Object_);
     expect(true, String_, Object_);
-    expect(true, dynamic_, Object_);
+    expect(true, dynamic_, Object_, expectMoreSpecific: false);
 
     expect(false, Object_, num_);
     expect(true, num_, num_);
     expect(true, int_, num_);
     expect(false, String_, num_);
-    expect(true, dynamic_, num_);
+    expect(true, dynamic_, num_, expectMoreSpecific: false);
 
     expect(false, Object_, int_);
     expect(false, num_, int_);
     expect(true, int_, int_);
     expect(false, String_, int_);
-    expect(true, dynamic_, int_);
+    expect(true, dynamic_, int_, expectMoreSpecific: false);
 
     expect(false, Object_, String_);
     expect(false, num_, String_);
     expect(false, int_, String_);
     expect(true, String_, String_);
-    expect(true, dynamic_, String_);
+    expect(true, dynamic_, String_, expectMoreSpecific: false);
 
-    expect(true, Object_, dynamic_, expectMoreSpecific: false);
-    expect(true, num_, dynamic_, expectMoreSpecific: false);
-    expect(true, int_, dynamic_, expectMoreSpecific: false);
-    expect(true, String_, dynamic_, expectMoreSpecific: false);
+    expect(true, Object_, dynamic_);
+    expect(true, num_, dynamic_);
+    expect(true, int_, dynamic_);
+    expect(true, String_, dynamic_);
     expect(true, dynamic_, dynamic_);
 
     DartType A_Object = instantiate(A, [Object_]);
@@ -103,36 +103,36 @@
     expect(false, A_Object, num_);
     expect(false, A_Object, int_);
     expect(false, A_Object, String_);
-    expect(true, A_Object, dynamic_, expectMoreSpecific: false);
+    expect(true, A_Object, dynamic_);
 
     expect(true, A_Object, A_Object);
     expect(true, A_num, A_Object);
     expect(true, A_int, A_Object);
     expect(true, A_String, A_Object);
-    expect(true, A_dynamic, A_Object);
+    expect(true, A_dynamic, A_Object, expectMoreSpecific: false);
 
     expect(false, A_Object, A_num);
     expect(true, A_num, A_num);
     expect(true, A_int, A_num);
     expect(false, A_String, A_num);
-    expect(true, A_dynamic, A_num);
+    expect(true, A_dynamic, A_num, expectMoreSpecific: false);
 
     expect(false, A_Object, A_int);
     expect(false, A_num, A_int);
     expect(true, A_int, A_int);
     expect(false, A_String, A_int);
-    expect(true, A_dynamic, A_int);
+    expect(true, A_dynamic, A_int, expectMoreSpecific: false);
 
     expect(false, A_Object, A_String);
     expect(false, A_num, A_String);
     expect(false, A_int, A_String);
     expect(true, A_String, A_String);
-    expect(true, A_dynamic, A_String);
+    expect(true, A_dynamic, A_String, expectMoreSpecific: false);
 
-    expect(true, A_Object, A_dynamic, expectMoreSpecific: false);
-    expect(true, A_num, A_dynamic, expectMoreSpecific: false);
-    expect(true, A_int, A_dynamic, expectMoreSpecific: false);
-    expect(true, A_String, A_dynamic, expectMoreSpecific: false);
+    expect(true, A_Object, A_dynamic);
+    expect(true, A_num, A_dynamic);
+    expect(true, A_int, A_dynamic);
+    expect(true, A_String, A_dynamic);
     expect(true, A_dynamic, A_dynamic);
 
     DartType B_Object_Object = instantiate(B, [Object_, Object_]);
@@ -146,27 +146,27 @@
     expect(false, B_Object_Object, A_num);
     expect(false, B_Object_Object, A_int);
     expect(false, B_Object_Object, A_String);
-    expect(true, B_Object_Object, A_dynamic, expectMoreSpecific: false);
+    expect(true, B_Object_Object, A_dynamic);
 
     expect(true, B_num_num, Object_);
     expect(true, B_num_num, A_Object);
     expect(true, B_num_num, A_num);
     expect(false, B_num_num, A_int);
     expect(false, B_num_num, A_String);
-    expect(true, B_num_num, A_dynamic, expectMoreSpecific: false);
+    expect(true, B_num_num, A_dynamic);
 
     expect(true, B_int_num, Object_);
     expect(true, B_int_num, A_Object);
     expect(true, B_int_num, A_num);
     expect(true, B_int_num, A_int);
     expect(false, B_int_num, A_String);
-    expect(true, B_int_num, A_dynamic, expectMoreSpecific: false);
+    expect(true, B_int_num, A_dynamic);
 
     expect(true, B_dynamic_dynamic, Object_);
-    expect(true, B_dynamic_dynamic, A_Object);
-    expect(true, B_dynamic_dynamic, A_num);
-    expect(true, B_dynamic_dynamic, A_int);
-    expect(true, B_dynamic_dynamic, A_String);
+    expect(true, B_dynamic_dynamic, A_Object, expectMoreSpecific: false);
+    expect(true, B_dynamic_dynamic, A_num, expectMoreSpecific: false);
+    expect(true, B_dynamic_dynamic, A_int, expectMoreSpecific: false);
+    expect(true, B_dynamic_dynamic, A_String, expectMoreSpecific: false);
     expect(true, B_dynamic_dynamic, A_dynamic);
 
     expect(true, B_String_dynamic, Object_);
@@ -174,37 +174,37 @@
     expect(false, B_String_dynamic, A_num);
     expect(false, B_String_dynamic, A_int);
     expect(true, B_String_dynamic, A_String);
-    expect(true, B_String_dynamic, A_dynamic, expectMoreSpecific: false);
+    expect(true, B_String_dynamic, A_dynamic);
 
     expect(true, B_Object_Object, B_Object_Object);
     expect(true, B_num_num, B_Object_Object);
     expect(true, B_int_num, B_Object_Object);
-    expect(true, B_dynamic_dynamic, B_Object_Object);
-    expect(true, B_String_dynamic, B_Object_Object);
+    expect(true, B_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false);
+    expect(true, B_String_dynamic, B_Object_Object, expectMoreSpecific: false);
 
     expect(false, B_Object_Object, B_num_num);
     expect(true, B_num_num, B_num_num);
     expect(true, B_int_num, B_num_num);
-    expect(true, B_dynamic_dynamic, B_num_num);
+    expect(true, B_dynamic_dynamic, B_num_num, expectMoreSpecific: false);
     expect(false, B_String_dynamic, B_num_num);
 
     expect(false, B_Object_Object, B_int_num);
     expect(false, B_num_num, B_int_num);
     expect(true, B_int_num, B_int_num);
-    expect(true, B_dynamic_dynamic, B_int_num);
+    expect(true, B_dynamic_dynamic, B_int_num, expectMoreSpecific: false);
     expect(false, B_String_dynamic, B_int_num);
 
-    expect(true, B_Object_Object, B_dynamic_dynamic, expectMoreSpecific: false);
-    expect(true, B_num_num, B_dynamic_dynamic, expectMoreSpecific: false);
-    expect(true, B_int_num, B_dynamic_dynamic, expectMoreSpecific: false);
+    expect(true, B_Object_Object, B_dynamic_dynamic);
+    expect(true, B_num_num, B_dynamic_dynamic);
+    expect(true, B_int_num, B_dynamic_dynamic);
     expect(true, B_dynamic_dynamic, B_dynamic_dynamic);
-    expect(true, B_String_dynamic, B_dynamic_dynamic,
-           expectMoreSpecific: false);
+    expect(true, B_String_dynamic, B_dynamic_dynamic);
 
     expect(false, B_Object_Object, B_String_dynamic);
     expect(false, B_num_num, B_String_dynamic);
     expect(false, B_int_num, B_String_dynamic);
-    expect(true, B_dynamic_dynamic, B_String_dynamic);
+    expect(true, B_dynamic_dynamic, B_String_dynamic,
+           expectMoreSpecific: false);
     expect(true, B_String_dynamic, B_String_dynamic);
 
     DartType C_Object_Object = instantiate(C, [Object_, Object_]);
@@ -215,26 +215,27 @@
     expect(true, C_Object_Object, B_Object_Object);
     expect(false, C_Object_Object, B_num_num);
     expect(false, C_Object_Object, B_int_num);
-    expect(true, C_Object_Object, B_dynamic_dynamic, expectMoreSpecific: false);
+    expect(true, C_Object_Object, B_dynamic_dynamic);
     expect(false, C_Object_Object, B_String_dynamic);
 
     expect(true, C_num_num, B_Object_Object);
     expect(true, C_num_num, B_num_num);
     expect(false, C_num_num, B_int_num);
-    expect(true, C_num_num, B_dynamic_dynamic, expectMoreSpecific: false);
+    expect(true, C_num_num, B_dynamic_dynamic);
     expect(false, C_num_num, B_String_dynamic);
 
     expect(true, C_int_String, B_Object_Object);
     expect(false, C_int_String, B_num_num);
     expect(false, C_int_String, B_int_num);
-    expect(true, C_int_String, B_dynamic_dynamic, expectMoreSpecific: false);
-    expect(true, C_int_String, B_String_dynamic, expectMoreSpecific: false);
+    expect(true, C_int_String, B_dynamic_dynamic);
+    expect(true, C_int_String, B_String_dynamic);
 
-    expect(true, C_dynamic_dynamic, B_Object_Object);
-    expect(true, C_dynamic_dynamic, B_num_num);
-    expect(true, C_dynamic_dynamic, B_int_num);
+    expect(true, C_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false);
+    expect(true, C_dynamic_dynamic, B_num_num, expectMoreSpecific: false);
+    expect(true, C_dynamic_dynamic, B_int_num, expectMoreSpecific: false);
     expect(true, C_dynamic_dynamic, B_dynamic_dynamic);
-    expect(true, C_dynamic_dynamic, B_String_dynamic);
+    expect(true, C_dynamic_dynamic, B_String_dynamic,
+           expectMoreSpecific: false);
 
     expect(false, C_int_String, A_int);
     expect(true, C_int_String, A_String);
@@ -586,7 +587,7 @@
     expect(false, A_T, num_);
     expect(false, A_T, int_);
     expect(false, A_T, String_);
-    expect(true, A_T, dynamic_, expectMoreSpecific: false);
+    expect(true, A_T, dynamic_);
     expect(true, A_T, A_T);
     expect(false, A_T, B_T);
 
@@ -595,7 +596,7 @@
     expect(false, B_T, num_);
     expect(false, B_T, int_);
     expect(false, B_T, String_);
-    expect(true, B_T, dynamic_, expectMoreSpecific: false);
+    expect(true, B_T, dynamic_);
     expect(true, B_T, B_T);
     expect(false, B_T, A_T);
 
@@ -604,7 +605,7 @@
     expect(true, C_T, num_);
     expect(false, C_T, int_);
     expect(false, C_T, String_);
-    expect(true, C_T, dynamic_, expectMoreSpecific: false);
+    expect(true, C_T, dynamic_);
     expect(true, C_T, C_T);
     expect(false, C_T, A_T);
 
@@ -613,7 +614,7 @@
     expect(true, D_T, num_);
     expect(true, D_T, int_);
     expect(false, D_T, String_);
-    expect(true, D_T, dynamic_, expectMoreSpecific: false);
+    expect(true, D_T, dynamic_);
     expect(true, D_T, D_T);
     expect(false, D_T, A_T);
 
@@ -622,7 +623,7 @@
     expect(true, E_T, num_);
     expect(false, E_T, int_);
     expect(false, E_T, String_);
-    expect(true, E_T, dynamic_, expectMoreSpecific: false);
+    expect(true, E_T, dynamic_);
     expect(true, E_T, E_T);
     expect(true, E_T, E_S);
     expect(false, E_T, A_T);
@@ -631,7 +632,7 @@
     expect(true, E_S, num_);
     expect(false, E_S, int_);
     expect(false, E_S, String_);
-    expect(true, E_S, dynamic_, expectMoreSpecific: false);
+    expect(true, E_S, dynamic_);
     expect(false, E_S, E_T);
     expect(true, E_S, E_S);
     expect(false, E_S, A_T);
@@ -641,7 +642,7 @@
     expect(true, F_T, num_);
     expect(false, F_T, int_);
     expect(false, F_T, String_);
-    expect(true, F_T, dynamic_, expectMoreSpecific: false);
+    expect(true, F_T, dynamic_);
     expect(false, F_T, F_S);
     expect(true, F_T, F_T);
     expect(false, F_T, A_T);
@@ -650,7 +651,7 @@
     expect(true, F_S, num_);
     expect(false, F_S, int_);
     expect(false, F_S, String_);
-    expect(true, F_S, dynamic_, expectMoreSpecific: false);
+    expect(true, F_S, dynamic_);
     expect(true, F_S, F_S);
     expect(true, F_S, F_T);
     expect(false, F_S, A_T);
@@ -660,7 +661,7 @@
     expect(false, G_T, num_);
     expect(false, G_T, int_);
     expect(false, G_T, String_);
-    expect(true, G_T, dynamic_, expectMoreSpecific: false);
+    expect(true, G_T, dynamic_);
     expect(true, G_T, G_T);
     expect(false, G_T, A_T);
 
@@ -669,7 +670,7 @@
     expect(false, H_T, num_);
     expect(false, H_T, int_);
     expect(false, H_T, String_);
-    expect(true, H_T, dynamic_, expectMoreSpecific: false);
+    expect(true, H_T, dynamic_);
     expect(true, H_T, H_T);
     expect(true, H_T, H_S);
     expect(false, H_T, A_T);
@@ -678,7 +679,7 @@
     expect(false, H_S, num_);
     expect(false, H_S, int_);
     expect(false, H_S, String_);
-    expect(true, H_S, dynamic_, expectMoreSpecific: false);
+    expect(true, H_S, dynamic_);
     expect(true, H_S, H_T);
     expect(true, H_S, H_S);
     expect(false, H_S, A_T);
@@ -688,7 +689,7 @@
     expect(false, I_T, num_);
     expect(false, I_T, int_);
     expect(false, I_T, String_);
-    expect(true, I_T, dynamic_, expectMoreSpecific: false);
+    expect(true, I_T, dynamic_);
     expect(true, I_T, I_T);
     expect(true, I_T, I_S);
     expect(true, I_T, I_U);
@@ -698,7 +699,7 @@
     expect(false, I_S, num_);
     expect(false, I_S, int_);
     expect(false, I_S, String_);
-    expect(true, I_S, dynamic_, expectMoreSpecific: false);
+    expect(true, I_S, dynamic_);
     expect(true, I_S, I_T);
     expect(true, I_S, I_S);
     expect(true, I_S, I_U);
@@ -708,7 +709,7 @@
     expect(false, I_U, num_);
     expect(false, I_U, int_);
     expect(false, I_U, String_);
-    expect(true, I_U, dynamic_, expectMoreSpecific: false);
+    expect(true, I_U, dynamic_);
     expect(true, I_U, I_T);
     expect(true, I_U, I_S);
     expect(true, I_U, I_U);
@@ -719,7 +720,7 @@
     expect(false, J_T, num_);
     expect(false, J_T, int_);
     expect(false, J_T, String_);
-    expect(true, J_T, dynamic_, expectMoreSpecific: false);
+    expect(true, J_T, dynamic_);
     expect(true, J_T, J_T);
     expect(true, J_T, J_S);
     expect(true, J_T, J_U);
@@ -729,7 +730,7 @@
     expect(false, J_S, num_);
     expect(false, J_S, int_);
     expect(false, J_S, String_);
-    expect(true, J_S, dynamic_, expectMoreSpecific: false);
+    expect(true, J_S, dynamic_);
     expect(false, J_S, J_T);
     expect(true, J_S, J_S);
     expect(true, J_S, J_U);
@@ -739,7 +740,7 @@
     expect(false, J_U, num_);
     expect(false, J_U, int_);
     expect(false, J_U, String_);
-    expect(true, J_U, dynamic_, expectMoreSpecific: false);
+    expect(true, J_U, dynamic_);
     expect(false, J_U, J_T);
     expect(true, J_U, J_S);
     expect(true, J_U, J_U);
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 19539ae..8ca53a8 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -1554,17 +1554,17 @@
         infos: []);
 
   check('''
-           D d = new E();
-           if (d is E<int>) {
+           D<int> d = new E();
+           if (d is E) {
              var x = d.e;
            }''',
         warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
-        hints: [MessageKind.NOT_MORE_SPECIFIC_RAW],
+        hints: [MessageKind.NOT_MORE_SPECIFIC],
         infos: []);
 
   check('''
-           D d = new E();
-           if (d is E<int>) {
+           D<int> d = new E();
+           if (d is E) {
              var x = d.f; // Type promotion wouldn't help.
            }''',
         warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index fd7cbf4..2d1a4d5 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -8,18 +8,18 @@
 import "../../../sdk/lib/_internal/compiler/implementation/ssa/ssa.dart";
 import "../../../sdk/lib/_internal/compiler/implementation/types/types.dart";
 
-const CONFLICTING = HType.CONFLICTING;
-const UNKNOWN = HType.UNKNOWN;
-const BOOLEAN = HType.BOOLEAN;
-const NUMBER = HType.NUMBER;
-const INTEGER = HType.INTEGER;
-const DOUBLE = HType.DOUBLE;
-const BOOLEAN_OR_NULL = HType.BOOLEAN_OR_NULL;
-const NUMBER_OR_NULL = HType.NUMBER_OR_NULL;
-const INTEGER_OR_NULL = HType.INTEGER_OR_NULL;
-const DOUBLE_OR_NULL = HType.DOUBLE_OR_NULL;
-const NULL = HType.NULL;
-const NON_NULL = HType.NON_NULL;
+HType nullType;
+HType objectType;
+HType jsBoolean;
+HType jsNumber;
+HType jsInteger;
+HType jsDouble;
+HType jsBooleanOrNull;
+HType jsNumberOrNull;
+HType jsIntegerOrNull;
+HType jsDoubleOrNull;
+HType emptyType;
+HType dynamicType;
 
 var patternClass;
 HType nonPrimitive1;
@@ -101,283 +101,283 @@
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
   check(type1, type2, predicate) => ruleSet.check(type1, type2, predicate);
 
-  rule(CONFLICTING, CONFLICTING, CONFLICTING);
-  rule(CONFLICTING, UNKNOWN, UNKNOWN);
-  rule(CONFLICTING, BOOLEAN, BOOLEAN);
-  rule(CONFLICTING, NUMBER, NUMBER);
-  rule(CONFLICTING, INTEGER, INTEGER);
-  rule(CONFLICTING, DOUBLE, DOUBLE);
-  rule(CONFLICTING, jsIndexable, jsIndexable);
-  rule(CONFLICTING, jsString, jsString);
-  rule(CONFLICTING, jsReadableArray, jsReadableArray);
-  rule(CONFLICTING, jsMutableArray, jsMutableArray);
-  rule(CONFLICTING, jsExtendableArray, jsExtendableArray);
-  rule(CONFLICTING, nonPrimitive1, nonPrimitive1);
-  rule(CONFLICTING, nonPrimitive2, nonPrimitive2);
-  rule(CONFLICTING, potentialArray, potentialArray);
-  rule(CONFLICTING, potentialString, potentialString);
-  rule(CONFLICTING, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
-  rule(CONFLICTING, NUMBER_OR_NULL, NUMBER_OR_NULL);
-  rule(CONFLICTING, INTEGER_OR_NULL, INTEGER_OR_NULL);
-  rule(CONFLICTING, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(CONFLICTING, jsStringOrNull, jsStringOrNull);
-  rule(CONFLICTING, NULL, NULL);
-  rule(CONFLICTING, jsFixedArray, jsFixedArray);
+  rule(emptyType, emptyType, emptyType);
+  rule(emptyType, dynamicType, dynamicType);
+  rule(emptyType, jsBoolean, jsBoolean);
+  rule(emptyType, jsNumber, jsNumber);
+  rule(emptyType, jsInteger, jsInteger);
+  rule(emptyType, jsDouble, jsDouble);
+  rule(emptyType, jsIndexable, jsIndexable);
+  rule(emptyType, jsString, jsString);
+  rule(emptyType, jsReadableArray, jsReadableArray);
+  rule(emptyType, jsMutableArray, jsMutableArray);
+  rule(emptyType, jsExtendableArray, jsExtendableArray);
+  rule(emptyType, nonPrimitive1, nonPrimitive1);
+  rule(emptyType, nonPrimitive2, nonPrimitive2);
+  rule(emptyType, potentialArray, potentialArray);
+  rule(emptyType, potentialString, potentialString);
+  rule(emptyType, jsBooleanOrNull, jsBooleanOrNull);
+  rule(emptyType, jsNumberOrNull, jsNumberOrNull);
+  rule(emptyType, jsIntegerOrNull, jsIntegerOrNull);
+  rule(emptyType, jsDoubleOrNull, jsDoubleOrNull);
+  rule(emptyType, jsStringOrNull, jsStringOrNull);
+  rule(emptyType, nullType, nullType);
+  rule(emptyType, jsFixedArray, jsFixedArray);
 
-  rule(UNKNOWN, UNKNOWN, UNKNOWN);
-  rule(UNKNOWN, BOOLEAN, UNKNOWN);
-  rule(UNKNOWN, NUMBER, UNKNOWN);
-  rule(UNKNOWN, INTEGER, UNKNOWN);
-  rule(UNKNOWN, DOUBLE, UNKNOWN);
-  rule(UNKNOWN, jsIndexable, UNKNOWN);
-  rule(UNKNOWN, jsString, UNKNOWN);
-  rule(UNKNOWN, jsReadableArray, UNKNOWN);
-  rule(UNKNOWN, jsMutableArray, UNKNOWN);
-  rule(UNKNOWN, jsExtendableArray, UNKNOWN);
-  rule(UNKNOWN, nonPrimitive1, UNKNOWN);
-  rule(UNKNOWN, nonPrimitive2, UNKNOWN);
-  rule(UNKNOWN, potentialArray, UNKNOWN);
-  rule(UNKNOWN, potentialString, UNKNOWN);
-  rule(UNKNOWN, BOOLEAN_OR_NULL, UNKNOWN);
-  rule(UNKNOWN, NUMBER_OR_NULL, UNKNOWN);
-  rule(UNKNOWN, INTEGER_OR_NULL, UNKNOWN);
-  rule(UNKNOWN, DOUBLE_OR_NULL, UNKNOWN);
-  rule(UNKNOWN, jsStringOrNull, UNKNOWN);
-  rule(UNKNOWN, NULL, UNKNOWN);
-  rule(UNKNOWN, jsFixedArray, UNKNOWN);
+  rule(dynamicType, dynamicType, dynamicType);
+  rule(dynamicType, jsBoolean, dynamicType);
+  rule(dynamicType, jsNumber, dynamicType);
+  rule(dynamicType, jsInteger, dynamicType);
+  rule(dynamicType, jsDouble, dynamicType);
+  rule(dynamicType, jsIndexable, dynamicType);
+  rule(dynamicType, jsString, dynamicType);
+  rule(dynamicType, jsReadableArray, dynamicType);
+  rule(dynamicType, jsMutableArray, dynamicType);
+  rule(dynamicType, jsExtendableArray, dynamicType);
+  rule(dynamicType, nonPrimitive1, dynamicType);
+  rule(dynamicType, nonPrimitive2, dynamicType);
+  rule(dynamicType, potentialArray, dynamicType);
+  rule(dynamicType, potentialString, dynamicType);
+  rule(dynamicType, jsBooleanOrNull, dynamicType);
+  rule(dynamicType, jsNumberOrNull, dynamicType);
+  rule(dynamicType, jsIntegerOrNull, dynamicType);
+  rule(dynamicType, jsDoubleOrNull, dynamicType);
+  rule(dynamicType, jsStringOrNull, dynamicType);
+  rule(dynamicType, nullType, dynamicType);
+  rule(dynamicType, jsFixedArray, dynamicType);
 
-  rule(BOOLEAN, BOOLEAN, BOOLEAN);
-  rule(BOOLEAN, NUMBER, jsInterceptor);
-  rule(BOOLEAN, INTEGER, jsInterceptor);
-  rule(BOOLEAN, DOUBLE, jsInterceptor);
-  rule(BOOLEAN, jsIndexable, NON_NULL);
-  rule(BOOLEAN, jsString, jsInterceptor);
-  rule(BOOLEAN, jsReadableArray, jsInterceptor);
-  rule(BOOLEAN, jsMutableArray, jsInterceptor);
-  rule(BOOLEAN, jsExtendableArray, jsInterceptor);
-  rule(BOOLEAN, nonPrimitive1, NON_NULL);
-  rule(BOOLEAN, nonPrimitive2, NON_NULL);
-  rule(BOOLEAN, potentialArray, UNKNOWN);
-  rule(BOOLEAN, potentialString, UNKNOWN);
-  rule(BOOLEAN, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
-  rule(BOOLEAN, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN, jsStringOrNull, jsInterceptorOrNull);
-  rule(BOOLEAN, NULL, BOOLEAN_OR_NULL);
-  rule(BOOLEAN, jsFixedArray, jsInterceptor);
+  rule(jsBoolean, jsBoolean, jsBoolean);
+  rule(jsBoolean, jsNumber, jsInterceptor);
+  rule(jsBoolean, jsInteger, jsInterceptor);
+  rule(jsBoolean, jsDouble, jsInterceptor);
+  rule(jsBoolean, jsIndexable, objectType);
+  rule(jsBoolean, jsString, jsInterceptor);
+  rule(jsBoolean, jsReadableArray, jsInterceptor);
+  rule(jsBoolean, jsMutableArray, jsInterceptor);
+  rule(jsBoolean, jsExtendableArray, jsInterceptor);
+  rule(jsBoolean, nonPrimitive1, objectType);
+  rule(jsBoolean, nonPrimitive2, objectType);
+  rule(jsBoolean, potentialArray, dynamicType);
+  rule(jsBoolean, potentialString, dynamicType);
+  rule(jsBoolean, jsBooleanOrNull, jsBooleanOrNull);
+  rule(jsBoolean, jsNumberOrNull, jsInterceptorOrNull);
+  rule(jsBoolean, jsIntegerOrNull, jsInterceptorOrNull);
+  rule(jsBoolean, jsDoubleOrNull, jsInterceptorOrNull);
+  rule(jsBoolean, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsBoolean, nullType, jsBooleanOrNull);
+  rule(jsBoolean, jsFixedArray, jsInterceptor);
 
-  rule(NUMBER, NUMBER, NUMBER);
-  rule(NUMBER, INTEGER, NUMBER);
-  rule(NUMBER, DOUBLE, NUMBER);
-  rule(NUMBER, jsIndexable, NON_NULL);
-  rule(NUMBER, jsString, jsInterceptor);
-  rule(NUMBER, jsReadableArray, jsInterceptor);
-  rule(NUMBER, jsMutableArray, jsInterceptor);
-  rule(NUMBER, jsExtendableArray, jsInterceptor);
-  rule(NUMBER, nonPrimitive1, NON_NULL);
-  rule(NUMBER, nonPrimitive2, NON_NULL);
-  rule(NUMBER, potentialArray, UNKNOWN);
-  rule(NUMBER, potentialString, UNKNOWN);
-  rule(NUMBER, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(NUMBER, NUMBER_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER, INTEGER_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER, jsStringOrNull, jsInterceptorOrNull);
-  rule(NUMBER, NULL, NUMBER_OR_NULL);
-  rule(NUMBER, jsFixedArray, jsInterceptor);
+  rule(jsNumber, jsNumber, jsNumber);
+  rule(jsNumber, jsInteger, jsNumber);
+  rule(jsNumber, jsDouble, jsNumber);
+  rule(jsNumber, jsIndexable, objectType);
+  rule(jsNumber, jsString, jsInterceptor);
+  rule(jsNumber, jsReadableArray, jsInterceptor);
+  rule(jsNumber, jsMutableArray, jsInterceptor);
+  rule(jsNumber, jsExtendableArray, jsInterceptor);
+  rule(jsNumber, nonPrimitive1, objectType);
+  rule(jsNumber, nonPrimitive2, objectType);
+  rule(jsNumber, potentialArray, dynamicType);
+  rule(jsNumber, potentialString, dynamicType);
+  rule(jsNumber, jsBooleanOrNull, jsInterceptorOrNull);
+  rule(jsNumber, jsNumberOrNull, jsNumberOrNull);
+  rule(jsNumber, jsIntegerOrNull, jsNumberOrNull);
+  rule(jsNumber, jsDoubleOrNull, jsNumberOrNull);
+  rule(jsNumber, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsNumber, nullType, jsNumberOrNull);
+  rule(jsNumber, jsFixedArray, jsInterceptor);
 
-  rule(INTEGER, INTEGER, INTEGER);
-  rule(INTEGER, DOUBLE, NUMBER);
-  rule(INTEGER, jsIndexable, NON_NULL);
-  rule(INTEGER, jsString, jsInterceptor);
-  rule(INTEGER, jsReadableArray, jsInterceptor);
-  rule(INTEGER, jsMutableArray, jsInterceptor);
-  rule(INTEGER, jsExtendableArray, jsInterceptor);
-  rule(INTEGER, nonPrimitive1, NON_NULL);
-  rule(INTEGER, nonPrimitive2, NON_NULL);
-  rule(INTEGER, potentialArray, UNKNOWN);
-  rule(INTEGER, potentialString, UNKNOWN);
-  rule(INTEGER, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(INTEGER, NUMBER_OR_NULL, NUMBER_OR_NULL);
-  rule(INTEGER, INTEGER_OR_NULL, INTEGER_OR_NULL);
-  rule(INTEGER, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(INTEGER, jsStringOrNull, jsInterceptorOrNull);
-  rule(INTEGER, NULL, INTEGER_OR_NULL);
-  rule(INTEGER, jsFixedArray, jsInterceptor);
+  rule(jsInteger, jsInteger, jsInteger);
+  rule(jsInteger, jsDouble, jsNumber);
+  rule(jsInteger, jsIndexable, objectType);
+  rule(jsInteger, jsString, jsInterceptor);
+  rule(jsInteger, jsReadableArray, jsInterceptor);
+  rule(jsInteger, jsMutableArray, jsInterceptor);
+  rule(jsInteger, jsExtendableArray, jsInterceptor);
+  rule(jsInteger, nonPrimitive1, objectType);
+  rule(jsInteger, nonPrimitive2, objectType);
+  rule(jsInteger, potentialArray, dynamicType);
+  rule(jsInteger, potentialString, dynamicType);
+  rule(jsInteger, jsBooleanOrNull, jsInterceptorOrNull);
+  rule(jsInteger, jsNumberOrNull, jsNumberOrNull);
+  rule(jsInteger, jsIntegerOrNull, jsIntegerOrNull);
+  rule(jsInteger, jsDoubleOrNull, jsNumberOrNull);
+  rule(jsInteger, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsInteger, nullType, jsIntegerOrNull);
+  rule(jsInteger, jsFixedArray, jsInterceptor);
 
-  rule(DOUBLE, DOUBLE, DOUBLE);
-  rule(DOUBLE, jsIndexable, NON_NULL);
-  rule(DOUBLE, jsString, jsInterceptor);
-  rule(DOUBLE, jsReadableArray, jsInterceptor);
-  rule(DOUBLE, jsMutableArray, jsInterceptor);
-  rule(DOUBLE, jsExtendableArray, jsInterceptor);
-  rule(DOUBLE, nonPrimitive1, NON_NULL);
-  rule(DOUBLE, nonPrimitive2, NON_NULL);
-  rule(DOUBLE, potentialArray, UNKNOWN);
-  rule(DOUBLE, potentialString, UNKNOWN);
-  rule(DOUBLE, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(DOUBLE, NUMBER_OR_NULL, NUMBER_OR_NULL);
-  rule(DOUBLE, INTEGER_OR_NULL, NUMBER_OR_NULL);
-  rule(DOUBLE, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE, jsStringOrNull, jsInterceptorOrNull);
-  rule(DOUBLE, NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE, jsFixedArray, jsInterceptor);
+  rule(jsDouble, jsDouble, jsDouble);
+  rule(jsDouble, jsIndexable, objectType);
+  rule(jsDouble, jsString, jsInterceptor);
+  rule(jsDouble, jsReadableArray, jsInterceptor);
+  rule(jsDouble, jsMutableArray, jsInterceptor);
+  rule(jsDouble, jsExtendableArray, jsInterceptor);
+  rule(jsDouble, nonPrimitive1, objectType);
+  rule(jsDouble, nonPrimitive2, objectType);
+  rule(jsDouble, potentialArray, dynamicType);
+  rule(jsDouble, potentialString, dynamicType);
+  rule(jsDouble, jsBooleanOrNull, jsInterceptorOrNull);
+  rule(jsDouble, jsNumberOrNull, jsNumberOrNull);
+  rule(jsDouble, jsIntegerOrNull, jsNumberOrNull);
+  rule(jsDouble, jsDoubleOrNull, jsDoubleOrNull);
+  rule(jsDouble, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsDouble, nullType, jsDoubleOrNull);
+  rule(jsDouble, jsFixedArray, jsInterceptor);
 
   rule(jsIndexable, jsIndexable, jsIndexable);
   rule(jsIndexable, jsString, jsIndexable);
   rule(jsIndexable, jsReadableArray, jsIndexable);
   rule(jsIndexable, jsMutableArray, jsIndexable);
   rule(jsIndexable, jsExtendableArray, jsIndexable);
-  rule(jsIndexable, nonPrimitive1, NON_NULL);
-  rule(jsIndexable, nonPrimitive2, NON_NULL);
-  rule(jsIndexable, potentialArray, UNKNOWN);
-  rule(jsIndexable, potentialString, UNKNOWN);
-  rule(jsIndexable, BOOLEAN_OR_NULL, UNKNOWN);
-  rule(jsIndexable, NUMBER_OR_NULL, UNKNOWN);
-  rule(jsIndexable, INTEGER_OR_NULL, UNKNOWN);
-  rule(jsIndexable, DOUBLE_OR_NULL, UNKNOWN);
+  rule(jsIndexable, nonPrimitive1, objectType);
+  rule(jsIndexable, nonPrimitive2, objectType);
+  rule(jsIndexable, potentialArray, dynamicType);
+  rule(jsIndexable, potentialString, dynamicType);
+  rule(jsIndexable, jsBooleanOrNull, dynamicType);
+  rule(jsIndexable, jsNumberOrNull, dynamicType);
+  rule(jsIndexable, jsIntegerOrNull, dynamicType);
+  rule(jsIndexable, jsDoubleOrNull, dynamicType);
   rule(jsIndexable, jsStringOrNull, jsIndexableOrNull);
-  rule(jsIndexable, NULL, jsIndexableOrNull);
+  rule(jsIndexable, nullType, jsIndexableOrNull);
   rule(jsIndexable, jsFixedArray, jsIndexable);
 
   rule(jsString, jsString, jsString);
   rule(jsString, jsReadableArray, jsIndexable);
   rule(jsString, jsMutableArray, jsIndexable);
   rule(jsString, jsExtendableArray, jsIndexable);
-  rule(jsString, nonPrimitive1, NON_NULL);
-  rule(jsString, nonPrimitive2, NON_NULL);
-  rule(jsString, potentialArray, UNKNOWN);
+  rule(jsString, nonPrimitive1, objectType);
+  rule(jsString, nonPrimitive2, objectType);
+  rule(jsString, potentialArray, dynamicType);
   rule(jsString, potentialString, potentialString);
-  rule(jsString, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(jsString, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(jsString, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(jsString, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsString, jsBooleanOrNull, jsInterceptorOrNull);
+  rule(jsString, jsNumberOrNull, jsInterceptorOrNull);
+  rule(jsString, jsIntegerOrNull, jsInterceptorOrNull);
+  rule(jsString, jsDoubleOrNull, jsInterceptorOrNull);
   rule(jsString, jsStringOrNull, jsStringOrNull);
-  rule(jsString, NULL, jsStringOrNull);
+  rule(jsString, nullType, jsStringOrNull);
   rule(jsString, jsFixedArray, jsIndexable);
 
   rule(jsReadableArray, jsReadableArray, jsReadableArray);
   rule(jsReadableArray, jsMutableArray, jsReadableArray);
   rule(jsReadableArray, jsExtendableArray, jsReadableArray);
-  rule(jsReadableArray, nonPrimitive1, NON_NULL);
-  rule(jsReadableArray, nonPrimitive2, NON_NULL);
+  rule(jsReadableArray, nonPrimitive1, objectType);
+  rule(jsReadableArray, nonPrimitive2, objectType);
   rule(jsReadableArray, potentialArray, potentialArray);
-  rule(jsReadableArray, potentialString, UNKNOWN);
-  rule(jsReadableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(jsReadableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(jsReadableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(jsReadableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsReadableArray, potentialString, dynamicType);
+  rule(jsReadableArray, jsBooleanOrNull, jsInterceptorOrNull);
+  rule(jsReadableArray, jsNumberOrNull, jsInterceptorOrNull);
+  rule(jsReadableArray, jsIntegerOrNull, jsInterceptorOrNull);
+  rule(jsReadableArray, jsDoubleOrNull, jsInterceptorOrNull);
   rule(jsReadableArray, jsStringOrNull, jsIndexableOrNull);
-  rule(jsReadableArray, NULL, jsArrayOrNull);
+  rule(jsReadableArray, nullType, jsArrayOrNull);
   rule(jsReadableArray, jsFixedArray, jsReadableArray);
 
   rule(jsMutableArray, jsMutableArray, jsMutableArray);
   rule(jsMutableArray, jsExtendableArray, jsMutableArray);
-  rule(jsMutableArray, nonPrimitive1, NON_NULL);
-  rule(jsMutableArray, nonPrimitive2, NON_NULL);
+  rule(jsMutableArray, nonPrimitive1, objectType);
+  rule(jsMutableArray, nonPrimitive2, objectType);
   rule(jsMutableArray, potentialArray, potentialArray);
-  rule(jsMutableArray, potentialString, UNKNOWN);
-  rule(jsMutableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(jsMutableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(jsMutableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(jsMutableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsMutableArray, potentialString, dynamicType);
+  rule(jsMutableArray, jsBooleanOrNull, jsInterceptorOrNull);
+  rule(jsMutableArray, jsNumberOrNull, jsInterceptorOrNull);
+  rule(jsMutableArray, jsIntegerOrNull, jsInterceptorOrNull);
+  rule(jsMutableArray, jsDoubleOrNull, jsInterceptorOrNull);
   rule(jsMutableArray, jsStringOrNull, jsIndexableOrNull);
-  rule(jsMutableArray, NULL, jsMutableArrayOrNull);
+  rule(jsMutableArray, nullType, jsMutableArrayOrNull);
   rule(jsMutableArray, jsFixedArray, jsMutableArray);
 
   rule(jsExtendableArray, jsExtendableArray, jsExtendableArray);
-  rule(jsExtendableArray, nonPrimitive1, NON_NULL);
-  rule(jsExtendableArray, nonPrimitive2, NON_NULL);
+  rule(jsExtendableArray, nonPrimitive1, objectType);
+  rule(jsExtendableArray, nonPrimitive2, objectType);
   rule(jsExtendableArray, potentialArray, potentialArray);
-  rule(jsExtendableArray, potentialString, UNKNOWN);
-  rule(jsExtendableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(jsExtendableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(jsExtendableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(jsExtendableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsExtendableArray, potentialString, dynamicType);
+  rule(jsExtendableArray, jsBooleanOrNull, jsInterceptorOrNull);
+  rule(jsExtendableArray, jsNumberOrNull, jsInterceptorOrNull);
+  rule(jsExtendableArray, jsIntegerOrNull, jsInterceptorOrNull);
+  rule(jsExtendableArray, jsDoubleOrNull, jsInterceptorOrNull);
   rule(jsExtendableArray, jsStringOrNull, jsIndexableOrNull);
-  rule(jsExtendableArray, NULL, jsExtendableArrayOrNull);
+  rule(jsExtendableArray, nullType, jsExtendableArrayOrNull);
   rule(jsExtendableArray, jsFixedArray, jsMutableArray);
 
   rule(nonPrimitive1, nonPrimitive1, nonPrimitive1);
-  rule(nonPrimitive1, nonPrimitive2, NON_NULL);
-  rule(nonPrimitive1, potentialArray, UNKNOWN);
-  rule(nonPrimitive1, potentialString, UNKNOWN);
-  rule(nonPrimitive1, BOOLEAN_OR_NULL, UNKNOWN);
-  rule(nonPrimitive1, NUMBER_OR_NULL, UNKNOWN);
-  rule(nonPrimitive1, INTEGER_OR_NULL, UNKNOWN);
-  rule(nonPrimitive1, DOUBLE_OR_NULL, UNKNOWN);
-  rule(nonPrimitive1, jsStringOrNull, UNKNOWN);
-  rule(nonPrimitive1, jsFixedArray, NON_NULL);
+  rule(nonPrimitive1, nonPrimitive2, objectType);
+  rule(nonPrimitive1, potentialArray, dynamicType);
+  rule(nonPrimitive1, potentialString, dynamicType);
+  rule(nonPrimitive1, jsBooleanOrNull, dynamicType);
+  rule(nonPrimitive1, jsNumberOrNull, dynamicType);
+  rule(nonPrimitive1, jsIntegerOrNull, dynamicType);
+  rule(nonPrimitive1, jsDoubleOrNull, dynamicType);
+  rule(nonPrimitive1, jsStringOrNull, dynamicType);
+  rule(nonPrimitive1, jsFixedArray, objectType);
 
   rule(nonPrimitive2, nonPrimitive2, nonPrimitive2);
-  rule(nonPrimitive2, potentialArray, UNKNOWN);
-  rule(nonPrimitive2, potentialString, UNKNOWN);
-  rule(nonPrimitive2, BOOLEAN_OR_NULL, UNKNOWN);
-  rule(nonPrimitive2, NUMBER_OR_NULL, UNKNOWN);
-  rule(nonPrimitive2, INTEGER_OR_NULL, UNKNOWN);
-  rule(nonPrimitive2, DOUBLE_OR_NULL, UNKNOWN);
-  rule(nonPrimitive2, jsStringOrNull, UNKNOWN);
-  rule(nonPrimitive2, jsFixedArray, NON_NULL);
+  rule(nonPrimitive2, potentialArray, dynamicType);
+  rule(nonPrimitive2, potentialString, dynamicType);
+  rule(nonPrimitive2, jsBooleanOrNull, dynamicType);
+  rule(nonPrimitive2, jsNumberOrNull, dynamicType);
+  rule(nonPrimitive2, jsIntegerOrNull, dynamicType);
+  rule(nonPrimitive2, jsDoubleOrNull, dynamicType);
+  rule(nonPrimitive2, jsStringOrNull, dynamicType);
+  rule(nonPrimitive2, jsFixedArray, objectType);
 
   rule(potentialArray, potentialArray, potentialArray);
-  rule(potentialArray, potentialString, UNKNOWN);
-  rule(potentialArray, BOOLEAN_OR_NULL, UNKNOWN);
-  rule(potentialArray, NUMBER_OR_NULL, UNKNOWN);
-  rule(potentialArray, INTEGER_OR_NULL, UNKNOWN);
-  rule(potentialArray, DOUBLE_OR_NULL, UNKNOWN);
-  rule(potentialArray, jsStringOrNull, UNKNOWN);
-  rule(potentialArray, NULL, potentialArray);
+  rule(potentialArray, potentialString, dynamicType);
+  rule(potentialArray, jsBooleanOrNull, dynamicType);
+  rule(potentialArray, jsNumberOrNull, dynamicType);
+  rule(potentialArray, jsIntegerOrNull, dynamicType);
+  rule(potentialArray, jsDoubleOrNull, dynamicType);
+  rule(potentialArray, jsStringOrNull, dynamicType);
+  rule(potentialArray, nullType, potentialArray);
   rule(potentialArray, jsFixedArray, potentialArray);
 
   rule(potentialString, potentialString, potentialString);
-  rule(potentialString, BOOLEAN_OR_NULL, UNKNOWN);
-  rule(potentialString, NUMBER_OR_NULL, UNKNOWN);
-  rule(potentialString, INTEGER_OR_NULL, UNKNOWN);
-  rule(potentialString, DOUBLE_OR_NULL, UNKNOWN);
+  rule(potentialString, jsBooleanOrNull, dynamicType);
+  rule(potentialString, jsNumberOrNull, dynamicType);
+  rule(potentialString, jsIntegerOrNull, dynamicType);
+  rule(potentialString, jsDoubleOrNull, dynamicType);
   rule(potentialString, jsStringOrNull, potentialString);
-  rule(potentialString, NULL, potentialString);
-  rule(potentialString, jsFixedArray, UNKNOWN);
+  rule(potentialString, nullType, potentialString);
+  rule(potentialString, jsFixedArray, dynamicType);
 
-  rule(BOOLEAN_OR_NULL, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
-  rule(BOOLEAN_OR_NULL, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN_OR_NULL, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN_OR_NULL, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
-  rule(BOOLEAN_OR_NULL, NULL, BOOLEAN_OR_NULL);
-  rule(BOOLEAN_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+  rule(jsBooleanOrNull, jsBooleanOrNull, jsBooleanOrNull);
+  rule(jsBooleanOrNull, jsNumberOrNull, jsInterceptorOrNull);
+  rule(jsBooleanOrNull, jsIntegerOrNull, jsInterceptorOrNull);
+  rule(jsBooleanOrNull, jsDoubleOrNull, jsInterceptorOrNull);
+  rule(jsBooleanOrNull, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsBooleanOrNull, nullType, jsBooleanOrNull);
+  rule(jsBooleanOrNull, jsFixedArray, jsInterceptorOrNull);
 
-  rule(NUMBER_OR_NULL, NUMBER_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER_OR_NULL, INTEGER_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER_OR_NULL, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
-  rule(NUMBER_OR_NULL, NULL, NUMBER_OR_NULL);
-  rule(NUMBER_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+  rule(jsNumberOrNull, jsNumberOrNull, jsNumberOrNull);
+  rule(jsNumberOrNull, jsIntegerOrNull, jsNumberOrNull);
+  rule(jsNumberOrNull, jsDoubleOrNull, jsNumberOrNull);
+  rule(jsNumberOrNull, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsNumberOrNull, nullType, jsNumberOrNull);
+  rule(jsNumberOrNull, jsFixedArray, jsInterceptorOrNull);
 
-  rule(INTEGER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
-  rule(INTEGER_OR_NULL, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(INTEGER_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
-  rule(INTEGER_OR_NULL, NULL, INTEGER_OR_NULL);
-  rule(INTEGER_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+  rule(jsIntegerOrNull, jsIntegerOrNull, jsIntegerOrNull);
+  rule(jsIntegerOrNull, jsDoubleOrNull, jsNumberOrNull);
+  rule(jsIntegerOrNull, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsIntegerOrNull, nullType, jsIntegerOrNull);
+  rule(jsIntegerOrNull, jsFixedArray, jsInterceptorOrNull);
 
-  rule(DOUBLE_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
-  rule(DOUBLE_OR_NULL, NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+  rule(jsDoubleOrNull, jsDoubleOrNull, jsDoubleOrNull);
+  rule(jsDoubleOrNull, jsStringOrNull, jsInterceptorOrNull);
+  rule(jsDoubleOrNull, nullType, jsDoubleOrNull);
+  rule(jsDoubleOrNull, jsFixedArray, jsInterceptorOrNull);
 
   rule(jsStringOrNull, jsStringOrNull, jsStringOrNull);
-  rule(jsStringOrNull, NULL, jsStringOrNull);
+  rule(jsStringOrNull, nullType, jsStringOrNull);
   rule(jsStringOrNull, jsFixedArray, jsIndexableOrNull);
 
-  rule(NULL, NULL, NULL);
-  rule(NULL, jsFixedArray, jsFixedArrayOrNull);
+  rule(nullType, nullType, nullType);
+  rule(nullType, jsFixedArray, jsFixedArrayOrNull);
 
   rule(jsFixedArray, jsFixedArray, jsFixedArray);
 
-  check(nonPrimitive1, NULL, (type) => type is HBoundedType);
-  check(nonPrimitive2, NULL, (type) => type is HBoundedType);
-  check(NULL, nonPrimitive1, (type) => type.canBeNull());
-  check(NULL, nonPrimitive2, (type) => type.canBeNull());
+  check(nonPrimitive1, nullType, (type) => type is HBoundedType);
+  check(nonPrimitive2, nullType, (type) => type is HBoundedType);
+  check(nullType, nonPrimitive1, (type) => type.canBeNull());
+  check(nullType, nonPrimitive2, (type) => type.canBeNull());
 
   ruleSet.validateCoverage();
 }
@@ -387,279 +387,279 @@
                                 (t1, t2) => t1.intersection(t2, compiler));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
 
-  rule(CONFLICTING, CONFLICTING, CONFLICTING);
-  rule(CONFLICTING, UNKNOWN, CONFLICTING);
-  rule(CONFLICTING, BOOLEAN, CONFLICTING);
-  rule(CONFLICTING, NUMBER, CONFLICTING);
-  rule(CONFLICTING, INTEGER, CONFLICTING);
-  rule(CONFLICTING, DOUBLE, CONFLICTING);
-  rule(CONFLICTING, jsIndexable, CONFLICTING);
-  rule(CONFLICTING, jsString, CONFLICTING);
-  rule(CONFLICTING, jsReadableArray, CONFLICTING);
-  rule(CONFLICTING, jsMutableArray, CONFLICTING);
-  rule(CONFLICTING, jsExtendableArray, CONFLICTING);
-  rule(CONFLICTING, nonPrimitive1, CONFLICTING);
-  rule(CONFLICTING, nonPrimitive2, CONFLICTING);
-  rule(CONFLICTING, potentialArray, CONFLICTING);
-  rule(CONFLICTING, potentialString, CONFLICTING);
-  rule(CONFLICTING, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(CONFLICTING, NUMBER_OR_NULL, CONFLICTING);
-  rule(CONFLICTING, INTEGER_OR_NULL, CONFLICTING);
-  rule(CONFLICTING, DOUBLE_OR_NULL, CONFLICTING);
-  rule(CONFLICTING, jsStringOrNull, CONFLICTING);
-  rule(CONFLICTING, NULL, CONFLICTING);
-  rule(CONFLICTING, jsFixedArray, CONFLICTING);
+  rule(emptyType, emptyType, emptyType);
+  rule(emptyType, dynamicType, emptyType);
+  rule(emptyType, jsBoolean, emptyType);
+  rule(emptyType, jsNumber, emptyType);
+  rule(emptyType, jsInteger, emptyType);
+  rule(emptyType, jsDouble, emptyType);
+  rule(emptyType, jsIndexable, emptyType);
+  rule(emptyType, jsString, emptyType);
+  rule(emptyType, jsReadableArray, emptyType);
+  rule(emptyType, jsMutableArray, emptyType);
+  rule(emptyType, jsExtendableArray, emptyType);
+  rule(emptyType, nonPrimitive1, emptyType);
+  rule(emptyType, nonPrimitive2, emptyType);
+  rule(emptyType, potentialArray, emptyType);
+  rule(emptyType, potentialString, emptyType);
+  rule(emptyType, jsBooleanOrNull, emptyType);
+  rule(emptyType, jsNumberOrNull, emptyType);
+  rule(emptyType, jsIntegerOrNull, emptyType);
+  rule(emptyType, jsDoubleOrNull, emptyType);
+  rule(emptyType, jsStringOrNull, emptyType);
+  rule(emptyType, nullType, emptyType);
+  rule(emptyType, jsFixedArray, emptyType);
 
-  rule(UNKNOWN, UNKNOWN, UNKNOWN);
-  rule(UNKNOWN, BOOLEAN, BOOLEAN);
-  rule(UNKNOWN, NUMBER, NUMBER);
-  rule(UNKNOWN, INTEGER, INTEGER);
-  rule(UNKNOWN, DOUBLE, DOUBLE);
-  rule(UNKNOWN, jsIndexable, jsIndexable);
-  rule(UNKNOWN, jsString, jsString);
-  rule(UNKNOWN, jsReadableArray, jsReadableArray);
-  rule(UNKNOWN, jsMutableArray, jsMutableArray);
-  rule(UNKNOWN, jsExtendableArray, jsExtendableArray);
-  rule(UNKNOWN, nonPrimitive1, nonPrimitive1);
-  rule(UNKNOWN, nonPrimitive2, nonPrimitive2);
-  rule(UNKNOWN, potentialArray, potentialArray);
-  rule(UNKNOWN, potentialString, potentialString);
-  rule(UNKNOWN, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
-  rule(UNKNOWN, NUMBER_OR_NULL, NUMBER_OR_NULL);
-  rule(UNKNOWN, INTEGER_OR_NULL, INTEGER_OR_NULL);
-  rule(UNKNOWN, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(UNKNOWN, jsStringOrNull, jsStringOrNull);
-  rule(UNKNOWN, NULL, NULL);
-  rule(UNKNOWN, jsFixedArray, jsFixedArray);
+  rule(dynamicType, dynamicType, dynamicType);
+  rule(dynamicType, jsBoolean, jsBoolean);
+  rule(dynamicType, jsNumber, jsNumber);
+  rule(dynamicType, jsInteger, jsInteger);
+  rule(dynamicType, jsDouble, jsDouble);
+  rule(dynamicType, jsIndexable, jsIndexable);
+  rule(dynamicType, jsString, jsString);
+  rule(dynamicType, jsReadableArray, jsReadableArray);
+  rule(dynamicType, jsMutableArray, jsMutableArray);
+  rule(dynamicType, jsExtendableArray, jsExtendableArray);
+  rule(dynamicType, nonPrimitive1, nonPrimitive1);
+  rule(dynamicType, nonPrimitive2, nonPrimitive2);
+  rule(dynamicType, potentialArray, potentialArray);
+  rule(dynamicType, potentialString, potentialString);
+  rule(dynamicType, jsBooleanOrNull, jsBooleanOrNull);
+  rule(dynamicType, jsNumberOrNull, jsNumberOrNull);
+  rule(dynamicType, jsIntegerOrNull, jsIntegerOrNull);
+  rule(dynamicType, jsDoubleOrNull, jsDoubleOrNull);
+  rule(dynamicType, jsStringOrNull, jsStringOrNull);
+  rule(dynamicType, nullType, nullType);
+  rule(dynamicType, jsFixedArray, jsFixedArray);
 
-  rule(BOOLEAN, BOOLEAN, BOOLEAN);
-  rule(BOOLEAN, NUMBER, CONFLICTING);
-  rule(BOOLEAN, INTEGER, CONFLICTING);
-  rule(BOOLEAN, DOUBLE, CONFLICTING);
-  rule(BOOLEAN, jsIndexable, CONFLICTING);
-  rule(BOOLEAN, jsString, CONFLICTING);
-  rule(BOOLEAN, jsReadableArray, CONFLICTING);
-  rule(BOOLEAN, jsMutableArray, CONFLICTING);
-  rule(BOOLEAN, jsExtendableArray, CONFLICTING);
-  rule(BOOLEAN, nonPrimitive1, CONFLICTING);
-  rule(BOOLEAN, nonPrimitive2, CONFLICTING);
-  rule(BOOLEAN, potentialArray, CONFLICTING);
-  rule(BOOLEAN, potentialString, CONFLICTING);
-  rule(BOOLEAN, BOOLEAN_OR_NULL, BOOLEAN);
-  rule(BOOLEAN, NUMBER_OR_NULL, CONFLICTING);
-  rule(BOOLEAN, INTEGER_OR_NULL, CONFLICTING);
-  rule(BOOLEAN, DOUBLE_OR_NULL, CONFLICTING);
-  rule(BOOLEAN, jsStringOrNull, CONFLICTING);
-  rule(BOOLEAN, NULL, CONFLICTING);
-  rule(BOOLEAN, jsFixedArray, CONFLICTING);
+  rule(jsBoolean, jsBoolean, jsBoolean);
+  rule(jsBoolean, jsNumber, emptyType);
+  rule(jsBoolean, jsInteger, emptyType);
+  rule(jsBoolean, jsDouble, emptyType);
+  rule(jsBoolean, jsIndexable, emptyType);
+  rule(jsBoolean, jsString, emptyType);
+  rule(jsBoolean, jsReadableArray, emptyType);
+  rule(jsBoolean, jsMutableArray, emptyType);
+  rule(jsBoolean, jsExtendableArray, emptyType);
+  rule(jsBoolean, nonPrimitive1, emptyType);
+  rule(jsBoolean, nonPrimitive2, emptyType);
+  rule(jsBoolean, potentialArray, emptyType);
+  rule(jsBoolean, potentialString, emptyType);
+  rule(jsBoolean, jsBooleanOrNull, jsBoolean);
+  rule(jsBoolean, jsNumberOrNull, emptyType);
+  rule(jsBoolean, jsIntegerOrNull, emptyType);
+  rule(jsBoolean, jsDoubleOrNull, emptyType);
+  rule(jsBoolean, jsStringOrNull, emptyType);
+  rule(jsBoolean, nullType, emptyType);
+  rule(jsBoolean, jsFixedArray, emptyType);
 
-  rule(NUMBER, NUMBER, NUMBER);
-  rule(NUMBER, INTEGER, INTEGER);
-  rule(NUMBER, DOUBLE, DOUBLE);
-  rule(NUMBER, jsIndexable, CONFLICTING);
-  rule(NUMBER, jsString, CONFLICTING);
-  rule(NUMBER, jsReadableArray, CONFLICTING);
-  rule(NUMBER, jsMutableArray, CONFLICTING);
-  rule(NUMBER, jsExtendableArray, CONFLICTING);
-  rule(NUMBER, nonPrimitive1, CONFLICTING);
-  rule(NUMBER, nonPrimitive2, CONFLICTING);
-  rule(NUMBER, potentialArray, CONFLICTING);
-  rule(NUMBER, potentialString, CONFLICTING);
-  rule(NUMBER, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(NUMBER, NUMBER_OR_NULL, NUMBER);
-  rule(NUMBER, INTEGER_OR_NULL, INTEGER);
-  rule(NUMBER, DOUBLE_OR_NULL, DOUBLE);
-  rule(NUMBER, jsStringOrNull, CONFLICTING);
-  rule(NUMBER, NULL, CONFLICTING);
-  rule(NUMBER, jsFixedArray, CONFLICTING);
+  rule(jsNumber, jsNumber, jsNumber);
+  rule(jsNumber, jsInteger, jsInteger);
+  rule(jsNumber, jsDouble, jsDouble);
+  rule(jsNumber, jsIndexable, emptyType);
+  rule(jsNumber, jsString, emptyType);
+  rule(jsNumber, jsReadableArray, emptyType);
+  rule(jsNumber, jsMutableArray, emptyType);
+  rule(jsNumber, jsExtendableArray, emptyType);
+  rule(jsNumber, nonPrimitive1, emptyType);
+  rule(jsNumber, nonPrimitive2, emptyType);
+  rule(jsNumber, potentialArray, emptyType);
+  rule(jsNumber, potentialString, emptyType);
+  rule(jsNumber, jsBooleanOrNull, emptyType);
+  rule(jsNumber, jsNumberOrNull, jsNumber);
+  rule(jsNumber, jsIntegerOrNull, jsInteger);
+  rule(jsNumber, jsDoubleOrNull, jsDouble);
+  rule(jsNumber, jsStringOrNull, emptyType);
+  rule(jsNumber, nullType, emptyType);
+  rule(jsNumber, jsFixedArray, emptyType);
 
-  rule(INTEGER, INTEGER, INTEGER);
-  rule(INTEGER, DOUBLE, CONFLICTING);
-  rule(INTEGER, jsIndexable, CONFLICTING);
-  rule(INTEGER, jsString, CONFLICTING);
-  rule(INTEGER, jsReadableArray, CONFLICTING);
-  rule(INTEGER, jsMutableArray, CONFLICTING);
-  rule(INTEGER, jsExtendableArray, CONFLICTING);
-  rule(INTEGER, nonPrimitive1, CONFLICTING);
-  rule(INTEGER, nonPrimitive2, CONFLICTING);
-  rule(INTEGER, potentialArray, CONFLICTING);
-  rule(INTEGER, potentialString, CONFLICTING);
-  rule(INTEGER, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(INTEGER, NUMBER_OR_NULL, INTEGER);
-  rule(INTEGER, INTEGER_OR_NULL, INTEGER);
-  rule(INTEGER, DOUBLE_OR_NULL, CONFLICTING);
-  rule(INTEGER, jsStringOrNull, CONFLICTING);
-  rule(INTEGER, NULL, CONFLICTING);
-  rule(INTEGER, jsFixedArray, CONFLICTING);
+  rule(jsInteger, jsInteger, jsInteger);
+  rule(jsInteger, jsDouble, emptyType);
+  rule(jsInteger, jsIndexable, emptyType);
+  rule(jsInteger, jsString, emptyType);
+  rule(jsInteger, jsReadableArray, emptyType);
+  rule(jsInteger, jsMutableArray, emptyType);
+  rule(jsInteger, jsExtendableArray, emptyType);
+  rule(jsInteger, nonPrimitive1, emptyType);
+  rule(jsInteger, nonPrimitive2, emptyType);
+  rule(jsInteger, potentialArray, emptyType);
+  rule(jsInteger, potentialString, emptyType);
+  rule(jsInteger, jsBooleanOrNull, emptyType);
+  rule(jsInteger, jsNumberOrNull, jsInteger);
+  rule(jsInteger, jsIntegerOrNull, jsInteger);
+  rule(jsInteger, jsDoubleOrNull, emptyType);
+  rule(jsInteger, jsStringOrNull, emptyType);
+  rule(jsInteger, nullType, emptyType);
+  rule(jsInteger, jsFixedArray, emptyType);
 
-  rule(DOUBLE, DOUBLE, DOUBLE);
-  rule(DOUBLE, jsIndexable, CONFLICTING);
-  rule(DOUBLE, jsString, CONFLICTING);
-  rule(DOUBLE, jsReadableArray, CONFLICTING);
-  rule(DOUBLE, jsMutableArray, CONFLICTING);
-  rule(DOUBLE, jsExtendableArray, CONFLICTING);
-  rule(DOUBLE, nonPrimitive1, CONFLICTING);
-  rule(DOUBLE, nonPrimitive2, CONFLICTING);
-  rule(DOUBLE, potentialArray, CONFLICTING);
-  rule(DOUBLE, potentialString, CONFLICTING);
-  rule(DOUBLE, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(DOUBLE, NUMBER_OR_NULL, DOUBLE);
-  rule(DOUBLE, INTEGER_OR_NULL, CONFLICTING);
-  rule(DOUBLE, DOUBLE_OR_NULL, DOUBLE);
-  rule(DOUBLE, jsStringOrNull, CONFLICTING);
-  rule(DOUBLE, NULL, CONFLICTING);
-  rule(DOUBLE, jsFixedArray, CONFLICTING);
+  rule(jsDouble, jsDouble, jsDouble);
+  rule(jsDouble, jsIndexable, emptyType);
+  rule(jsDouble, jsString, emptyType);
+  rule(jsDouble, jsReadableArray, emptyType);
+  rule(jsDouble, jsMutableArray, emptyType);
+  rule(jsDouble, jsExtendableArray, emptyType);
+  rule(jsDouble, nonPrimitive1, emptyType);
+  rule(jsDouble, nonPrimitive2, emptyType);
+  rule(jsDouble, potentialArray, emptyType);
+  rule(jsDouble, potentialString, emptyType);
+  rule(jsDouble, jsBooleanOrNull, emptyType);
+  rule(jsDouble, jsNumberOrNull, jsDouble);
+  rule(jsDouble, jsIntegerOrNull, emptyType);
+  rule(jsDouble, jsDoubleOrNull, jsDouble);
+  rule(jsDouble, jsStringOrNull, emptyType);
+  rule(jsDouble, nullType, emptyType);
+  rule(jsDouble, jsFixedArray, emptyType);
 
   rule(jsIndexable, jsIndexable, jsIndexable);
   rule(jsIndexable, jsString, jsString);
   rule(jsIndexable, jsReadableArray, jsReadableArray);
   rule(jsIndexable, jsMutableArray, jsMutableArray);
   rule(jsIndexable, jsExtendableArray, jsExtendableArray);
-  rule(jsIndexable, nonPrimitive1, CONFLICTING);
-  rule(jsIndexable, nonPrimitive2, CONFLICTING);
+  rule(jsIndexable, nonPrimitive1, emptyType);
+  rule(jsIndexable, nonPrimitive2, emptyType);
   rule(jsIndexable, potentialArray, new HType.nonNullSubtype(
       compiler.backend.jsArrayClass, compiler));
   rule(jsIndexable, potentialString, jsString);
-  rule(jsIndexable, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(jsIndexable, NUMBER_OR_NULL, CONFLICTING);
-  rule(jsIndexable, INTEGER_OR_NULL, CONFLICTING);
-  rule(jsIndexable, DOUBLE_OR_NULL, CONFLICTING);
+  rule(jsIndexable, jsBooleanOrNull, emptyType);
+  rule(jsIndexable, jsNumberOrNull, emptyType);
+  rule(jsIndexable, jsIntegerOrNull, emptyType);
+  rule(jsIndexable, jsDoubleOrNull, emptyType);
   rule(jsIndexable, jsStringOrNull, jsString);
-  rule(jsIndexable, NULL, CONFLICTING);
+  rule(jsIndexable, nullType, emptyType);
   rule(jsIndexable, jsFixedArray, jsFixedArray);
 
   rule(jsString, jsString, jsString);
-  rule(jsString, jsReadableArray, CONFLICTING);
-  rule(jsString, jsMutableArray, CONFLICTING);
-  rule(jsString, jsExtendableArray, CONFLICTING);
-  rule(jsString, nonPrimitive1, CONFLICTING);
-  rule(jsString, nonPrimitive2, CONFLICTING);
-  rule(jsString, potentialArray, CONFLICTING);
+  rule(jsString, jsReadableArray, emptyType);
+  rule(jsString, jsMutableArray, emptyType);
+  rule(jsString, jsExtendableArray, emptyType);
+  rule(jsString, nonPrimitive1, emptyType);
+  rule(jsString, nonPrimitive2, emptyType);
+  rule(jsString, potentialArray, emptyType);
   rule(jsString, potentialString, jsString);
-  rule(jsString, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(jsString, NUMBER_OR_NULL, CONFLICTING);
-  rule(jsString, INTEGER_OR_NULL, CONFLICTING);
-  rule(jsString, DOUBLE_OR_NULL, CONFLICTING);
+  rule(jsString, jsBooleanOrNull, emptyType);
+  rule(jsString, jsNumberOrNull, emptyType);
+  rule(jsString, jsIntegerOrNull, emptyType);
+  rule(jsString, jsDoubleOrNull, emptyType);
   rule(jsString, jsStringOrNull, jsString);
-  rule(jsString, NULL, CONFLICTING);
-  rule(jsString, jsFixedArray, CONFLICTING);
+  rule(jsString, nullType, emptyType);
+  rule(jsString, jsFixedArray, emptyType);
 
   rule(jsReadableArray, jsReadableArray, jsReadableArray);
   rule(jsReadableArray, jsMutableArray, jsMutableArray);
   rule(jsReadableArray, jsExtendableArray, jsExtendableArray);
-  rule(jsReadableArray, nonPrimitive1, CONFLICTING);
-  rule(jsReadableArray, nonPrimitive2, CONFLICTING);
+  rule(jsReadableArray, nonPrimitive1, emptyType);
+  rule(jsReadableArray, nonPrimitive2, emptyType);
   rule(jsReadableArray, potentialArray, jsReadableArray);
-  rule(jsReadableArray, potentialString, CONFLICTING);
-  rule(jsReadableArray, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(jsReadableArray, NUMBER_OR_NULL, CONFLICTING);
-  rule(jsReadableArray, INTEGER_OR_NULL, CONFLICTING);
-  rule(jsReadableArray, DOUBLE_OR_NULL, CONFLICTING);
-  rule(jsReadableArray, jsStringOrNull, CONFLICTING);
-  rule(jsReadableArray, NULL, CONFLICTING);
+  rule(jsReadableArray, potentialString, emptyType);
+  rule(jsReadableArray, jsBooleanOrNull, emptyType);
+  rule(jsReadableArray, jsNumberOrNull, emptyType);
+  rule(jsReadableArray, jsIntegerOrNull, emptyType);
+  rule(jsReadableArray, jsDoubleOrNull, emptyType);
+  rule(jsReadableArray, jsStringOrNull, emptyType);
+  rule(jsReadableArray, nullType, emptyType);
   rule(jsReadableArray, jsFixedArray, jsFixedArray);
 
   rule(jsMutableArray, jsMutableArray, jsMutableArray);
   rule(jsMutableArray, jsExtendableArray, jsExtendableArray);
-  rule(jsMutableArray, nonPrimitive1, CONFLICTING);
-  rule(jsMutableArray, nonPrimitive2, CONFLICTING);
+  rule(jsMutableArray, nonPrimitive1, emptyType);
+  rule(jsMutableArray, nonPrimitive2, emptyType);
   rule(jsMutableArray, potentialArray, jsMutableArray);
-  rule(jsMutableArray, potentialString, CONFLICTING);
-  rule(jsMutableArray, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(jsMutableArray, NUMBER_OR_NULL, CONFLICTING);
-  rule(jsMutableArray, INTEGER_OR_NULL, CONFLICTING);
-  rule(jsMutableArray, DOUBLE_OR_NULL, CONFLICTING);
-  rule(jsMutableArray, jsStringOrNull, CONFLICTING);
-  rule(jsMutableArray, NULL, CONFLICTING);
+  rule(jsMutableArray, potentialString, emptyType);
+  rule(jsMutableArray, jsBooleanOrNull, emptyType);
+  rule(jsMutableArray, jsNumberOrNull, emptyType);
+  rule(jsMutableArray, jsIntegerOrNull, emptyType);
+  rule(jsMutableArray, jsDoubleOrNull, emptyType);
+  rule(jsMutableArray, jsStringOrNull, emptyType);
+  rule(jsMutableArray, nullType, emptyType);
   rule(jsMutableArray, jsFixedArray, jsFixedArray);
 
   rule(jsExtendableArray, jsExtendableArray, jsExtendableArray);
-  rule(jsExtendableArray, nonPrimitive1, CONFLICTING);
-  rule(jsExtendableArray, nonPrimitive2, CONFLICTING);
+  rule(jsExtendableArray, nonPrimitive1, emptyType);
+  rule(jsExtendableArray, nonPrimitive2, emptyType);
   rule(jsExtendableArray, potentialArray, jsExtendableArray);
-  rule(jsExtendableArray, potentialString, CONFLICTING);
-  rule(jsExtendableArray, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(jsExtendableArray, NUMBER_OR_NULL, CONFLICTING);
-  rule(jsExtendableArray, INTEGER_OR_NULL, CONFLICTING);
-  rule(jsExtendableArray, DOUBLE_OR_NULL, CONFLICTING);
-  rule(jsExtendableArray, jsStringOrNull, CONFLICTING);
-  rule(jsExtendableArray, NULL, CONFLICTING);
-  rule(jsExtendableArray, jsFixedArray, CONFLICTING);
+  rule(jsExtendableArray, potentialString, emptyType);
+  rule(jsExtendableArray, jsBooleanOrNull, emptyType);
+  rule(jsExtendableArray, jsNumberOrNull, emptyType);
+  rule(jsExtendableArray, jsIntegerOrNull, emptyType);
+  rule(jsExtendableArray, jsDoubleOrNull, emptyType);
+  rule(jsExtendableArray, jsStringOrNull, emptyType);
+  rule(jsExtendableArray, nullType, emptyType);
+  rule(jsExtendableArray, jsFixedArray, emptyType);
 
   rule(nonPrimitive1, nonPrimitive1, nonPrimitive1);
-  rule(nonPrimitive1, nonPrimitive2, CONFLICTING);
-  rule(nonPrimitive1, potentialArray, CONFLICTING);
-  rule(nonPrimitive1, potentialString, CONFLICTING);
-  rule(nonPrimitive1, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(nonPrimitive1, NUMBER_OR_NULL, CONFLICTING);
-  rule(nonPrimitive1, INTEGER_OR_NULL, CONFLICTING);
-  rule(nonPrimitive1, DOUBLE_OR_NULL, CONFLICTING);
-  rule(nonPrimitive1, jsStringOrNull, CONFLICTING);
-  rule(nonPrimitive1, NULL, CONFLICTING);
-  rule(nonPrimitive1, jsFixedArray, CONFLICTING);
+  rule(nonPrimitive1, nonPrimitive2, emptyType);
+  rule(nonPrimitive1, potentialArray, emptyType);
+  rule(nonPrimitive1, potentialString, emptyType);
+  rule(nonPrimitive1, jsBooleanOrNull, emptyType);
+  rule(nonPrimitive1, jsNumberOrNull, emptyType);
+  rule(nonPrimitive1, jsIntegerOrNull, emptyType);
+  rule(nonPrimitive1, jsDoubleOrNull, emptyType);
+  rule(nonPrimitive1, jsStringOrNull, emptyType);
+  rule(nonPrimitive1, nullType, emptyType);
+  rule(nonPrimitive1, jsFixedArray, emptyType);
 
   rule(nonPrimitive2, nonPrimitive2, nonPrimitive2);
-  rule(nonPrimitive2, potentialArray, CONFLICTING);
-  rule(nonPrimitive2, potentialString, CONFLICTING);
-  rule(nonPrimitive2, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(nonPrimitive2, NUMBER_OR_NULL, CONFLICTING);
-  rule(nonPrimitive2, INTEGER_OR_NULL, CONFLICTING);
-  rule(nonPrimitive2, DOUBLE_OR_NULL, CONFLICTING);
-  rule(nonPrimitive2, jsStringOrNull, CONFLICTING);
-  rule(nonPrimitive2, NULL, CONFLICTING);
-  rule(nonPrimitive2, jsFixedArray, CONFLICTING);
+  rule(nonPrimitive2, potentialArray, emptyType);
+  rule(nonPrimitive2, potentialString, emptyType);
+  rule(nonPrimitive2, jsBooleanOrNull, emptyType);
+  rule(nonPrimitive2, jsNumberOrNull, emptyType);
+  rule(nonPrimitive2, jsIntegerOrNull, emptyType);
+  rule(nonPrimitive2, jsDoubleOrNull, emptyType);
+  rule(nonPrimitive2, jsStringOrNull, emptyType);
+  rule(nonPrimitive2, nullType, emptyType);
+  rule(nonPrimitive2, jsFixedArray, emptyType);
 
   rule(potentialArray, potentialArray, potentialArray);
-  rule(potentialArray, potentialString, NULL);
-  rule(potentialArray, BOOLEAN_OR_NULL, NULL);
-  rule(potentialArray, NUMBER_OR_NULL, NULL);
-  rule(potentialArray, INTEGER_OR_NULL, NULL);
-  rule(potentialArray, DOUBLE_OR_NULL, NULL);
-  rule(potentialArray, jsStringOrNull, NULL);
-  rule(potentialArray, NULL, NULL);
+  rule(potentialArray, potentialString, nullType);
+  rule(potentialArray, jsBooleanOrNull, nullType);
+  rule(potentialArray, jsNumberOrNull, nullType);
+  rule(potentialArray, jsIntegerOrNull, nullType);
+  rule(potentialArray, jsDoubleOrNull, nullType);
+  rule(potentialArray, jsStringOrNull, nullType);
+  rule(potentialArray, nullType, nullType);
   rule(potentialArray, jsFixedArray, jsFixedArray);
 
   rule(potentialString, potentialString, potentialString);
-  rule(potentialString, BOOLEAN_OR_NULL, NULL);
-  rule(potentialString, NUMBER_OR_NULL, NULL);
-  rule(potentialString, INTEGER_OR_NULL, NULL);
-  rule(potentialString, DOUBLE_OR_NULL, NULL);
+  rule(potentialString, jsBooleanOrNull, nullType);
+  rule(potentialString, jsNumberOrNull, nullType);
+  rule(potentialString, jsIntegerOrNull, nullType);
+  rule(potentialString, jsDoubleOrNull, nullType);
   rule(potentialString, jsStringOrNull, jsStringOrNull);
-  rule(potentialString, NULL, NULL);
-  rule(potentialString, jsFixedArray, CONFLICTING);
+  rule(potentialString, nullType, nullType);
+  rule(potentialString, jsFixedArray, emptyType);
 
-  rule(BOOLEAN_OR_NULL, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
-  rule(BOOLEAN_OR_NULL, NUMBER_OR_NULL, NULL);
-  rule(BOOLEAN_OR_NULL, INTEGER_OR_NULL, NULL);
-  rule(BOOLEAN_OR_NULL, DOUBLE_OR_NULL, NULL);
-  rule(BOOLEAN_OR_NULL, jsStringOrNull, NULL);
-  rule(BOOLEAN_OR_NULL, NULL, NULL);
-  rule(BOOLEAN_OR_NULL, jsFixedArray, CONFLICTING);
+  rule(jsBooleanOrNull, jsBooleanOrNull, jsBooleanOrNull);
+  rule(jsBooleanOrNull, jsNumberOrNull, nullType);
+  rule(jsBooleanOrNull, jsIntegerOrNull, nullType);
+  rule(jsBooleanOrNull, jsDoubleOrNull, nullType);
+  rule(jsBooleanOrNull, jsStringOrNull, nullType);
+  rule(jsBooleanOrNull, nullType, nullType);
+  rule(jsBooleanOrNull, jsFixedArray, emptyType);
 
-  rule(NUMBER_OR_NULL, NUMBER_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
-  rule(NUMBER_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(NUMBER_OR_NULL, jsStringOrNull, NULL);
-  rule(NUMBER_OR_NULL, NULL, NULL);
-  rule(NUMBER_OR_NULL, jsFixedArray, CONFLICTING);
+  rule(jsNumberOrNull, jsNumberOrNull, jsNumberOrNull);
+  rule(jsNumberOrNull, jsIntegerOrNull, jsIntegerOrNull);
+  rule(jsNumberOrNull, jsDoubleOrNull, jsDoubleOrNull);
+  rule(jsNumberOrNull, jsStringOrNull, nullType);
+  rule(jsNumberOrNull, nullType, nullType);
+  rule(jsNumberOrNull, jsFixedArray, emptyType);
 
-  rule(INTEGER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
-  rule(INTEGER_OR_NULL, DOUBLE_OR_NULL, NULL);
-  rule(INTEGER_OR_NULL, jsStringOrNull, NULL);
-  rule(INTEGER_OR_NULL, NULL, NULL);
-  rule(INTEGER_OR_NULL, jsFixedArray, CONFLICTING);
+  rule(jsIntegerOrNull, jsIntegerOrNull, jsIntegerOrNull);
+  rule(jsIntegerOrNull, jsDoubleOrNull, nullType);
+  rule(jsIntegerOrNull, jsStringOrNull, nullType);
+  rule(jsIntegerOrNull, nullType, nullType);
+  rule(jsIntegerOrNull, jsFixedArray, emptyType);
 
-  rule(DOUBLE_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE_OR_NULL, jsStringOrNull, NULL);
-  rule(DOUBLE_OR_NULL, NULL, NULL);
-  rule(DOUBLE_OR_NULL, jsFixedArray, CONFLICTING);
+  rule(jsDoubleOrNull, jsDoubleOrNull, jsDoubleOrNull);
+  rule(jsDoubleOrNull, jsStringOrNull, nullType);
+  rule(jsDoubleOrNull, nullType, nullType);
+  rule(jsDoubleOrNull, jsFixedArray, emptyType);
 
   rule(jsStringOrNull, jsStringOrNull, jsStringOrNull);
-  rule(jsStringOrNull, NULL, NULL);
-  rule(jsStringOrNull, jsFixedArray, CONFLICTING);
+  rule(jsStringOrNull, nullType, nullType);
+  rule(jsStringOrNull, jsFixedArray, emptyType);
 
-  rule(NULL, NULL, NULL);
-  rule(NULL, jsFixedArray, CONFLICTING);
+  rule(nullType, nullType, nullType);
+  rule(nullType, jsFixedArray, emptyType);
 
   rule(jsFixedArray, jsFixedArray, jsFixedArray);
 
@@ -725,6 +725,30 @@
       compiler.backend.jsStringClass, compiler);
   jsString = new HType.nonNullExact(
       compiler.backend.jsStringClass, compiler);
+  jsBoolean = new HType.nonNullExact(
+      compiler.backend.jsBoolClass, compiler);
+  jsNumber = new HType.nonNullSubclass(
+      compiler.backend.jsNumberClass, compiler);
+  jsInteger = new HType.nonNullExact(
+      compiler.backend.jsIntClass, compiler);
+  jsDouble = new HType.nonNullExact(
+      compiler.backend.jsDoubleClass, compiler);
+  jsBooleanOrNull = new HType.exact(
+      compiler.backend.jsBoolClass, compiler);
+  jsNumberOrNull = new HType.subclass(
+      compiler.backend.jsNumberClass, compiler);
+  jsIntegerOrNull = new HType.exact(
+      compiler.backend.jsIntClass, compiler);
+  jsDoubleOrNull = new HType.exact(
+      compiler.backend.jsDoubleClass, compiler);
+  nullType = new HBoundedType(
+      const TypeMask.empty());
+  objectType = new HType.nonNullSubclass(
+      compiler.objectClass, compiler);
+  emptyType = new HBoundedType(
+      const TypeMask.nonNullEmpty());
+  dynamicType = new HType.subclass(
+      compiler.objectClass, compiler);
 
   testUnion(compiler);
   testIntersection(compiler);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index c3db052..5055a89 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -12,7 +12,6 @@
 
 [ $compiler == none || $compiler == dart2dart ]
 symbol_test/none: Fail # bug 11669
-error_stack_trace2_test: Fail  # Bug 5802
 
 [ $compiler == none && $runtime == drt ]
 main_test: Fail  # Dartium needs to check for both main() and main(args).
@@ -41,7 +40,6 @@
 [ $compiler == dart2js ]
 error_stack_trace1_test: RuntimeError # Issue 12399
 hash_set_test/01: RuntimeError # Issue 11551
-main_test: Fail # Issue 14200
 
 big_integer_vm_test: RuntimeError, OK # VM specific test.
 bit_twiddling_bigint_test: RuntimeError # Requires bigint support.
@@ -113,3 +111,14 @@
 
 [ $arch == simmips && $mode == debug ]
 collection_to_string_test: Pass, Crash # Issue: 11207
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+collection_to_string_test: StaticWarning
+error_stack_trace_test: StaticWarning
+iterable_element_at_test: StaticWarning
+iterable_test: StaticWarning
+list_map_test: StaticWarning
+num_clamp_test: StaticWarning
+queue_test: StaticWarning
+string_codeunits_test: StaticWarning
+string_test: StaticWarning
diff --git a/tests/html/html.status b/tests/html/html.status
index cb34ece..0a46d3b 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -5,6 +5,7 @@
 async_window_test: Skip #TODO(gram): investigating
 event_test: Skip  # Issue 1996
 interactive_test: Skip # Must be run manually.
+dromaeo_smoke_test: Fail, Pass # Issue 14521
 
 [ $compiler == dart2js && $browser ]
 element_offset_test/offset: Pass, Fail # Issue 13296
@@ -29,10 +30,10 @@
 postmessage_structured_test/typed_arrays: Fail
 xhr_test: Pass, Fail # Issue 12648
 xhr_test/json: Fail # Issue 13069
-uri_test: Fail Issue 13581
 async_test: Fail # Background timers not implemented.
 keyboard_event_test: Fail # Issue 13902
 isolates_test: Fail # Issue 13921
+js_interop_2_test: Fail # Issue 14604
 
 [ $compiler == none && $runtime == drt && $system == windows ]
 worker_test/functional: Pass, Crash # Issue 9929.
@@ -70,9 +71,9 @@
 worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
 
 [ $compiler == dart2js && $runtime == safari ]
-url_test: Pass, Fail # Issue 14506 Passes only on certain versions of Safari
 audiobuffersourcenode_test/supported: Pass, Timeout # Issue 12772
 
+
 [ $compiler == dart2js && $browser && $checked ]
 postmessage_structured_test/typed_arrays: Fail # Issue 10097
 postmessage_structured_test/primitives: Fail # Issue 10097
@@ -273,11 +274,10 @@
 input_element_test/supported_time: Fail, Crash
 input_element_test/supported_week: Fail, Crash
 webgl_1_test: Pass, Fail # Issue 8219
-wheelevent_test: Pass, Fail # Issue: 14506 Passes only on certain versions of Safari
-xhr_test/xhr_requestBlob: Pass, Fail # Issue: 14506 Passes only on certain versions of Safari
 canvasrenderingcontext2d_test/drawImage_video_element: Fail # Safari does not support drawImage w/ video element
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
 audiocontext_test/functional: Fail # Issue 14354
+websql_test/functional: Pass, Fail # Issue 14523
 
 
 # Safari Feature support statuses-
@@ -350,8 +350,8 @@
 
 # FireFox Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
-audiobuffersourcenode_test/supported: Fail
-audiocontext_test/supported: Fail
+audiobuffersourcenode_test: Pass, Fail # Issue 14602
+audiocontext_test: Pass, Fail # Issue 14602
 css_test/supportsPointConversions: Fail
 document_test/supports_cssCanvasContext: Fail
 element_types_test/supported_content: Fail
@@ -402,3 +402,23 @@
 dromaeo_smoke_test: Fail # Issue 13719: Please triage this failure.
 element_offset_test/offset: Pass, Fail # Issue 13719, 13296
 touchevent_test/supported: Fail # Issue 13719: Please triage this failure.
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+audiocontext_test: StaticWarning
+custom/created_callback_test: StaticWarning
+custom/document_register_basic_test: StaticWarning
+datalistelement_test: StaticWarning
+documentfragment_test: StaticWarning
+element_add_test: StaticWarning
+element_test: StaticWarning
+events_test: StaticWarning
+htmlelement_test: StaticWarning
+isolates_test: StaticWarning
+localstorage_test: StaticWarning
+mutationobserver_test: StaticWarning
+track_element_constructor_test: StaticWarning
+transferables_test: StaticWarning
+typed_arrays_range_checks_test: StaticWarning
+typing_test: StaticWarning
+webgl_1_test: StaticWarning
+window_nosuchmethod_test: StaticWarning
diff --git a/tests/html/js_test.dart b/tests/html/js_test.dart
index 633ed89..e1aafae 100644
--- a/tests/html/js_test.dart
+++ b/tests/html/js_test.dart
@@ -269,7 +269,6 @@
       context.deleteProperty('foo2');
     });
 
-
     test('retrieve same dart Object', () {
       final obj = new Object();
       context['obj'] = obj;
@@ -315,16 +314,19 @@
     });
 
     test('new Array()', () {
-      final a = new JsObject(context['Array']);
-      expect(a, isNotNull);
-      expect(a['length'], equals(0));
+      var a = new JsObject(context['Array']);
+      expect(a, new isInstanceOf<JsArray>());
+
+      // Test that the object still behaves via the base JsObject interface.
+      // JsArray specific tests are below.
+      expect(a['length'], 0);
 
       a.callMethod('push', ["value 1"]);
-      expect(a['length'], equals(1));
-      expect(a[0], equals("value 1"));
+      expect(a['length'], 1);
+      expect(a[0], "value 1");
 
       a.callMethod('pop');
-      expect(a['length'], equals(0));
+      expect(a['length'], 0);
     });
 
     test('new Date()', () {
@@ -337,10 +339,9 @@
       expect(a.callMethod('getTime'), equals(12345678));
     });
 
-    test('new Date("December 17, 1995 03:24:00 GMT")',
-        () {
+    test('new Date("December 17, 1995 03:24:00 GMT")', () {
       final a = new JsObject(context['Date'],
-                             ["December 17, 1995 03:24:00 GMT"]);
+          ["December 17, 1995 03:24:00 GMT"]);
       expect(a.callMethod('getTime'), equals(819170640000));
     });
 
@@ -354,7 +355,7 @@
     test('new Date(1995,11,17,3,24,0)', () {
       // Note: JS Date counts months from 0 while Dart counts from 1.
       final a = new JsObject(context['Date'],
-                                         [1995, 11, 17, 3, 24, 0]);
+          [1995, 11, 17, 3, 24, 0]);
       final b = new DateTime(1995, 12, 17, 3, 24, 0);
       expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
     });
@@ -419,6 +420,11 @@
 
   group('JsFunction and callMethod', () {
 
+    test('new JsObject can return a JsFunction', () {
+      var f = new JsObject(context['Function']);
+      expect(f, new isInstanceOf<JsFunction>());
+    });
+
     test('JsFunction.apply on a function defined in JS', () {
       expect(context['razzle'].apply([]), equals(42));
     });
@@ -454,6 +460,150 @@
 */
   });
 
+  group('JsArray', () {
+
+    test('new JsArray()', () {
+      var array = new JsArray();
+      var arrayType = context['Array'];
+      expect(array.instanceof(arrayType), true);
+      expect(array, []);
+      // basic check that it behaves like a List
+      array.addAll([1, 2, 3]);
+      expect(array, [1, 2, 3]);
+    });
+
+    test('new JsArray.from()', () {
+      var array = new JsArray.from([1, 2, 3]);
+      var arrayType = context['Array'];
+      expect(array.instanceof(arrayType), true);
+      expect(array, [1, 2, 3]);
+    });
+
+    test('get Array from JS', () {
+      context['a'] = new JsObject(context['Array'], [1, 2, 3]);
+      expect(context.callMethod('isPropertyInstanceOf',
+          ['a', context['Array']]), isTrue);
+      var a = context['a'];
+      expect(a, new isInstanceOf<JsArray>());
+      expect(a, [1, 2, 3]);
+      context.deleteProperty('a');
+    });
+
+    test('pass Array to JS', () {
+      context['a'] = [1, 2, 3];
+      expect(context.callMethod('isPropertyInstanceOf',
+          ['a', context['Array']]), isFalse);
+      var a = context['a'];
+      expect(a, new isInstanceOf<List>());
+      expect(a, isNot(new isInstanceOf<JsArray>()));
+      expect(a, [1, 2, 3]);
+      context.deleteProperty('a');
+    });
+
+    test('[]', () {
+      var array = new JsArray.from([1, 2]);
+      expect(array[0], 1);
+      expect(array[1], 2);
+      expect(() => array[-1], throwsA(isRangeError));
+      expect(() => array[2], throwsA(isRangeError));
+    });
+
+   test('[]=', () {
+      var array = new JsArray.from([1, 2]);
+      array[0] = 'd';
+      array[1] = 'e';
+      expect(array, ['d', 'e']);
+      expect(() => array[-1] = 3, throwsA(isRangeError));
+      expect(() => array[2] = 3, throwsA(isRangeError));
+    });
+
+    test('length', () {
+      var array = new JsArray.from([1, 2, 3]);
+      expect(array.length, 3);
+      array.add(4);
+      expect(array.length, 4);
+      array.length = 2;
+      expect(array, [1, 2]);
+      array.length = 3;
+      expect(array, [1, 2, null]);
+    });
+ 
+     test('add', () {
+      var array = new JsArray();
+      array.add('a');
+      expect(array, ['a']);
+      array.add('b');
+      expect(array, ['a', 'b']);
+    });
+
+    test('addAll', () {
+      var array = new JsArray();
+      array.addAll(['a', 'b']);
+      expect(array, ['a', 'b']);
+      // make sure addAll can handle Iterables
+      array.addAll(new Set.from(['c']));
+      expect(array, ['a', 'b', 'c']);
+    });
+
+    test('insert', () {
+      var array = new JsArray.from([]);
+      array.insert(0, 'b');
+      expect(array, ['b']);
+      array.insert(0, 'a');
+      expect(array, ['a', 'b']);
+      array.insert(2, 'c');
+      expect(array, ['a', 'b', 'c']);
+      expect(() => array.insert(4, 'e'), throwsA(isRangeError));
+      expect(() => array.insert(-1, 'e'), throwsA(isRangeError));
+    });
+
+    test('removeAt', () {
+      var array = new JsArray.from(['a', 'b', 'c']);
+      expect(array.removeAt(1), 'b');
+      expect(array, ['a', 'c']);
+      expect(() => array.removeAt(2), throwsA(isRangeError));
+      expect(() => array.removeAt(-1), throwsA(isRangeError));
+    });
+
+    test('removeLast', () {
+      var array = new JsArray.from(['a', 'b', 'c']);
+      expect(array.removeLast(), 'c');
+      expect(array, ['a', 'b']);
+      array.length = 0;
+      expect(() => array.removeLast(), throwsA(isRangeError));
+    });
+
+    test('removeRange', () {
+      var array = new JsArray.from(['a', 'b', 'c', 'd']);
+      array.removeRange(1, 3);
+      expect(array, ['a', 'd']);
+      expect(() => array.removeRange(-1, 2), throwsA(isRangeError));
+      expect(() => array.removeRange(0, 3), throwsA(isRangeError));
+      expect(() => array.removeRange(2, 1), throwsA(isRangeError));
+    });
+
+    test('setRange', () {
+      var array = new JsArray.from(['a', 'b', 'c', 'd']);
+      array.setRange(1, 3, ['e', 'f']);
+      expect(array, ['a', 'e', 'f', 'd']);
+      array.setRange(3, 4, ['g', 'h', 'i'], 1);
+      expect(array, ['a', 'e', 'f', 'h']);
+    });
+
+    test('sort', () {
+      var array = new JsArray.from(['c', 'a', 'b']);
+      array.sort();
+      expect(array, ['a', 'b', 'c']);
+    });
+
+    test('sort with a Comparator', () {
+      var array = new JsArray.from(['c', 'a', 'b']);
+      array.sort((a, b) => -(a.compareTo(b)));
+      expect(array, ['c', 'b', 'a']);
+    });
+
+  });
+
   group('JsObject.fromBrowserObject()', () {
 
     test('Nodes are proxied', () {
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index d7e85a6..58e6cd7 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -13,10 +13,7 @@
 
 [ $analyzer ]
 isolate2_negative_test: Fail
-isolate_negative_test: Fail
 isolate_import_negative_test: Fail
-spawn_function_negative_test: Fail
-spawn_uri_vm_negative_test: Fail
 unresolved_ports_negative_test: Fail
 mandel_isolate_test: Fail # issue 14452
 
@@ -119,3 +116,18 @@
 spawn_function_test: Fail
 stacktrace_message_test: Fail
 unresolved_ports_test: Fail
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+browser/typed_data_message_test: StaticWarning
+illegal_msg_test: StaticWarning
+isolate3_negative_test: CompileTimeError
+isolate/illegal_msg_test: StaticWarning
+isolate_import_negative_test: CompileTimeError
+isolate/mint_maker_test: StaticWarning
+isolate/unresolved_ports_test: StaticWarning
+mandel_isolate_stream_test: StaticWarning
+mandel_isolate_test: StaticWarning
+mint_maker_test: StaticWarning
+serialization_test: StaticWarning
+unresolved_ports_test: StaticWarning
+
diff --git a/tests/language/arithmetic2_test.dart b/tests/language/arithmetic2_test.dart
index 0952f2b..65655da 100644
--- a/tests/language/arithmetic2_test.dart
+++ b/tests/language/arithmetic2_test.dart
@@ -2,7 +2,6 @@
 // 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.
 // Dart test program to test arithmetic operations.
-// @static-clean
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/bool_test.dart b/tests/language/bool_test.dart
index 4015c18..efe8a7a 100644
--- a/tests/language/bool_test.dart
+++ b/tests/language/bool_test.dart
@@ -4,9 +4,6 @@
 
 import "package:expect/expect.dart";
 
-// Dart test program for testing basic boolean properties.
-// @static-clean
-
 class BoolTest {
   static void testEquality() {
     Expect.equals(true, true);
diff --git a/tests/language/context2_test.dart b/tests/language/context2_test.dart
index 1b4d683..f3358ed 100644
--- a/tests/language/context2_test.dart
+++ b/tests/language/context2_test.dart
@@ -6,7 +6,6 @@
 import "package:expect/expect.dart";
 
 // Regression test for issue 5991015.
-// @static-clean
 
 class V {
 
diff --git a/tests/language/default_implementation_test.dart b/tests/language/default_implementation_test.dart
index 74a797d..51a2210 100644
--- a/tests/language/default_implementation_test.dart
+++ b/tests/language/default_implementation_test.dart
@@ -5,8 +5,6 @@
 
 import "package:expect/expect.dart";
 
-// @static-clean
-
 abstract class Point {
   factory Point(int x, int y) = PointImplementation;
 
diff --git a/tests/language/dynamic_test.dart b/tests/language/dynamic_test.dart
index b871001..8813b23 100644
--- a/tests/language/dynamic_test.dart
+++ b/tests/language/dynamic_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 //
 // Dart test program testing the use of 'dynamic' in generic types.
-// @static-clean
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/getters_setters_type2_test.dart b/tests/language/getters_setters_type2_test.dart
index 22a3264..0e19f80 100644
--- a/tests/language/getters_setters_type2_test.dart
+++ b/tests/language/getters_setters_type2_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // Getters and setters can have different types, and it is not a warning if the
 // two types are assignable.
-// @static-clean
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/getters_setters_type3_test.dart b/tests/language/getters_setters_type3_test.dart
index aaa8b35..a41f59f 100644
--- a/tests/language/getters_setters_type3_test.dart
+++ b/tests/language/getters_setters_type3_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // Getters and setters can have different types, and it is not a warning if the
 // two types are assignable.
-// @static-clean
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/language.status b/tests/language/language.status
index 120f90f..d5bb2ff 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -5,9 +5,6 @@
 # This directory contains tests that are intended to show the
 # current state of the language.
 
-[ $compiler == none && $runtime == drt && $mode == debug ]
-source_self_negative_test: Crash # Issue 14003
-
 [ $compiler == none ]
 mixin_super_constructor_named_test: Fail # Issue 12631
 mixin_super_constructor_positionals_test: Fail # Issue 12631
@@ -27,9 +24,6 @@
 mixin_forwarding_constructor2_test: Fail # Issue 13641
 implicit_setter_test: Fail # Issue 13917
 
-cyclic_typedef_test/10: Fail # Issue 13675
-cyclic_typedef_test/11: Fail # Issue 13675
-
 [ $compiler == none && $runtime == vm ]
 class_keyword_test/02: MissingCompileTimeError # Issue 13627
 
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 8bdaf61..5fb3de7 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -13,9 +13,6 @@
 class_literal_test: fail
 constructor_call_as_function_test/01: fail
 
-# TBF: It is a static warning if the function type of k' is not a subtype of the type of k.
-default_implementation2_test: fail
-
 function_type_alias9_test/00: crash # Issue 11987
 
 # TBF: we should check conflicts not only for methods, but for accessors too
@@ -24,9 +21,6 @@
 method_override7_test/03: Fail # Issue 11496
 method_override8_test/03: Fail # Issue 11496
 
-# TBF: prefix T hidden by type variable T in 'new T.Class()'
-prefix10_negative_test: fail
-
 built_in_identifier_test/none: Fail # Issue 13023
 
 
@@ -36,10 +30,6 @@
 #
 
 
-# test issue 10683, It is a compile-time error if e refers to the name v or the name v=.
-block_scope_test: fail
-lazy_static3_test: fail
-
 # test issue 11124, It is warning, not error to don't initialize final field
 field3a_negative_test: Fail # Issue 11124
 final_syntax_test/01: Fail # Issue 11124
@@ -72,9 +62,6 @@
 # test issue 11579, assignment, no setter
 getter_no_setter_test/none: fail
 
-# test issue 11581, it is not warning to call dynamic
-call_through_getter_test: fail
-
 # test issue 11584, positional arguments cannot be used for named parameters
 compile_time_constant_e_test: fail
 
@@ -96,16 +83,10 @@
 import_combinators_negative_test: fail
 interface_static_non_final_fields_negative_test: fail
 
-# test issue 11698, no setter, so warning, not error
-assign_instance_method_negative_test: fail
-
 # test issue 11918: mixin and const constructor
 const_constructor_mixin_test/01: fail
 const_constructor_mixin3_test/01: fail
 
-# test issue 11958, fails only at runtime
-no_such_method_negative_test: fail
-
 # test issue 11962, it is warning, not error to reference undeclared identifier
 prefix1_negative_test: fail
 prefix2_negative_test: fail
@@ -113,9 +94,6 @@
 prefix5_negative_test: fail
 prefix12_negative_test: fail
 
-# test issue 11963, it is fine to access any property of the dynamic variable
-prefix6_negative_test: fail
-
 # test issue 11964, Any use of a malformed type gives rise to a static warning.
 prefix8_negative_test: fail
 prefix11_negative_test: fail
@@ -180,17 +158,13 @@
 bailout3_test: fail # test issue 14289
 prefix9_test: fail # test issue 14289
 
-# test issue 14358, E does not implement inherited A.+
-type_promotion_closure_test/none: Fail
-
-# test issue 14362, wrong assumption that dynamic << A
-type_promotion_functions_test/none: Fail
-
 # test issue 14363, "if ((a is B))" has the same effect as "if (a is B)", so no static warning expected
 type_promotion_parameter_test/53: Fail
 
 # test issue 14364, "E<A> << D"
-type_promotion_more_specific_test/08: fail
+type_promotion_more_specific_test/09: Fail
+type_promotion_more_specific_test/10: Fail
+type_promotion_more_specific_test/11: Fail
 
 # test issue 14406, setter for final field was removed from spec
 implicit_setter_test/01: fail
@@ -199,24 +173,292 @@
 # test issue 14410, "typedef C = " is now really illegal syntax
 mixin_illegal_syntax_test/none: fail
 
-#
-# Please don't add new items here.
-# This is section for invalid tests.
-#
 
-[ $compiler == dartanalyzer && $checked ]
-factory1_test/00: fail
-factory1_test/01: fail
-field_type_check2_test/01: fail
-factory_implementation_test/00: fail
-factory_redirection_test/08: fail
-factory_redirection_test/09: fail
-factory_redirection_test/10: fail
-factory_redirection_test/11: fail
-factory_redirection_test/12: fail
-factory_redirection_test/13: fail
-factory_redirection_test/14: fail
-getters_setters2_test/03: fail
-type_variable_bounds3_test/00: fail
-type_variable_bounds2_test/05: fail
+abstract_exact_selector_test: StaticWarning
+abstract_getter_test: StaticWarning
+abstract_object_method_test: StaticWarning
+abstract_runtime_error_test: StaticWarning
+application_negative_test: CompileTimeError
+bad_constructor_test/05: CompileTimeError
+bad_initializer1_negative_test: CompileTimeError
+bad_named_constructor_negative_test: CompileTimeError
+bad_named_parameters2_test: StaticWarning
+bad_named_parameters_test: StaticWarning
+bit_operations_test: StaticWarning
+body_less_constructor_wrong_arg_negative_test: CompileTimeError
+built_in_identifier_test/01: CompileTimeError
+call_constructor_on_unresolvable_class_test/04: StaticWarning
+call_constructor_on_unresolvable_class_test/05: StaticWarning
+call_constructor_on_unresolvable_class_test/06: StaticWarning
+call_nonexistent_constructor_test: StaticWarning
+checked_null_test: StaticWarning
+checked_setter2_test: StaticWarning
+checked_setter_test: StaticWarning
+closure_type_test: StaticWarning
+compile_time_constant_checked2_test/02: MissingCompileTimeError
+compile_time_constant_checked2_test/03: MissingCompileTimeError
+compile_time_constant_checked2_test/04: MissingCompileTimeError
+compile_time_constant_checked2_test/06: MissingCompileTimeError
+compile_time_constant_checked3_test/02: MissingCompileTimeError
+compile_time_constant_checked3_test/03: MissingCompileTimeError
+compile_time_constant_checked3_test/04: MissingCompileTimeError
+compile_time_constant_checked3_test/06: MissingCompileTimeError
+compile_time_constant_checked_test/02: MissingCompileTimeError
+compile_time_constant_k_test: StaticWarning
+compile_time_constant_o_test: StaticWarning
+const_counter_negative_test: CompileTimeError
+const_objects_are_immutable_test: StaticWarning
+const_optional_args_negative_test: CompileTimeError
+constructor_named_arguments_test/01: StaticWarning
+constructor_redirect1_negative_test: CompileTimeError
+constructor_redirect2_negative_test: CompileTimeError
+constructor_setter_negative_test: CompileTimeError
+constructor_test: StaticWarning
+core_type_check_test: StaticWarning
+crash_6725_test: StaticWarning
+default_factory_library_test: StaticWarning
+default_factory_test: StaticWarning
+div_with_power_of_two2_test: StaticWarning
+double_to_string_as_exponential2_test: StaticWarning
+double_to_string_as_fixed2_test: StaticWarning
+double_to_string_as_precision2_test: StaticWarning
+duplicate_export_negative_test: CompileTimeError
+duplicate_interface_negative_test: CompileTimeError
+dynamic_field_test: StaticWarning
+dynamic_prefix_core_test: StaticWarning
+empty_block_case_test: StaticWarning
+error_stacktrace_test: StaticWarning
+extend_type_parameter2_negative_test: CompileTimeError
+extend_type_parameter_negative_test: CompileTimeError
+external_test/20: StaticWarning
+factory2_negative_test: CompileTimeError
+factory2_test: StaticWarning
+factory3_negative_test: CompileTimeError
+factory3_test: StaticWarning
+factory4_test: StaticWarning
+factory_implementation_test/00: StaticWarning
+factory_negative_test: CompileTimeError
+factory_redirection_test/01: StaticWarning
+factory_redirection_test/03: StaticWarning
+factory_redirection_test/05: StaticWarning
+factory_redirection_test/06: StaticWarning
+factory_return_type_checked_test: StaticWarning
+f_bounded_quantification4_test: StaticWarning
+f_bounded_quantification5_test: StaticWarning
+field1_negative_test: CompileTimeError
+field2_negative_test: CompileTimeError
+field3_negative_test: CompileTimeError
+field4_negative_test: CompileTimeError
+field5_negative_test: CompileTimeError
+field6a_negative_test: CompileTimeError
+field6_negative_test: CompileTimeError
+first_class_types_literals_test: StaticWarning
+function_malformed_result_type_test: StaticWarning
+function_subtype_bound_closure7_test: StaticWarning
+function_subtype_checked0_test: StaticWarning
+function_subtype_closure0_test: StaticWarning
+function_subtype_closure1_test: StaticWarning
+function_subtype_factory1_test: StaticWarning
+function_subtype_inline1_test: StaticWarning
+function_type2_test: StaticWarning
+function_type_parameter2_negative_test: CompileTimeError
+function_type_parameter_negative_test: CompileTimeError
+generic_list_checked_test: StaticWarning
+generics_test: StaticWarning
+generic_test: StaticWarning
+getter_declaration_negative_test: CompileTimeError
+getter_no_setter2_test/01: StaticWarning
+getter_no_setter_test/01: StaticWarning
+illegal_invocation_test/01: CompileTimeError
+implicit_this_test/02: StaticWarning
+implied_interface_test: StaticWarning
+import_combinators_test: StaticWarning
+import_core_prefix_test: StaticWarning
+inferrer_this_access_test: StaticWarning
+inlined_throw_test: StaticWarning
+instance_method2_negative_test: CompileTimeError
+instance_method_negative_test: CompileTimeError
+instanceof3_test: StaticWarning
+instantiate_type_variable_test/01: StaticWarning
+inst_field_initializer1_negative_test: CompileTimeError
+interceptor6_test: StaticWarning
+interface2_negative_test: CompileTimeError
+interface_inherit_field_test: StaticWarning
+interface_injection1_negative_test: CompileTimeError
+interface_injection2_negative_test: CompileTimeError
+interface_static_method_negative_test: CompileTimeError
+invocation_mirror_test: StaticWarning
+is_not_class1_negative_test: CompileTimeError
+is_not_class2_test: StaticWarning
+is_not_class4_negative_test: CompileTimeError
+isnot_malformed_type_test: StaticWarning
+issue1363_test: StaticWarning
+issue1578_negative_test: CompileTimeError
+label2_negative_test: CompileTimeError
+label3_negative_test: CompileTimeError
+label5_negative_test: CompileTimeError
+label6_negative_test: CompileTimeError
+label8_negative_test: CompileTimeError
+label_test: StaticWarning
+library_ambiguous_test/00: StaticWarning
+library_ambiguous_test/01: CompileTimeError
+library_ambiguous_test/02: CompileTimeError
+library_ambiguous_test/03: CompileTimeError
+library_negative_test: CompileTimeError
+list_literal2_negative_test: CompileTimeError
+list_literal4_test: StaticWarning
+list_literal_negative_test: CompileTimeError
+list_test: StaticWarning
+malbounded_type_cast_test: StaticWarning
+malbounded_type_literal_test: StaticWarning
+malformed_type_test: StaticWarning
+map_literal11_test: StaticWarning
+map_literal2_negative_test: CompileTimeError
+map_literal3_test: StaticWarning
+map_literal4_test: StaticWarning
+map_literal6_test: StaticWarning
+map_literal8_test: StaticWarning
+map_literal_negative_test: CompileTimeError
+method_override4_test: StaticWarning
+method_override5_test: StaticWarning
+method_override6_test: StaticWarning
+method_override_test: StaticWarning
+mixin_illegal_syntax_test/13: CompileTimeError
+mixin_typedef_constructor_test: StaticWarning
+mixin_type_parameter2_test: StaticWarning
+mixin_type_parameters_mixin_extends_test: StaticWarning
+mixin_type_parameters_mixin_test: StaticWarning
+mixin_type_parameters_super_extends_test: StaticWarning
+mixin_type_parameters_super_test: StaticWarning
+mixin_with_two_implicit_constructors_test: StaticWarning
+named_constructor_test/01: StaticWarning
+named_constructor_test/03: StaticWarning
+named_parameters2_test: StaticWarning
+named_parameters3_test: StaticWarning
+named_parameters4_test: StaticWarning
+named_parameters_test/01: StaticWarning
+named_parameters_test/02: StaticWarning
+named_parameters_test/03: StaticWarning
+named_parameters_test/04: StaticWarning
+named_parameters_test/05: StaticWarning
+named_parameters_test/06: StaticWarning
+named_parameters_test/07: StaticWarning
+named_parameters_test/08: StaticWarning
+named_parameters_test/09: StaticWarning
+named_parameters_test/10: StaticWarning
+named_parameters_type_test/01: StaticWarning
+new_expression1_negative_test: CompileTimeError
+new_expression2_negative_test: CompileTimeError
+new_expression3_negative_test: CompileTimeError
+non_const_super_negative_test: CompileTimeError
+non_parameterized_factory2_test: StaticWarning
+non_parameterized_factory_test: StaticWarning
+no_such_constructor2_test: StaticWarning
+no_such_method2_test: StaticWarning
+no_such_method_dispatcher_test: StaticWarning
+not_enough_positional_arguments_test/00: StaticWarning
+not_enough_positional_arguments_test/01: CompileTimeError
+not_enough_positional_arguments_test/02: StaticWarning
+not_enough_positional_arguments_test/03: StaticWarning
+not_enough_positional_arguments_test/05: StaticWarning
+not_enough_positional_arguments_test/06: StaticWarning
+not_enough_positional_arguments_test/07: StaticWarning
+number_identifier_test/08: StaticWarning
+number_identifier_test/09: StaticWarning
+on_catch_malformed_type_test: StaticWarning
+operator1_negative_test: CompileTimeError
+operator2_negative_test: CompileTimeError
+operator_equals_test: StaticWarning
+optional_named_parameters_test/01: StaticWarning
+optional_named_parameters_test/02: StaticWarning
+optional_named_parameters_test/03: StaticWarning
+optional_named_parameters_test/04: StaticWarning
+optional_named_parameters_test/05: StaticWarning
+optional_named_parameters_test/06: StaticWarning
+optional_named_parameters_test/07: StaticWarning
+optional_named_parameters_test/08: StaticWarning
+optional_named_parameters_test/09: StaticWarning
+override_field_method1_negative_test: CompileTimeError
+override_field_method2_negative_test: CompileTimeError
+override_field_method4_negative_test: CompileTimeError
+override_field_method5_negative_test: CompileTimeError
+parameter_initializer1_negative_test: CompileTimeError
+parameter_initializer2_negative_test: CompileTimeError
+parameter_initializer3_negative_test: CompileTimeError
+parameter_initializer4_negative_test: CompileTimeError
+parameter_initializer5_negative_test: CompileTimeError
+parameter_initializer6_negative_test: CompileTimeError
+parser_quirks_test: StaticWarning
+part2_test: StaticWarning
+positional_parameters_type_test/01: StaticWarning
+prefix13_negative_test: CompileTimeError
+prefix14_test: StaticWarning
+prefix15_negative_test: CompileTimeError
+prefix15_test: StaticWarning
+prefix16_test: StaticWarning
+prefix17_test: StaticWarning
+prefix18_negative_test: CompileTimeError
+prefix22_test: StaticWarning
+prefix23_test: StaticWarning
+prefix7_negative_test: CompileTimeError
+property_field_override_test: StaticWarning
+redirecting_factory_default_values_test/none: StaticWarning
+redirecting_factory_incompatible_signature_test: StaticWarning
+regress_13494_test: StaticWarning
+return_type_test: StaticWarning
+script1_negative_test: CompileTimeError
+script2_negative_test: CompileTimeError
+setter_declaration2_negative_test: CompileTimeError
+setter_declaration_negative_test: CompileTimeError
+setter_no_getter_call_test/01: CompileTimeError
+source_self_negative_test: CompileTimeError
+static_initializer_type_error_test: StaticWarning
+string_escape4_negative_test: CompileTimeError
+string_interpolate1_negative_test: CompileTimeError
+string_interpolate2_negative_test: CompileTimeError
+string_interpolate_test: StaticWarning
+string_interpolation1_negative_test: CompileTimeError
+string_interpolation2_negative_test: CompileTimeError
+string_interpolation3_negative_test: CompileTimeError
+string_interpolation4_negative_test: CompileTimeError
+string_interpolation5_negative_test: CompileTimeError
+string_interpolation6_negative_test: CompileTimeError
+string_test: StaticWarning
+string_unicode1_negative_test: CompileTimeError
+string_unicode2_negative_test: CompileTimeError
+string_unicode3_negative_test: CompileTimeError
+string_unicode4_negative_test: CompileTimeError
+super_assign_test: StaticWarning
+super_call4_test: StaticWarning
+super_getter_setter_test: StaticWarning
+super_operator_index5_test: StaticWarning
+super_operator_index6_test: StaticWarning
+super_operator_index7_test: StaticWarning
+super_operator_index8_test: StaticWarning
+super_operator_test: StaticWarning
+super_setter_test: StaticWarning
+switch1_negative_test: CompileTimeError
+switch3_negative_test: CompileTimeError
+switch4_negative_test: CompileTimeError
+switch5_negative_test: CompileTimeError
+switch6_test: StaticWarning
+switch7_negative_test: CompileTimeError
+switch_fallthru_test: StaticWarning
+test_negative_test: CompileTimeError
+top_level_non_prefixed_library_test: StaticWarning
+try_catch4_test: StaticWarning
+try_catch5_test: StaticWarning
+type_argument_in_super_type_test: StaticWarning
+typed_selector2_test: StaticWarning
+type_variable_bounds2_test/05: StaticWarning
+type_variable_bounds3_test/00: StaticWarning
+type_variable_identifier_expression_test: StaticWarning
+type_variable_scope2_test: StaticWarning
+unary_plus_negative_test: CompileTimeError
+unbound_getter_test: StaticWarning
+unhandled_exception_negative_test: CompileTimeError
+unresolved_top_level_method_negative_test: CompileTimeError
+vm/type_cast_vm_test: StaticWarning
+vm/type_vm_test: StaticWarning
+void_type_test: StaticWarning
 
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 5d6dc93..a8ebdfd 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -13,9 +13,6 @@
 class_literal_test: fail
 constructor_call_as_function_test/01: fail
 
-# TBF: It is a static warning if the function type of k' is not a subtype of the type of k.
-default_implementation2_test: fail
-
 function_type_alias9_test/00: crash # Issue 11987
 
 # TBF: we should check conflicts not only for methods, but for accessors too
@@ -24,21 +21,8 @@
 method_override7_test/03: Fail # Issue 11496
 method_override8_test/03: Fail # Issue 11496
 
-# TBF: prefix T hidden by type variable T in 'new T.Class()'
-prefix10_negative_test: fail
-
 built_in_identifier_test/none: Fail # Issue 13023
 
-# Invalid constant redirecting factories should cause compile-time error.
-const_types_test/23: Fail # Issue 14306
-const_types_test/24: Fail # Issue 14306
-const_types_test/25: Fail # Issue 14306
-const_types_test/26: Fail # Issue 14306
-const_types_test/27: Fail # Issue 14306
-const_types_test/28: Fail # Issue 14306
-const_types_test/29: Fail # Issue 14306
-const_types_test/30: Fail # Issue 14306
-const_types_test/41: Fail # Issue 14306
 
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
@@ -82,9 +66,6 @@
 # test issue 11579, assignment, no setter
 getter_no_setter_test/none: fail
 
-# test issue 11581, it is not warning to call dynamic
-call_through_getter_test: fail
-
 # test issue 11584, positional arguments cannot be used for named parameters
 compile_time_constant_e_test: fail
 
@@ -106,16 +87,10 @@
 import_combinators_negative_test: fail
 interface_static_non_final_fields_negative_test: fail
 
-# test issue 11698, no setter, so warning, not error
-assign_instance_method_negative_test: fail
-
 # test issue 11918: mixin and const constructor
 const_constructor_mixin_test/01: fail
 const_constructor_mixin3_test/01: fail
 
-# test issue 11958, fails only at runtime
-no_such_method_negative_test: fail
-
 # test issue 11962, it is warning, not error to reference undeclared identifier
 prefix1_negative_test: fail
 prefix2_negative_test: fail
@@ -123,9 +98,6 @@
 prefix5_negative_test: fail
 prefix12_negative_test: fail
 
-# test issue 11963, it is fine to access any property of the dynamic variable
-prefix6_negative_test: fail
-
 # test issue 11964, Any use of a malformed type gives rise to a static warning.
 prefix8_negative_test: fail
 prefix11_negative_test: fail
@@ -167,6 +139,9 @@
 # test issue 13916, Looks as no warning should be in this redirecting factory
 redirecting_factory_infinite_steps_test/01: fail
 
+# test issue  , disallow default values in redirecting factories
+redirecting_factory_default_values_test/none: fail # Issue 14471
+
 # test issue 13956, It is a static type warning if any of the type arguments to k' are not subtypes of the bounds of the corresponding formal type parameters of type.
 default_factory2_test/none: fail
 
@@ -188,16 +163,16 @@
 prefix9_test: fail # test issue 14289
 
 # test issue 14358, E does not implement inherited A.+
-type_promotion_closure_test/none: Fail
-
-# test issue 14362, wrong assumption that dynamic << A
-type_promotion_functions_test/none: Fail
+type_promotion_closure_test/01: Fail
+type_promotion_closure_test/02: Fail
 
 # test issue 14363, "if ((a is B))" has the same effect as "if (a is B)", so no static warning expected
 type_promotion_parameter_test/53: Fail
 
 # test issue 14364, "E<A> << D"
-type_promotion_more_specific_test/08: fail
+type_promotion_more_specific_test/09: Fail
+type_promotion_more_specific_test/10: Fail
+type_promotion_more_specific_test/11: Fail
 
 # test issue 14406, setter for final field was removed from spec
 implicit_setter_test/01: fail
@@ -206,24 +181,293 @@
 # test issue 14410, "typedef C = " is now really illegal syntax
 mixin_illegal_syntax_test/none: fail
 
-#
-# Please don't add new items here.
-# This is section for invalid tests.
-#
 
-[ $compiler == dart2analyzer && $checked ]
-factory1_test/00: fail
-factory1_test/01: fail
-field_type_check2_test/01: fail
-factory_implementation_test/00: fail
-factory_redirection_test/08: fail
-factory_redirection_test/09: fail
-factory_redirection_test/10: fail
-factory_redirection_test/11: fail
-factory_redirection_test/12: fail
-factory_redirection_test/13: fail
-factory_redirection_test/14: fail
-getters_setters2_test/03: fail
-type_variable_bounds3_test/00: fail
-type_variable_bounds2_test/05: fail
+abstract_exact_selector_test: StaticWarning
+abstract_getter_test: StaticWarning
+abstract_object_method_test: StaticWarning
+abstract_runtime_error_test: StaticWarning
+application_negative_test: CompileTimeError
+bad_constructor_test/05: CompileTimeError
+bad_initializer1_negative_test: CompileTimeError
+bad_initializer2_negative_test: CompileTimeError
+bad_named_constructor_negative_test: CompileTimeError
+bad_named_parameters2_test: StaticWarning
+bad_named_parameters_test: StaticWarning
+bit_operations_test: StaticWarning
+body_less_constructor_wrong_arg_negative_test: CompileTimeError
+built_in_identifier_test/01: CompileTimeError
+call_constructor_on_unresolvable_class_test/04: StaticWarning
+call_constructor_on_unresolvable_class_test/05: StaticWarning
+call_constructor_on_unresolvable_class_test/06: StaticWarning
+call_nonexistent_constructor_test: StaticWarning
+checked_null_test: StaticWarning
+checked_setter2_test: StaticWarning
+checked_setter_test: StaticWarning
+closure_type_test: StaticWarning
+compile_time_constant_checked2_test/02: MissingCompileTimeError
+compile_time_constant_checked2_test/03: MissingCompileTimeError
+compile_time_constant_checked2_test/04: MissingCompileTimeError
+compile_time_constant_checked2_test/06: MissingCompileTimeError
+compile_time_constant_checked3_test/02: MissingCompileTimeError
+compile_time_constant_checked3_test/03: MissingCompileTimeError
+compile_time_constant_checked3_test/04: MissingCompileTimeError
+compile_time_constant_checked3_test/06: MissingCompileTimeError
+compile_time_constant_checked_test/02: MissingCompileTimeError
+compile_time_constant_k_test: StaticWarning
+compile_time_constant_o_test: StaticWarning
+const_counter_negative_test: CompileTimeError
+const_objects_are_immutable_test: StaticWarning
+const_optional_args_negative_test: CompileTimeError
+constructor_named_arguments_test/01: StaticWarning
+constructor_redirect1_negative_test: CompileTimeError
+constructor_redirect2_negative_test: CompileTimeError
+constructor_setter_negative_test: CompileTimeError
+constructor_test: StaticWarning
+core_type_check_test: StaticWarning
+crash_6725_test: StaticWarning
+default_factory_library_test: StaticWarning
+default_factory_test: StaticWarning
+div_with_power_of_two2_test: StaticWarning
+double_to_string_as_exponential2_test: StaticWarning
+double_to_string_as_fixed2_test: StaticWarning
+double_to_string_as_precision2_test: StaticWarning
+duplicate_export_negative_test: CompileTimeError
+duplicate_interface_negative_test: CompileTimeError
+dynamic_field_test: StaticWarning
+dynamic_prefix_core_test: StaticWarning
+empty_block_case_test: StaticWarning
+error_stacktrace_test: StaticWarning
+extend_type_parameter2_negative_test: CompileTimeError
+extend_type_parameter_negative_test: CompileTimeError
+external_test/20: StaticWarning
+factory2_negative_test: CompileTimeError
+factory2_test: StaticWarning
+factory3_negative_test: CompileTimeError
+factory3_test: StaticWarning
+factory4_test: StaticWarning
+factory_implementation_test/00: StaticWarning
+factory_negative_test: CompileTimeError
+factory_redirection_test/01: StaticWarning
+factory_redirection_test/03: StaticWarning
+factory_redirection_test/05: StaticWarning
+factory_redirection_test/06: StaticWarning
+factory_return_type_checked_test: StaticWarning
+f_bounded_quantification4_test: StaticWarning
+f_bounded_quantification5_test: StaticWarning
+field1_negative_test: CompileTimeError
+field2_negative_test: CompileTimeError
+field3_negative_test: CompileTimeError
+field4_negative_test: CompileTimeError
+field5_negative_test: CompileTimeError
+field6a_negative_test: CompileTimeError
+field6_negative_test: CompileTimeError
+first_class_types_literals_test: StaticWarning
+function_malformed_result_type_test: StaticWarning
+function_subtype_bound_closure7_test: StaticWarning
+function_subtype_checked0_test: StaticWarning
+function_subtype_closure0_test: StaticWarning
+function_subtype_closure1_test: StaticWarning
+function_subtype_factory1_test: StaticWarning
+function_subtype_inline1_test: StaticWarning
+function_type2_test: StaticWarning
+function_type_parameter2_negative_test: CompileTimeError
+function_type_parameter_negative_test: CompileTimeError
+generic_list_checked_test: StaticWarning
+generics_test: StaticWarning
+generic_test: StaticWarning
+getter_declaration_negative_test: CompileTimeError
+getter_no_setter2_test/01: StaticWarning
+getter_no_setter_test/01: StaticWarning
+illegal_invocation_test/01: CompileTimeError
+implicit_this_test/02: StaticWarning
+implied_interface_test: StaticWarning
+import_combinators_test: StaticWarning
+import_core_prefix_test: StaticWarning
+inferrer_this_access_test: StaticWarning
+inlined_throw_test: StaticWarning
+instance_method2_negative_test: CompileTimeError
+instance_method_negative_test: CompileTimeError
+instanceof3_test: StaticWarning
+instantiate_type_variable_test/01: StaticWarning
+inst_field_initializer1_negative_test: CompileTimeError
+interceptor6_test: StaticWarning
+interface2_negative_test: CompileTimeError
+interface_inherit_field_test: StaticWarning
+interface_injection1_negative_test: CompileTimeError
+interface_injection2_negative_test: CompileTimeError
+interface_static_method_negative_test: CompileTimeError
+invocation_mirror_test: StaticWarning
+is_not_class1_negative_test: CompileTimeError
+is_not_class2_test: StaticWarning
+is_not_class4_negative_test: CompileTimeError
+isnot_malformed_type_test: StaticWarning
+issue1363_test: StaticWarning
+issue1578_negative_test: CompileTimeError
+label2_negative_test: CompileTimeError
+label3_negative_test: CompileTimeError
+label5_negative_test: CompileTimeError
+label6_negative_test: CompileTimeError
+label8_negative_test: CompileTimeError
+label_test: StaticWarning
+library_ambiguous_test/00: StaticWarning
+library_ambiguous_test/01: CompileTimeError
+library_ambiguous_test/02: CompileTimeError
+library_ambiguous_test/03: CompileTimeError
+library_negative_test: CompileTimeError
+list_literal2_negative_test: CompileTimeError
+list_literal4_test: StaticWarning
+list_literal_negative_test: CompileTimeError
+list_test: StaticWarning
+malbounded_type_cast_test: StaticWarning
+malbounded_type_literal_test: StaticWarning
+malformed_type_test: StaticWarning
+map_literal11_test: StaticWarning
+map_literal2_negative_test: CompileTimeError
+map_literal3_test: StaticWarning
+map_literal4_test: StaticWarning
+map_literal6_test: StaticWarning
+map_literal8_test: StaticWarning
+map_literal_negative_test: CompileTimeError
+method_override4_test: StaticWarning
+method_override5_test: StaticWarning
+method_override6_test: StaticWarning
+method_override_test: StaticWarning
+mixin_illegal_syntax_test/13: CompileTimeError
+mixin_typedef_constructor_test: StaticWarning
+mixin_type_parameter2_test: StaticWarning
+mixin_type_parameters_mixin_extends_test: StaticWarning
+mixin_type_parameters_mixin_test: StaticWarning
+mixin_type_parameters_super_extends_test: StaticWarning
+mixin_type_parameters_super_test: StaticWarning
+mixin_with_two_implicit_constructors_test: StaticWarning
+named_constructor_test/01: StaticWarning
+named_constructor_test/03: StaticWarning
+named_parameters2_test: StaticWarning
+named_parameters3_test: StaticWarning
+named_parameters4_test: StaticWarning
+named_parameters_test/01: StaticWarning
+named_parameters_test/02: StaticWarning
+named_parameters_test/03: StaticWarning
+named_parameters_test/04: StaticWarning
+named_parameters_test/05: StaticWarning
+named_parameters_test/06: StaticWarning
+named_parameters_test/07: StaticWarning
+named_parameters_test/08: StaticWarning
+named_parameters_test/09: StaticWarning
+named_parameters_test/10: StaticWarning
+named_parameters_type_test/01: StaticWarning
+new_expression1_negative_test: CompileTimeError
+new_expression2_negative_test: CompileTimeError
+new_expression3_negative_test: CompileTimeError
+non_const_super_negative_test: CompileTimeError
+non_parameterized_factory2_test: StaticWarning
+non_parameterized_factory_test: StaticWarning
+no_such_constructor2_test: StaticWarning
+no_such_method2_test: StaticWarning
+no_such_method_dispatcher_test: StaticWarning
+not_enough_positional_arguments_test/00: StaticWarning
+not_enough_positional_arguments_test/01: CompileTimeError
+not_enough_positional_arguments_test/02: StaticWarning
+not_enough_positional_arguments_test/03: StaticWarning
+not_enough_positional_arguments_test/05: StaticWarning
+not_enough_positional_arguments_test/06: StaticWarning
+not_enough_positional_arguments_test/07: StaticWarning
+number_identifier_test/08: StaticWarning
+number_identifier_test/09: StaticWarning
+on_catch_malformed_type_test: StaticWarning
+operator1_negative_test: CompileTimeError
+operator2_negative_test: CompileTimeError
+operator_equals_test: StaticWarning
+optional_named_parameters_test/01: StaticWarning
+optional_named_parameters_test/02: StaticWarning
+optional_named_parameters_test/03: StaticWarning
+optional_named_parameters_test/04: StaticWarning
+optional_named_parameters_test/05: StaticWarning
+optional_named_parameters_test/06: StaticWarning
+optional_named_parameters_test/07: StaticWarning
+optional_named_parameters_test/08: StaticWarning
+optional_named_parameters_test/09: StaticWarning
+override_field_method1_negative_test: CompileTimeError
+override_field_method2_negative_test: CompileTimeError
+override_field_method4_negative_test: CompileTimeError
+override_field_method5_negative_test: CompileTimeError
+parameter_initializer1_negative_test: CompileTimeError
+parameter_initializer2_negative_test: CompileTimeError
+parameter_initializer3_negative_test: CompileTimeError
+parameter_initializer4_negative_test: CompileTimeError
+parameter_initializer5_negative_test: CompileTimeError
+parameter_initializer6_negative_test: CompileTimeError
+parser_quirks_test: StaticWarning
+part2_test: StaticWarning
+positional_parameters_type_test/01: StaticWarning
+prefix13_negative_test: CompileTimeError
+prefix14_test: StaticWarning
+prefix15_negative_test: CompileTimeError
+prefix15_test: StaticWarning
+prefix16_test: StaticWarning
+prefix17_test: StaticWarning
+prefix18_negative_test: CompileTimeError
+prefix22_test: StaticWarning
+prefix23_test: StaticWarning
+prefix7_negative_test: CompileTimeError
+property_field_override_test: StaticWarning
+redirecting_factory_default_values_test/none: StaticWarning
+redirecting_factory_incompatible_signature_test: StaticWarning
+regress_13494_test: StaticWarning
+return_type_test: StaticWarning
+script1_negative_test: CompileTimeError
+script2_negative_test: CompileTimeError
+setter_declaration2_negative_test: CompileTimeError
+setter_declaration_negative_test: CompileTimeError
+setter_no_getter_call_test/01: CompileTimeError
+source_self_negative_test: CompileTimeError
+static_initializer_type_error_test: StaticWarning
+string_escape4_negative_test: CompileTimeError
+string_interpolate1_negative_test: CompileTimeError
+string_interpolate2_negative_test: CompileTimeError
+string_interpolate_test: StaticWarning
+string_interpolation1_negative_test: CompileTimeError
+string_interpolation2_negative_test: CompileTimeError
+string_interpolation3_negative_test: CompileTimeError
+string_interpolation4_negative_test: CompileTimeError
+string_interpolation5_negative_test: CompileTimeError
+string_interpolation6_negative_test: CompileTimeError
+string_test: StaticWarning
+string_unicode1_negative_test: CompileTimeError
+string_unicode2_negative_test: CompileTimeError
+string_unicode3_negative_test: CompileTimeError
+string_unicode4_negative_test: CompileTimeError
+super_assign_test: StaticWarning
+super_call4_test: StaticWarning
+super_getter_setter_test: StaticWarning
+super_operator_index5_test: StaticWarning
+super_operator_index6_test: StaticWarning
+super_operator_index7_test: StaticWarning
+super_operator_index8_test: StaticWarning
+super_operator_test: StaticWarning
+super_setter_test: StaticWarning
+switch1_negative_test: CompileTimeError
+switch3_negative_test: CompileTimeError
+switch4_negative_test: CompileTimeError
+switch5_negative_test: CompileTimeError
+switch6_test: StaticWarning
+switch7_negative_test: CompileTimeError
+switch_fallthru_test: StaticWarning
+test_negative_test: CompileTimeError
+top_level_non_prefixed_library_test: StaticWarning
+try_catch4_test: StaticWarning
+try_catch5_test: StaticWarning
+type_argument_in_super_type_test: StaticWarning
+typed_selector2_test: StaticWarning
+type_variable_bounds2_test/05: StaticWarning
+type_variable_bounds3_test/00: StaticWarning
+type_variable_identifier_expression_test: StaticWarning
+type_variable_scope2_test: StaticWarning
+unary_plus_negative_test: CompileTimeError
+unbound_getter_test: StaticWarning
+unhandled_exception_negative_test: CompileTimeError
+unresolved_top_level_method_negative_test: CompileTimeError
+vm/type_cast_vm_test: StaticWarning
+vm/type_vm_test: StaticWarning
+void_type_test: StaticWarning
 
diff --git a/tests/language/part_test.dart b/tests/language/part_test.dart
index 740e17c..38d84d8 100644
--- a/tests/language/part_test.dart
+++ b/tests/language/part_test.dart
@@ -2,8 +2,6 @@
 // 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.
 
-// @static-clean
-
 library org.dartlang.test.part_test;
 
 part "part_part.dart";
diff --git a/tests/language/third_test.dart b/tests/language/third_test.dart
index 04fc19a..28c1b0f 100644
--- a/tests/language/third_test.dart
+++ b/tests/language/third_test.dart
@@ -2,7 +2,6 @@
 // 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.
 // Third dart test program.
-// @static-clean
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/type_promotion_closure_test.dart b/tests/language/type_promotion_closure_test.dart
index 5c32a77..bb514da 100644
--- a/tests/language/type_promotion_closure_test.dart
+++ b/tests/language/type_promotion_closure_test.dart
@@ -17,7 +17,7 @@
 class D extends A {
   var d = "d";
 }
-class E implements C, D {
+class E extends D implements C {
   var a = "";
   var b = "";
   var c = "";
diff --git a/tests/language/type_promotion_functions_test.dart b/tests/language/type_promotion_functions_test.dart
index e6cc0c4..daa317d 100644
--- a/tests/language/type_promotion_functions_test.dart
+++ b/tests/language/type_promotion_functions_test.dart
@@ -37,10 +37,11 @@
   b = funcAtoDyn(new B());
   c = funcAtoDyn(new C()); /// 01: static type warning
 
-  if (funcAtoDyn is FuncDynToDyn) { // Promotion: FuncDynToDyn << FuncAtoDyn.
+  if (funcAtoDyn is FuncDynToDyn) {
+    // No promotion: FuncDynToDyn !<< FuncAtoDyn.
     a = funcAtoDyn(new A());
     b = funcAtoDyn(new B());
-    c = funcAtoDyn(new C());
+    c = funcAtoDyn(new C()); /// 11: static type warning
   }
 }
 
@@ -50,11 +51,10 @@
   b = funcDynToDyn(new B());
   c = funcDynToDyn(new C());
 
-  if (funcDynToDyn is FuncAtoDyn) {
-    // No promotion: FuncAtoDyn !<< FuncDynToDyn.
+  if (funcDynToDyn is FuncAtoDyn) { // Promotion: FuncAtoDyn << FuncDynToDyn.
     a = funcDynToDyn(new A());
     b = funcDynToDyn(new B());
-    c = funcDynToDyn(new C());
+    c = funcDynToDyn(new C()); /// 09: static type warning
   }
 
   if (funcDynToDyn is FuncDynToVoid) {
@@ -64,11 +64,10 @@
     c = funcDynToDyn(new C());
   }
 
-  if (funcDynToDyn is FuncDynToA) {
-    // No promotion: FuncDynToA !<< FuncDynToDyn.
+  if (funcDynToDyn is FuncDynToA) { // Promotion: FuncDynToA << FuncDynToDyn.
     a = funcDynToDyn(new A());
     b = funcDynToDyn(new B());
-    c = funcDynToDyn(new C());
+    c = funcDynToDyn(new C()); /// 10: static type warning
   }
 }
 
@@ -98,10 +97,11 @@
   b = funcDynToA(new B());
   c = funcDynToA(new C()); /// 06: static type warning
 
-  if (funcDynToA is FuncDynToDyn) { // Promotion: FuncDynToDyn << FuncDynToA.
+  if (funcDynToA is FuncDynToDyn) {
+    // No promotion: FuncDynToDyn !<< FuncDynToA.
     a = funcDynToA(new A());
     b = funcDynToA(new B());
-    c = funcDynToA(new C());
+    c = funcDynToA(new C()); /// 08: static type warning
   }
 
   if (funcDynToA is FuncDynToVoid) {
diff --git a/tests/language/type_promotion_more_specific_test.dart b/tests/language/type_promotion_more_specific_test.dart
index b672e4b..eb843b6 100644
--- a/tests/language/type_promotion_more_specific_test.dart
+++ b/tests/language/type_promotion_more_specific_test.dart
@@ -61,17 +61,17 @@
   if (d1 is E) { // Promotion: E << D.
     x = d1.e; /// 05: ok
   }
-  if (d1 is E<A>) { // No promotion E<A> << D.
-    int a = d1.d; /// 06: ok
-    String b = d1.d; /// 07: ok
-    x = d1.e; /// 08: static type warning
+  if (d1 is E<A>) { // Promotion: E<A> << D.
+    int a = d1.d; /// 06: static type warning
+    String b = d1.d; /// 07: static type warning
+    x = d1.e; /// 08: ok
   }
 
   D<A> d2 = new E<B>(null);
-  if (d2 is E) { // Promotion: E << D<A>
-    x = d2.e; /// 09: ok
-    int a = d2.e; /// 10: ok
-    String b = d2.e; /// 11: ok
+  if (d2 is E) { // No promotion: E !<< D<A>
+    x = d2.e; /// 09: static type warning
+    int a = d2.e; /// 10: static type warning
+    String b = d2.e; /// 11: static type warning
   }
 
   D<A> d3 = new E<B>(new B());
diff --git a/tests/language/vm/optimized_polymorphic_list_access_test.dart b/tests/language/vm/optimized_polymorphic_list_access_test.dart
new file mode 100644
index 0000000..6ab48f9
--- /dev/null
+++ b/tests/language/vm/optimized_polymorphic_list_access_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, 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.
+// VMOptions=--optimization_counter_threshold=10
+
+import "package:expect/expect.dart";
+
+// Test correct polymorphic inlining of recognized methods like list access.
+
+test(arr) {
+  var r = 0;
+  for (var i = 0; i < 1; ++i) {
+    r += arr[0];
+  }
+  return r;
+}
+
+
+main() {
+  var a = new List<int>(1);
+  a[0] = 0;
+  var b = <int>[0];
+  Expect.equals(0, test(a));
+  Expect.equals(0, test(b));
+  for (var i = 0; i < 20; ++i) test(a);
+  Expect.equals(0, test(a));
+  Expect.equals(0, test(b));
+}
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index bfa469b..52f7602 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -1,3 +1,166 @@
 # Copyright (c) 2012, 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.
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+lib/_chrome/dart2js/chrome_dart2js: CompileTimeError
+lib/collection/hash_set: CompileTimeError
+lib/collection/linked_hash_set: CompileTimeError
+lib/collection/list: CompileTimeError
+lib/convert/codec: CompileTimeError
+lib/html/dart2js/html_dart2js: CompileTimeError
+lib/html/dartium/html_dartium: CompileTimeError
+lib/html/html_common/lists: Pass, CompileTimeError
+lib/indexed_db/dart2js/indexed_db_dart2js: CompileTimeError
+lib/indexed_db/dartium/indexed_db_dartium: CompileTimeError
+lib/_internal/compiler/samples/compile_loop/compile_loop: CompileTimeError
+lib/_internal/compiler/samples/darttags/darttags: CompileTimeError
+lib/_internal/compiler/samples/jsonify/jsonify: CompileTimeError
+lib/_internal/compiler/samples/leap/leap: CompileTimeError
+lib/_internal/compiler/samples/leap/leap_leg: CompileTimeError
+lib/_internal/compiler/samples/leap/request_cache: CompileTimeError
+lib/_internal/dartdoc/bin/dartdoc: CompileTimeError
+lib/_internal/dartdoc/lib/dartdoc: CompileTimeError
+lib/_internal/dartdoc/lib/src/dartdoc/utils: CompileTimeError
+lib/_internal/dartdoc/lib/src/export_map: CompileTimeError
+lib/_internal/dartdoc/lib/universe_serializer: CompileTimeError
+lib/_internal/pub/bin/pub: CompileTimeError
+lib/_internal/pub/lib/src/barback: CompileTimeError
+lib/_internal/pub/lib/src/barback/dart2js_transformer: CompileTimeError
+lib/_internal/pub/lib/src/barback/dart_forwarding_transformer: CompileTimeError
+lib/_internal/pub/lib/src/barback/load_all_transformers: CompileTimeError
+lib/_internal/pub/lib/src/barback/load_transformers: CompileTimeError
+lib/_internal/pub/lib/src/barback/pub_barback_logger: CompileTimeError
+lib/_internal/pub/lib/src/barback/pub_package_provider: CompileTimeError
+lib/_internal/pub/lib/src/barback/rewrite_import_transformer: CompileTimeError
+lib/_internal/pub/lib/src/barback/server: CompileTimeError
+lib/_internal/pub/lib/src/barback/watch_sources: CompileTimeError
+lib/_internal/pub/lib/src/command: Pass, CompileTimeError # Pass necessary, since CompileTimeError is valid for everything in that directory (not only for src/command.dart)
+lib/_internal/pub/lib/src/command/build: CompileTimeError
+lib/_internal/pub/lib/src/command/lish: CompileTimeError
+lib/_internal/pub/lib/src/command/list_package_dirs: CompileTimeError
+lib/_internal/pub/lib/src/command/uploader: CompileTimeError
+lib/_internal/pub/lib/src/dart: CompileTimeError
+lib/_internal/pub/lib/src/directory_tree: CompileTimeError
+lib/_internal/pub/lib/src/entrypoint: CompileTimeError
+lib/_internal/pub/lib/src/http: CompileTimeError
+lib/_internal/pub/lib/src/io: CompileTimeError
+lib/_internal/pub/lib/src/lock_file: CompileTimeError
+lib/_internal/pub/lib/src/oauth2: CompileTimeError
+lib/_internal/pub/lib/src/package: CompileTimeError
+lib/_internal/pub/lib/src/package_graph: CompileTimeError
+lib/_internal/pub/lib/src/pubspec: CompileTimeError
+lib/_internal/pub/lib/src/safe_http_server: CompileTimeError
+lib/_internal/pub/lib/src/sdk: CompileTimeError
+lib/_internal/pub/lib/src/source: CompileTimeError
+lib/_internal/pub/lib/src/source/git: CompileTimeError
+lib/_internal/pub/lib/src/source/hosted: CompileTimeError
+lib/_internal/pub/lib/src/source/path: CompileTimeError
+lib/_internal/pub/lib/src/system_cache: CompileTimeError
+lib/_internal/pub/lib/src/utils: CompileTimeError
+lib/_internal/pub/lib/src/validator/compiled_dartdoc: CompileTimeError
+lib/_internal/pub/lib/src/validator/directory: CompileTimeError
+lib/_internal/pub/lib/src/validator/lib: CompileTimeError
+lib/_internal/pub/lib/src/validator/license: CompileTimeError
+lib/_internal/pub/lib/src/validator/name: CompileTimeError
+lib/_internal/pub/test/descriptor: CompileTimeError
+lib/_internal/pub/test/descriptor/git: CompileTimeError
+lib/_internal/pub/test/descriptor/tar: CompileTimeError
+lib/_internal/pub/test/lish/utils: CompileTimeError
+lib/_internal/pub/test/oauth2/utils: CompileTimeError
+lib/_internal/pub/test/serve/utils: CompileTimeError
+lib/_internal/pub/test/test_pub: CompileTimeError
+lib/_internal/pub/test/validator/utils: CompileTimeError
+lib/js/dartium/js_dartium: CompileTimeError
+lib/svg/dart2js/svg_dart2js: CompileTimeError
+lib/svg/dartium/svg_dartium: CompileTimeError
+lib/typed_data/dart2js/typed_data_dart2js: CompileTimeError
+lib/web_audio/dartium/web_audio_dartium: CompileTimeError
+lib/web_gl/dart2js/web_gl_dart2js: CompileTimeError
+lib/web_gl/dartium/web_gl_dartium: CompileTimeError
+lib/web_sql/dart2js/web_sql_dart2js: CompileTimeError
+lib/web_sql/dartium/web_sql_dartium: CompileTimeError
+
+
+[ $compiler == dart2analyzer ]
+lib/async/async_error: CompileTimeError
+lib/async/deferred_load: CompileTimeError
+lib/async/future: CompileTimeError
+lib/async/future_impl: CompileTimeError
+lib/async/schedule_microtask: CompileTimeError
+lib/async/stream: CompileTimeError
+lib/async/stream_controller: CompileTimeError
+lib/async/stream_impl: CompileTimeError
+lib/async/timer: CompileTimeError
+lib/async/zone: CompileTimeError
+lib/collection/collections: CompileTimeError
+lib/_collection_dev/iterable: CompileTimeError
+lib/_collection_dev/list: CompileTimeError
+lib/_collection_dev/symbol: CompileTimeError
+lib/collection/hash_map: CompileTimeError
+lib/collection/iterable: CompileTimeError
+lib/collection/linked_hash_map: CompileTimeError
+lib/collection/list: CompileTimeError
+lib/collection/queue: CompileTimeError
+lib/collection/splay_tree: CompileTimeError
+lib/convert/ascii: CompileTimeError
+lib/convert/byte_conversion: CompileTimeError
+lib/convert/converter: CompileTimeError
+lib/convert/encoding: CompileTimeError
+lib/convert/html_escape: CompileTimeError
+lib/convert/json: CompileTimeError
+lib/convert/latin1: CompileTimeError
+lib/convert/line_splitter: CompileTimeError
+lib/convert/string_conversion: CompileTimeError
+lib/convert/utf: CompileTimeError
+lib/core/iterable: CompileTimeError
+lib/core/list: CompileTimeError
+lib/core/map: CompileTimeError
+lib/core/print: CompileTimeError
+lib/core/set: CompileTimeError
+lib/core/string: CompileTimeError
+lib/core/symbol: CompileTimeError
+lib/core/uri: CompileTimeError
+lib/html/html_common/conversions: CompileTimeError
+lib/html/html_common/css_class_set: CompileTimeError
+lib/html/html_common/device: CompileTimeError
+lib/html/html_common/filtered_element_list: CompileTimeError
+lib/html/html_common/lists: CompileTimeError
+lib/io/bytes_builder: CompileTimeError
+lib/io/common: CompileTimeError
+lib/io/crypto: CompileTimeError
+lib/io/data_transformer: CompileTimeError
+lib/io/directory: CompileTimeError
+lib/io/directory_impl: CompileTimeError
+lib/io/eventhandler: CompileTimeError
+lib/io/file: CompileTimeError
+lib/io/file_impl: CompileTimeError
+lib/io/file_system_entity: CompileTimeError
+lib/io/http: CompileTimeError
+lib/io/http_date: CompileTimeError
+lib/io/http_headers: CompileTimeError
+lib/io/http_impl: CompileTimeError
+lib/io/http_parser: CompileTimeError
+lib/io/http_session: CompileTimeError
+lib/io/io_service: CompileTimeError
+lib/io/io_sink: CompileTimeError
+lib/io/link: CompileTimeError
+lib/io/options: CompileTimeError
+lib/io/platform: CompileTimeError
+lib/io/platform_impl: CompileTimeError
+lib/io/process: CompileTimeError
+lib/io/secure_server_socket: CompileTimeError
+lib/io/secure_socket: CompileTimeError
+lib/io/socket: CompileTimeError
+lib/io/stdio: CompileTimeError
+lib/io/string_transformer: CompileTimeError
+lib/io/timer_impl: CompileTimeError
+lib/io/websocket: CompileTimeError
+lib/io/websocket_impl: CompileTimeError
+lib/math/point: CompileTimeError
+lib/math/rectangle: CompileTimeError
+lib/utf/utf16: CompileTimeError
+lib/utf/utf32: CompileTimeError
+lib/utf/utf8: CompileTimeError
+lib/utf/utf_stream: CompileTimeError
+
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
deleted file mode 100644
index 4fe235a..0000000
--- a/tests/lib/analyzer/analyze_tests.status
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2012, 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.
-
-# The testing infrastructure is using the dart:io Path and LineTransformer
-# classes.
-standalone/io/skipping_dart2js_compilations_test: Skip # http/dartbug.com/12449
-standalone/io/dependency_graph_test: Skip # http/dartbug.com/12449
-standalone/io/status_file_parser_test: Skip # http/dartbug.com/12449
-
-[ $compiler == dartanalyzer ]
-standalone/javascript_int_overflow_literal_test/01: fail, ok
-
-# https://code.google.com/p/dart/issues/detail?id=11665
-standalone/io/directory_invalid_arguments_test: fail
-standalone/io/file_constructor_test: fail
-standalone/io/http_cookie_date_test: fail
-standalone/io/http_headers_test: fail
-standalone/io/http_parser_test: fail
-standalone/io/process_invalid_arguments_test: fail
-standalone/io/raw_secure_server_socket_argument_test: fail
-standalone/io/secure_socket_argument_test: fail
-standalone/io/stdout_bad_argument_test: fail
-standalone/io/skipping_dart2js_compilations_test: fail
-standalone/io/dependency_graph_test: fail # http/dartbug.com/12449
-standalone/io/web_socket_protocol_processor_test: fail
-standalone/io/test_runner_test: fail
-standalone/package/invalid_uri_test: fail
-standalone/package/package1_test: fail
-standalone/package/package_test: fail
-standalone/typed_data_view_test: fail
-standalone/typed_data_test: fail
-standalone/issue14236_test: Skip # Analyzer can't handle Script snapshots.
-
-
-[ $compiler == dart2analyzer ]
-standalone/javascript_int_overflow_literal_test/01: fail, ok
-
-# https://code.google.com/p/dart/issues/detail?id=11665
-standalone/io/directory_invalid_arguments_test: fail
-standalone/io/file_constructor_test: fail
-standalone/io/http_cookie_date_test: fail
-standalone/io/http_headers_test: fail
-standalone/io/http_parser_test: fail
-standalone/io/process_invalid_arguments_test: fail
-standalone/io/raw_secure_server_socket_argument_test: fail
-standalone/io/secure_socket_argument_test: fail
-standalone/io/stdout_bad_argument_test: fail
-standalone/io/skipping_dart2js_compilations_test: fail
-standalone/io/dependency_graph_test: fail # http/dartbug.com/12449
-standalone/io/web_socket_protocol_processor_test: fail
-standalone/io/test_runner_test: fail
-standalone/package/invalid_uri_test: fail
-standalone/package/package1_test: fail
-standalone/package/package_test: fail
-standalone/typed_data_view_test: fail
-standalone/typed_data_test: fail
-standalone/issue14236_test: Skip # Analyzer can't handle Script snapshots.
diff --git a/tests/lib/analyzer/test_config.dart b/tests/lib/analyzer/test_config.dart
deleted file mode 100644
index d2dcd52..0000000
--- a/tests/lib/analyzer/test_config.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2013, 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.
-
-library analyze_library_test_config;
-
-import 'dart:io';
-import '../../../tools/testing/dart/test_suite.dart';
-
-class AnalyzeLibraryTestSuite extends DartcCompilationTestSuite {
-  final libraries = [ 'async', 'core', 'crypto', 'io', 'isolate', 'json',
-                      'math', 'mirrors', 'typed_data', 'uri',
-                      'utf' ];
-
-  AnalyzeLibraryTestSuite(Map configuration)
-      : super(configuration,
-              'analyze_library',
-              'sdk',
-              [ 'lib' ],
-              ['tests/lib/analyzer/analyze_library.status'],
-              allStaticClean: true);
-
-  bool isTestFile(String filename) {
-    var sep = Platform.pathSeparator;
-    return libraries.any((String lib) {
-      return filename.endsWith('lib$sep$lib$sep$lib.dart');
-    });
-  }
-
-  bool get listRecursively => true;
-}
-
-
-class AnalyzeTestsTestSuite extends DartcCompilationTestSuite {
-  AnalyzeTestsTestSuite(Map configuration)
-      : super(configuration,
-              'analyze_tests',
-              'tests',
-              [ 'standalone' ],
-              ['tests/lib/analyzer/analyze_tests.status'],
-              allStaticClean: true);
-
-  bool isTestFile(String filename) {
-    return filename.endsWith('_test.dart');
-  }
-
-  bool get listRecursively => true;
-}
diff --git a/tests/lib/async/stream_controller_async_test.dart b/tests/lib/async/stream_controller_async_test.dart
index d66a6f1..e3c75b7 100644
--- a/tests/lib/async/stream_controller_async_test.dart
+++ b/tests/lib/async/stream_controller_async_test.dart
@@ -675,6 +675,84 @@
           }
         });
   });
+
+  test("$type-controller-addstream-error-stop", () {
+    // Check that addStream defaults to ending after the first error.
+    var done = expectAsync0((){});
+    StreamController c = broadcast
+        ? new StreamController.broadcast(sync: sync)
+        : new StreamController(sync: sync);
+    Stream stream = asBroadcast ? c.stream.asBroadcastStream() : c.stream;
+    var actual = new Events.capture(stream);
+
+    var source = new Events();
+    source..add(1)..add(2)..error("BAD")..add(3)..error("FAIL")..close();
+
+    var expected = new Events()..add(1)..add(2)..error("BAD")..close();
+    StreamController sourceController = new StreamController();
+    c.addStream(sourceController.stream).then((_) {
+      c.close().then((_) {
+        Expect.listEquals(expected.events, actual.events);
+        done();
+      });
+    });
+
+    source.replay(sourceController);
+  });
+
+  test("$type-controller-addstream-error-forward", () {
+    // Check that addStream with cancelOnError:false passes all data and errors
+    // to the controller.
+    var done = expectAsync0((){});
+    StreamController c = broadcast
+        ? new StreamController.broadcast(sync: sync)
+        : new StreamController(sync: sync);
+    Stream stream = asBroadcast ? c.stream.asBroadcastStream() : c.stream;
+    var actual = new Events.capture(stream);
+
+    var source = new Events();
+    source..add(1)..add(2)..addError("BAD")..add(3)..addError("FAIL")..close();
+
+    StreamController sourceController = new StreamController();
+    c.addStream(sourceController.stream, cancelOnError: false).then((_) {
+      c.close().then((_) {
+        Expect.listEquals(source.events, actual.events);
+        done();
+      });
+    });
+
+    source.replay(sourceController);
+  });
+
+  test("$type-controller-addstream-twice", () {
+    // Using addStream twice on the same stream
+    var done = expectAsync0((){});
+    StreamController c = broadcast
+        ? new StreamController.broadcast(sync: sync)
+        : new StreamController(sync: sync);
+    Stream stream = asBroadcast ? c.stream.asBroadcastStream() : c.stream;
+    var actual = new Events.capture(stream);
+
+    // Streams of five events, throws on 3.
+    Stream s1 = new Stream.fromIterable([1,2,3,4,5])
+                    .map((x) => (x == 3 ? throw x : x));
+    Stream s2 = new Stream.fromIterable([1,2,3,4,5])
+                    .map((x) => (x == 3 ? throw x : x));
+
+    Events expected = new Events();
+    expected..add(1)..add(2)..error(3);
+    expected..add(1)..add(2)..error(3)..add(4)..add(5);
+    expected..close();
+
+    c.addStream(s1).then((_) {
+      c.addStream(s2, cancelOnError: false).then((_) {
+        c.close().then((_) {
+          Expect.listEquals(expected.events, actual.events);
+          done();
+        });
+      });
+    });
+  });
 }
 
 main() {
diff --git a/tests/lib/async/stream_from_iterable_test.dart b/tests/lib/async/stream_from_iterable_test.dart
index ab7d543..ad342fe 100644
--- a/tests/lib/async/stream_from_iterable_test.dart
+++ b/tests/lib/async/stream_from_iterable_test.dart
@@ -73,4 +73,79 @@
       Expect.listEquals(expected.events, actual.events);
     }));
   });
+
+  test("iterable-single-subscription", () {
+    Stream stream = new Stream.fromIterable(iter);
+    stream.listen((x){});
+    Expect.throws(() { stream.listen((x){}); },
+                  (e) => e is StateError);
+  });
+
+  test("regression-14332", () {
+    // Regression test for http://dartbug.com/14332.
+    // This should succeede.
+    var from = new Stream.fromIterable([1,2,3,4,5]);
+
+    var c = new StreamController();
+    var sink = c.sink;
+
+    var done = expectAsync0((){}, count: 2);
+
+    // if this goes first, test failed (hanged). Swapping addStream and toList
+    // made failure go away.
+    sink.addStream(from).then((_) {
+      c.close();
+      done();
+    });
+
+    c.stream.toList().then((x) {
+      Expect.listEquals([1,2,3,4,5], x);
+      done();
+    });
+  });
+
+  test("regression-14334-a", () {
+    var from = new Stream.fromIterable([1,2,3,4,5]);
+
+    // odd numbers as data events, even numbers as error events
+    from = from.map((x) => x.isOdd ? x : throw x);
+
+    var c = new StreamController();
+    var sink = c.sink;
+
+    var done = expectAsync0((){}, count: 2);
+
+    var data = [], errors = [];
+    c.stream.listen(data.add, onError: errors.add, onDone: () {
+      Expect.listEquals([1], data);
+      Expect.listEquals([2], errors);
+      done();
+    });
+    sink.addStream(from).then((_) {
+      c.close();
+      done();
+    });
+  });
+
+  test("regression-14334-b", () {
+    var from = new Stream.fromIterable([1,2,3,4,5]);
+
+    // odd numbers as data events, even numbers as error events
+    from = from.map((x) => x.isOdd ? x : throw x);
+
+    var c = new StreamController();
+
+    var done = expectAsync0((){}, count: 2);
+
+    var data = [], errors = [];
+    c.stream.listen(data.add, onError: errors.add, onDone: () {
+      Expect.listEquals([1, 3, 5], data);
+      Expect.listEquals([2, 4], errors);
+      done();
+    });
+    c.addStream(from, cancelOnError: false).then((_) {
+      c.close();
+      done();
+    });
+  });
 }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index edff803..30c9900 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -19,7 +19,8 @@
 mirrors/closure_mirror_find_in_context_test: Fail # Issue 6490
 mirrors/constructor_kinds_test: RuntimeError # Issue 13799
 mirrors/equality_test/02: RuntimeError # Issue 12333
-mirrors/fake_function_test: RuntimeError # Issue 11612
+mirrors/fake_function_with_call_test: RuntimeError # Issue 11612
+mirrors/fake_function_without_call_test: RuntimeError # Issue 11612
 mirrors/find_in_context_fake_function_test: Fail # Issue 6490
 mirrors/function_type_mirror_test: RuntimeError # Issue 12166
 mirrors/generics_test/01: RuntimeError # Issue 12087
@@ -129,10 +130,6 @@
 mirrors/*: Skip # http://dartbug.com/11511
 async/schedule_microtask6_test: Fail             # Issue 10957 - may be related to issue 10910
 async/schedule_microtask3_test: RuntimeError # Issue 13719: Please triage this failure.
-platform/package_root_test: Fail # Issue 14451
-platform/script_test: Fail # Issue 14451
-platform/isolate_test: Fail # Issue 14451
-
 
 [ $compiler == dart2dart && $minified ]
 json/json_test: Fail                            # Issue 10961
@@ -189,7 +186,6 @@
 mirrors/library_uri_io_test: Skip # Not intended for drt as it uses dart:io.
 mirrors/local_isolate_test: Skip # http://dartbug.com/12188
 async/schedule_microtask6_test: Fail # Issue 10910
-platform/isolate_test: Skip # Issue 14444
 
 [ $compiler == none && $runtime == drt && $mode == debug ]
 mirrors/hierarchy_invariants_test: Pass, Slow # Issue 14449
@@ -206,32 +202,6 @@
 convert/chunked_conversion_utf88_test: Pass, Slow # Issue 12644.
 convert/utf85_test: Pass, Slow # Issue 12644.
 
-[ $compiler == dartanalyzer ]
-mirrors/typedef_test/none: Fail # Issue 13093
-mirrors/generics_test/none: Fail # Issue 13432
-mirrors/generic_bounded_test/none: Fail # Issue 13432
-mirrors/generic_f_bounded_test/none: Fail # Issue 13432
-mirrors/generic_bounded_by_type_parameter_test/none: Fail # Issue 13432
-mirrors/generic_mixin_test/none: Fail # Issue 13432
-mirrors/invoke_named_test/none: Fail # http://dartbug.com/13612
-mirrors/generic_f_bounded_mixin_application_test: Fail # Issue 14116
-mirrors/generic_interface_test/none: Fail # Inexpressible in multitest
-mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
-mirrors/type_variable_owner_test/none: Fail # Issue 14356
-
-[ $compiler == dart2analyzer ]
-mirrors/typedef_test/none: Fail # Issue 13093
-mirrors/generics_test/none: Fail # Issue 13432
-mirrors/generic_bounded_test/none: Fail # Issue 13432
-mirrors/generic_f_bounded_test/none: Fail # Issue 13432
-mirrors/generic_bounded_by_type_parameter_test/none: Fail # Issue 13432
-mirrors/generic_mixin_test/none: Fail # Issue 13432
-mirrors/invoke_named_test/none: Fail # http://dartbug.com/13612
-mirrors/generic_f_bounded_mixin_application_test: Fail # Issue 14116
-mirrors/generic_interface_test/none: Fail # Inexpressible in multitest
-mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
-mirrors/type_variable_owner_test/none: Fail # Issue 14356
-
 [ $compiler == none && $runtime == dartium ]
 async/schedule_microtask5_test: Pass, Timeout # Issue 13719: Please triage this failure.
 async/timer_cancel2_test: Pass, Timeout # Issue 13719: Please triage this failure.
@@ -240,9 +210,46 @@
 # Issue 13921: spawnFunction is not allowed on Dartium's DOM thread.
 async/timer_isolate_test: Fail
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows ]
-platform/uri_test: Fail # Issue 14504
-
 [ ($compiler != none && $runtime != none) || ($compiler == none && ($runtime != dartium && $runtime != drt)) ]
 async/schedule_microtask_test: Fail # Issue 9001, Issue 9002
 
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+async/future_test: StaticWarning
+async/future_value_chain4_test: StaticWarning
+async/schedule_microtask3_test: StaticWarning
+async/stream_controller_async_test: StaticWarning
+async/stream_controller_test: StaticWarning
+async/stream_event_transformed_test: StaticWarning
+async/stream_first_where_test: StaticWarning
+async/stream_from_iterable_test: StaticWarning
+async/stream_join_test: StaticWarning
+async/stream_last_where_test: StaticWarning
+async/stream_single_test: StaticWarning
+async/stream_single_to_multi_subscriber_test: StaticWarning
+async/stream_transform_test: StaticWarning
+async/stream_transformer_from_handlers_test: StaticWarning
+async/stream_transformer_test: StaticWarning
+async/zone_debug_test: StaticWarning
+convert/chunked_conversion1_test: StaticWarning
+convert/chunked_conversion_json_decode1_test: StaticWarning
+math/min_max_test: StaticWarning
+mirrors/equality_test/02: StaticWarning # Issue 14524
+mirrors/function_type_mirror_test: StaticWarning # Issue 14524
+mirrors/generic_f_bounded_mixin_application_test: CompileTimeError # Issue 14116
+mirrors/invoke_named_test: StaticWarning # Issue 14522
+mirrors/mirrors_test: StaticWarning # Issue 14524
+mirrors/private_symbol_test: StaticWarning # Issue 14524
+mirrors/reflect_class_test: StaticWarning # Issue 14524
+mirrors/type_variable_owner_test: StaticWarning # Issue 14524
+mirrors/typedef_test: StaticWarning # Issue 14524
+mirrors/typedef_metadata_test: StaticWarning # Issue 14524
+mirrors/typevariable_mirror_metadata_test: StaticWarning # Issue 14524
+
+mirrors/fake_function_without_call_test: StaticWarning, OK # Implements Function without defining call.
+mirrors/find_in_context_fake_function_test: StaticWarning, OK # Implements Function without defining call.
+mirrors/immutable_collections_test: StaticWarning, OK # Expect failure for any type of Iterable.
+mirrors/inference_and_no_such_method_test: StaticWarning, OK # Expect to trigger noSuchMethod.
+mirrors/library_metadata2_test/01: StaticWarning, OK # Compile-time or run-time
+
+mirrors/invoke_test: StaticWarning, OK # API being removed.
+mirrors/invoke_closurization_test: StaticWarning, OK # API being removed.
diff --git a/tests/lib/mirrors/closure_mirror_import1.dart b/tests/lib/mirrors/closure_mirror_import1.dart
index 2788b94..c0e41da 100644
--- a/tests/lib/mirrors/closure_mirror_import1.dart
+++ b/tests/lib/mirrors/closure_mirror_import1.dart
@@ -2,6 +2,8 @@
 // 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.
 
+library closure_mirror_import1;
+
 export "closure_mirror_import2.dart" show firstGlobalVariableInImport2;
 
 var globalVariableInImport1 = "globalVariableInImport1";
diff --git a/tests/lib/mirrors/closure_mirror_import2.dart b/tests/lib/mirrors/closure_mirror_import2.dart
index a14b7a9..9d09d36 100644
--- a/tests/lib/mirrors/closure_mirror_import2.dart
+++ b/tests/lib/mirrors/closure_mirror_import2.dart
@@ -2,5 +2,7 @@
 // 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.
 
+library closure_mirror_import2;
+
 var firstGlobalVariableInImport2 = "firstGlobalVariableInImport2";
 var secondGlobalVariableInImport2 = "secondGlobalVariableInImport2";
diff --git a/tests/lib/mirrors/delegate_test.dart b/tests/lib/mirrors/delegate_test.dart
index 1f7edc6..b7ea729 100644
--- a/tests/lib/mirrors/delegate_test.dart
+++ b/tests/lib/mirrors/delegate_test.dart
@@ -7,7 +7,6 @@
 import 'dart:mirrors';
 
 import 'package:expect/expect.dart';
-import 'invoke_test.dart';
 
 class C {
   method(a, b, c) => "$a-$b-$c";
diff --git a/tests/lib/mirrors/equality_test.dart b/tests/lib/mirrors/equality_test.dart
index 94c9856..26d1aac 100644
--- a/tests/lib/mirrors/equality_test.dart
+++ b/tests/lib/mirrors/equality_test.dart
@@ -139,9 +139,9 @@
      'thisLibrary.variables[#somePredicate].type'  /// 02: ok
         : thisLibrary.variables[#somePredicate].type},  /// 02: ok
 
-    {'reflectType(Predicate).referent' : reflectType(Predicate).referent,  /// 02: ok
+    {'reflectType(Predicate).referent' : (reflectType(Predicate) as TypedefMirror).referent,  /// 02: ok
      'thisLibrary.variables[#somePredicate].type.referent'  /// 02: ok
-        : thisLibrary.variables[#somePredicate].type.referent},  /// 02: ok
+        : (thisLibrary.variables[#somePredicate].type as TypedefMirror).referent},  /// 02: ok
 
     {'reflectClass(A).typeVariables.single'  /// 02: ok
         : reflectClass(A).typeVariables.single,  /// 02: ok
diff --git a/tests/lib/mirrors/fake_function_test.dart b/tests/lib/mirrors/fake_function_with_call_test.dart
similarity index 100%
rename from tests/lib/mirrors/fake_function_test.dart
rename to tests/lib/mirrors/fake_function_with_call_test.dart
diff --git a/tests/lib/mirrors/fake_function_without_call_test.dart b/tests/lib/mirrors/fake_function_without_call_test.dart
new file mode 100644
index 0000000..da6bd59
--- /dev/null
+++ b/tests/lib/mirrors/fake_function_without_call_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, 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.
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class MultiArityFunction implements Function {
+  noSuchMethod(Invocation msg) {
+    if (msg.memberName != #call) return super.noSuchMethod(msg);
+    return msg.positionalArguments.join(",");
+  }
+}
+
+main() {
+  var f = new MultiArityFunction();
+
+  Expect.isTrue(f is Function);
+  Expect.equals('a', f('a'));
+  Expect.equals('a,b', f('a', 'b'));
+  Expect.equals('a,b,c', f('a', 'b', 'c'));
+  Expect.equals('a', Function.apply(f, ['a']));
+  Expect.equals('a,b', Function.apply(f, ['a', 'b']));
+  Expect.equals('a,b,c', Function.apply(f, ['a', 'b', 'c']));
+  Expect.throws(() => f.foo('a', 'b', 'c'),
+                (e) => e is NoSuchMethodError);
+
+  ClosureMirror cm = reflect(f);
+  Expect.isTrue(cm is ClosureMirror);
+  Expect.equals('a', cm.apply(['a']).reflectee);
+  Expect.equals('a,b', cm.apply(['a', 'b']).reflectee);
+  Expect.equals('a,b,c', cm.apply(['a', 'b', 'c']).reflectee);
+
+  MethodMirror mm = cm.function;
+  Expect.isNull(mm);
+
+  ClassMirror km = cm.type;
+  Expect.equals(reflectClass(MultiArityFunction), km);
+}
diff --git a/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart b/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
index 2391aa5..c6f2b16 100644
--- a/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
+++ b/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
@@ -8,61 +8,61 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class Super<T, R extends T> {}
 
 class Fixed extends Super<num, int> {}
-class Generic<X, Y> extends Super<X, Y> {}
+class Generic<X, Y> extends Super<X, Y> {}  /// 02: static type warning
 class Malbounded extends Super<num, String> {} /// 01: static type warning
 
 main() {
   ClassMirror superDecl = reflectClass(Super);
   ClassMirror superOfNumAndInt = reflectClass(Fixed).superclass;
-  ClassMirror genericDecl = reflectClass(Generic);
-  ClassMirror superOfXAndY = genericDecl.superclass;
-  ClassMirror genericOfNumAndDouble = reflect(new Generic<num, double>()).type;
-  ClassMirror superOfNumAndDouble = genericOfNumAndDouble.superclass;
+  ClassMirror genericDecl = reflectClass(Generic);  /// 02: continued
+  ClassMirror superOfXAndY = genericDecl.superclass;  /// 02: continued
+  ClassMirror genericOfNumAndDouble = reflect(new Generic<num, double>()).type;  /// 02: continued
+  ClassMirror superOfNumAndDouble = genericOfNumAndDouble.superclass;  /// 02: continued
   ClassMirror genericOfNumAndBool = reflect(new Generic<num, bool>()).type;  /// 02: static type warning, dynamic type error
   ClassMirror superOfNumAndBool = genericOfNumAndBool.superclass;  /// 02: continued
   ClassMirror superOfNumAndString = reflectClass(Malbounded).superclass;  /// 01: continued
 
   Expect.isTrue(superDecl.isOriginalDeclaration);
   Expect.isFalse(superOfNumAndInt.isOriginalDeclaration);
-  Expect.isTrue(genericDecl.isOriginalDeclaration);
-  Expect.isFalse(superOfXAndY.isOriginalDeclaration); 
-  Expect.isFalse(genericOfNumAndDouble.isOriginalDeclaration);
-  Expect.isFalse(superOfNumAndDouble.isOriginalDeclaration);
+  Expect.isTrue(genericDecl.isOriginalDeclaration);  /// 02: continued
+  Expect.isFalse(superOfXAndY.isOriginalDeclaration);   /// 02: continued
+  Expect.isFalse(genericOfNumAndDouble.isOriginalDeclaration);  /// 02: continued
+  Expect.isFalse(superOfNumAndDouble.isOriginalDeclaration);  /// 02: continued
   Expect.isFalse(genericOfNumAndBool.isOriginalDeclaration);  /// 02: continued
   Expect.isFalse(superOfNumAndBool.isOriginalDeclaration);  /// 02: continued
   Expect.isFalse(superOfNumAndString.isOriginalDeclaration);  /// 01: continued
 
   TypeVariableMirror tFromSuper = superDecl.typeVariables[0];
   TypeVariableMirror rFromSuper = superDecl.typeVariables[1];
-  TypeVariableMirror xFromGeneric = genericDecl.typeVariables[0];
-  TypeVariableMirror yFromGeneric = genericDecl.typeVariables[1];
+  TypeVariableMirror xFromGeneric = genericDecl.typeVariables[0];  /// 02: continued
+  TypeVariableMirror yFromGeneric = genericDecl.typeVariables[1];  /// 02: continued
 
   Expect.equals(reflectClass(Object), tFromSuper.upperBound);
   Expect.equals(tFromSuper, rFromSuper.upperBound);
-  Expect.equals(reflectClass(Object), xFromGeneric.upperBound);
-  Expect.equals(reflectClass(Object), yFromGeneric.upperBound);
+  Expect.equals(reflectClass(Object), xFromGeneric.upperBound);  /// 02: continued
+  Expect.equals(reflectClass(Object), yFromGeneric.upperBound);  /// 02: continued
 
   typeParameters(superDecl, [#T, #R]);
   typeParameters(superOfNumAndInt, [#T, #R]);
-  typeParameters(genericDecl, [#X, #Y]);
-  typeParameters(superOfXAndY, [#T, #R]);
-  typeParameters(genericOfNumAndDouble, [#X, #Y]);
-  typeParameters(superOfNumAndDouble, [#T, #R]);
+  typeParameters(genericDecl, [#X, #Y]);  /// 02: continued
+  typeParameters(superOfXAndY, [#T, #R]);  /// 02: continued
+  typeParameters(genericOfNumAndDouble, [#X, #Y]);  /// 02: continued
+  typeParameters(superOfNumAndDouble, [#T, #R]);  /// 02: continued
   typeParameters(genericOfNumAndBool, [#X, #Y]);  /// 02: continued
   typeParameters(superOfNumAndBool, [#T, #R]);  /// 02: continued
   typeParameters(superOfNumAndString, [#T, #R]);  /// 01: continued
 
   typeArguments(superDecl, []);
   typeArguments(superOfNumAndInt, [reflectClass(num), reflectClass(int)]);
-  typeArguments(genericDecl, []);
-  typeArguments(superOfXAndY, [xFromGeneric, yFromGeneric]);
-  typeArguments(genericOfNumAndDouble, [reflectClass(num), reflectClass(double)]);
-  typeArguments(superOfNumAndDouble, [reflectClass(num), reflectClass(double)]);
+  typeArguments(genericDecl, []);  /// 02: continued
+  typeArguments(superOfXAndY, [xFromGeneric, yFromGeneric]);  /// 02: continued
+  typeArguments(genericOfNumAndDouble, [reflectClass(num), reflectClass(double)]);  /// 02: continued
+  typeArguments(superOfNumAndDouble, [reflectClass(num), reflectClass(double)]);  /// 02: continued
   typeArguments(genericOfNumAndBool, [reflectClass(num), reflectClass(bool)]);  /// 02: continued
   typeArguments(superOfNumAndBool, [reflectClass(num), reflectClass(bool)]);  /// 02: continued
   typeArguments(superOfNumAndString, [reflectClass(num), reflectClass(String)]);  /// 01: continued
diff --git a/tests/lib/mirrors/generic_bounded_test.dart b/tests/lib/mirrors/generic_bounded_test.dart
index c59d3af..dec144a 100644
--- a/tests/lib/mirrors/generic_bounded_test.dart
+++ b/tests/lib/mirrors/generic_bounded_test.dart
@@ -8,57 +8,57 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class Super<T extends num> {}
 
 class Fixed extends Super<int> {}
-class Generic<R> extends Super<R> {}
+class Generic<R> extends Super<R> {}  /// 02: static type warning
 class Malbounded extends Super<String> {} /// 01: static type warning
 
 main() {
   ClassMirror superDecl = reflectClass(Super);
   ClassMirror superOfInt = reflectClass(Fixed).superclass;
-  ClassMirror genericDecl = reflectClass(Generic);
-  ClassMirror superOfR = genericDecl.superclass;
-  ClassMirror genericOfDouble = reflect(new Generic<double>()).type;
-  ClassMirror superOfDouble = genericOfDouble.superclass;
+  ClassMirror genericDecl = reflectClass(Generic);  /// 02: continued
+  ClassMirror superOfR = genericDecl.superclass;  /// 02: continued
+  ClassMirror genericOfDouble = reflect(new Generic<double>()).type;  /// 02: continued
+  ClassMirror superOfDouble = genericOfDouble.superclass;  /// 02: continued
   ClassMirror genericOfBool = reflect(new Generic<bool>()).type;  /// 02: static type warning, dynamic type error
   ClassMirror superOfBool = genericOfBool.superclass;  /// 02: continued
   ClassMirror superOfString = reflectClass(Malbounded).superclass;  /// 01: continued
 
   Expect.isTrue(superDecl.isOriginalDeclaration);
   Expect.isFalse(superOfInt.isOriginalDeclaration);
-  Expect.isTrue(genericDecl.isOriginalDeclaration);
-  Expect.isFalse(superOfR.isOriginalDeclaration);
-  Expect.isFalse(genericOfDouble.isOriginalDeclaration);
-  Expect.isFalse(superOfDouble.isOriginalDeclaration);
+  Expect.isTrue(genericDecl.isOriginalDeclaration);  /// 02: continued
+  Expect.isFalse(superOfR.isOriginalDeclaration);  /// 02: continued
+  Expect.isFalse(genericOfDouble.isOriginalDeclaration);  /// 02: continued
+  Expect.isFalse(superOfDouble.isOriginalDeclaration);  /// 02: continued
   Expect.isFalse(genericOfBool.isOriginalDeclaration);  /// 02: continued
   Expect.isFalse(superOfBool.isOriginalDeclaration);  /// 02: continued
   Expect.isFalse(superOfString.isOriginalDeclaration);  /// 01: continued
 
   TypeVariableMirror tFromSuper = superDecl.typeVariables.single;
-  TypeVariableMirror rFromGeneric = genericDecl.typeVariables.single;
+  TypeVariableMirror rFromGeneric = genericDecl.typeVariables.single;  /// 02: continued
 
   Expect.equals(reflectClass(num), tFromSuper.upperBound);
-  Expect.equals(reflectClass(Object), rFromGeneric.upperBound);
+  Expect.equals(reflectClass(Object), rFromGeneric.upperBound);  /// 02: continued
 
   typeParameters(superDecl, [#T]);
   typeParameters(superOfInt, [#T]);
-  typeParameters(genericDecl, [#R]);
-  typeParameters(superOfR, [#T]);
-  typeParameters(genericOfDouble, [#R]);
-  typeParameters(superOfDouble, [#T]);
+  typeParameters(genericDecl, [#R]);  /// 02: continued
+  typeParameters(superOfR, [#T]);  /// 02: continued
+  typeParameters(genericOfDouble, [#R]);  /// 02: continued
+  typeParameters(superOfDouble, [#T]);  /// 02: continued
   typeParameters(genericOfBool, [#R]);  /// 02: continued
   typeParameters(superOfBool, [#T]);  /// 02: continued
   typeParameters(superOfString, [#T]);  /// 01: continued
 
   typeArguments(superDecl, []);
   typeArguments(superOfInt, [reflectClass(int)]);
-  typeArguments(genericDecl, []);
-  typeArguments(superOfR, [rFromGeneric]);
-  typeArguments(genericOfDouble, [reflectClass(double)]);
-  typeArguments(superOfDouble, [reflectClass(double)]);
+  typeArguments(genericDecl, []);  /// 02: continued
+  typeArguments(superOfR, [rFromGeneric]);  /// 02: continued
+  typeArguments(genericOfDouble, [reflectClass(double)]);  /// 02: continued
+  typeArguments(superOfDouble, [reflectClass(double)]);  /// 02: continued
   typeArguments(genericOfBool, [reflectClass(bool)]);  /// 02: continued
   typeArguments(superOfBool, [reflectClass(bool)]);  /// 02: continued
   typeArguments(superOfString, [reflectClass(String)]);  /// 01: continued
diff --git a/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart b/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart
index 5d38af6..334913d 100644
--- a/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart
+++ b/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class Collection<C> {}
 class Serializable<S> {}
diff --git a/tests/lib/mirrors/generic_f_bounded_test.dart b/tests/lib/mirrors/generic_f_bounded_test.dart
index 96148cc..00e4fbb 100644
--- a/tests/lib/mirrors/generic_f_bounded_test.dart
+++ b/tests/lib/mirrors/generic_f_bounded_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class Magnitude<T> {}
 class Real extends Magnitude<Real> {}
diff --git a/tests/lib/mirrors/generic_function_typedef_test.dart b/tests/lib/mirrors/generic_function_typedef_test.dart
index e0968f7..3f6853b 100644
--- a/tests/lib/mirrors/generic_function_typedef_test.dart
+++ b/tests/lib/mirrors/generic_function_typedef_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 typedef bool NonGenericPredicate(num n);
 typedef bool GenericPredicate<T>(T t);
diff --git a/tests/lib/mirrors/generic_interface_test.dart b/tests/lib/mirrors/generic_interface_test.dart
index 8a2b9a0..03e3f11 100644
--- a/tests/lib/mirrors/generic_interface_test.dart
+++ b/tests/lib/mirrors/generic_interface_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class Interface<T> {}
 class Bounded<S extends num> {}
@@ -17,7 +17,7 @@
 class Generic<R> implements Interface<R> {}
 
 class Bienbounded implements Bounded<int> {}
-class Malbounded implements Bounded<String> {}
+class Malbounded implements Bounded<String> {}  /// 01: static type warning
 class FBounded implements Interface<FBounded> {}
 
 class Mixin {}
@@ -37,7 +37,7 @@
   ClassMirror interfaceOfBool = reflect(new Generic<bool>()).type.superinterfaces.single;
 
   ClassMirror boundedOfInt = reflectClass(Bienbounded).superinterfaces.single;
-  ClassMirror boundedOfString = reflectClass(Malbounded).superinterfaces.single;
+  ClassMirror boundedOfString = reflectClass(Malbounded).superinterfaces.single;  /// 01: continued
   ClassMirror interfaceOfFBounded = reflectClass(FBounded).superinterfaces.single;
   
   ClassMirror interfaceOfInt2 = reflectClass(FixedMixinApplication).superinterfaces.single;
@@ -55,7 +55,7 @@
   Expect.isFalse(interfaceOfR.isOriginalDeclaration);
   Expect.isFalse(interfaceOfBool.isOriginalDeclaration);
   Expect.isFalse(boundedOfInt.isOriginalDeclaration);
-  Expect.isFalse(boundedOfString.isOriginalDeclaration);
+  Expect.isFalse(boundedOfString.isOriginalDeclaration);  /// 01: continued
   Expect.isFalse(interfaceOfFBounded.isOriginalDeclaration);
   Expect.isFalse(interfaceOfInt2.isOriginalDeclaration);
   Expect.isFalse(interfaceOfX.isOriginalDeclaration);
@@ -84,7 +84,7 @@
   typeParameters(interfaceOfR, [#T]);
   typeParameters(interfaceOfBool, [#T]);
   typeParameters(boundedOfInt, [#S]);
-  typeParameters(boundedOfString, [#S]);
+  typeParameters(boundedOfString, [#S]);  /// 01: continued
   typeParameters(interfaceOfFBounded, [#T]);
   typeParameters(interfaceOfInt2, [#T]);
   typeParameters(interfaceOfX, [#T]);
@@ -97,14 +97,14 @@
   typeArguments(boundedDecl, []);
   typeArguments(interfaceOfInt, [reflectClass(int)]);
   typeArguments(interfaceOfR, [rFromGeneric]);
-  typeArguments(interfaceOfBool, [reflectClass(bool)]);  /// 01: ok
+  typeArguments(interfaceOfBool, [reflectClass(bool)]);
   typeArguments(boundedOfInt, [reflectClass(int)]);
-  typeArguments(boundedOfString, [reflectClass(String)]);
+  typeArguments(boundedOfString, [reflectClass(String)]);  /// 01: continued
   typeArguments(interfaceOfFBounded, [reflectClass(FBounded)]);
   typeArguments(interfaceOfInt2, [reflectClass(int)]);
   typeArguments(interfaceOfX, [xFromGenericMixinApplication]);
-  typeArguments(interfaceOfDouble, [reflectClass(double)]);  /// 01: ok
+  typeArguments(interfaceOfDouble, [reflectClass(double)]);
   typeArguments(interfaceOfInt3, [reflectClass(int)]);
   typeArguments(interfaceOfY, [yFromGenericClass]);
-  typeArguments(interfaceOfDouble2, [reflectClass(double)]);  /// 01: ok
+  typeArguments(interfaceOfDouble2, [reflectClass(double)]);
 }
diff --git a/tests/lib/mirrors/generic_mixin_applications_test.dart b/tests/lib/mirrors/generic_mixin_applications_test.dart
index 1cc0acf..aac6e28 100644
--- a/tests/lib/mirrors/generic_mixin_applications_test.dart
+++ b/tests/lib/mirrors/generic_mixin_applications_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class Super<S> {}
 class Mixin<M> {}
diff --git a/tests/lib/mirrors/generic_mixin_test.dart b/tests/lib/mirrors/generic_mixin_test.dart
index c359d78..22e00ef 100644
--- a/tests/lib/mirrors/generic_mixin_test.dart
+++ b/tests/lib/mirrors/generic_mixin_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class Super<S> {}
 class Mixin<M> {}
diff --git a/tests/lib/mirrors/generics_helper.dart b/tests/lib/mirrors/generics_helper.dart
new file mode 100644
index 0000000..a8907c4
--- /dev/null
+++ b/tests/lib/mirrors/generics_helper.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, 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.
+
+library generics_helper;
+
+import 'package:expect/expect.dart';
+
+typeParameters(mirror, parameterNames) {
+  Expect.listEquals(parameterNames,
+                    mirror.typeVariables.map((v) => v.simpleName).toList());
+}
+
+typeArguments(mirror, argumentMirrors) {
+  Expect.listEquals(argumentMirrors, mirror.typeArguments);
+}
diff --git a/tests/lib/mirrors/generics_special_types_test.dart b/tests/lib/mirrors/generics_special_types_test.dart
new file mode 100644
index 0000000..49f72ec
--- /dev/null
+++ b/tests/lib/mirrors/generics_special_types_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, 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.
+
+library test.generics_special_types;
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+main() {
+  TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
+  Expect.isTrue(dynamicMirror.isOriginalDeclaration);
+  Expect.equals(dynamicMirror, dynamicMirror.originalDeclaration);
+  Expect.listEquals([], dynamicMirror.typeVariables);
+  Expect.listEquals([], dynamicMirror.typeArguments);
+
+  TypeMirror voidMirror = currentMirrorSystem().voidType;
+  Expect.isTrue(voidMirror.isOriginalDeclaration);
+  Expect.equals(voidMirror, voidMirror.originalDeclaration);
+  Expect.listEquals([], voidMirror.typeVariables);
+  Expect.listEquals([], voidMirror.typeArguments);
+
+  TypeMirror dynamicMirror2 = reflectType(dynamic);
+  Expect.equals(dynamicMirror, dynamicMirror2);
+  Expect.isTrue(dynamicMirror2.isOriginalDeclaration);
+  Expect.equals(dynamicMirror2, dynamicMirror2.originalDeclaration);
+  Expect.listEquals([], dynamicMirror2.typeVariables);
+  Expect.listEquals([], dynamicMirror2.typeArguments);
+}
diff --git a/tests/lib/mirrors/generics_test.dart b/tests/lib/mirrors/generics_test.dart
index 8eb63ee..ec2d49a 100644
--- a/tests/lib/mirrors/generics_test.dart
+++ b/tests/lib/mirrors/generics_test.dart
@@ -7,13 +7,14 @@
 import 'dart:mirrors';
 
 import 'package:expect/expect.dart';
+import 'generics_helper.dart';
 
 class A<T> {}
 class Z<T> {}
-class B extends A {}            // Same as class B extends A<dynamic>.
-class C extends A
-<num, int> // TODO(zarah): Should be "01: static warning".
-{} // Same as class C extends A<dynamic>.
+class B extends A {}
+class C
+    extends A<num, int>  /// 01: static type warning
+    {}
 class D extends A<int> {}
 class E<S> extends A<S> {}
 class F<R> extends A<int> {}
@@ -21,15 +22,6 @@
 class H<A,B,C> {}
 class I extends G {}
 
-typeParameters(mirror, parameterNames) {
-  Expect.listEquals(parameterNames,
-                    mirror.typeVariables.map((v) => v.simpleName).toList());
-}
-
-typeArguments(mirror, argumentMirrors) {
-  Expect.listEquals(argumentMirrors, mirror.typeArguments);
-}
-
 main() {
   // Declarations.
   typeParameters(reflectClass(A), [#T]);
@@ -75,7 +67,7 @@
 
   // Instantiations.
   typeParameters(reflect(new A<num>()).type, [#T]);
-  typeParameters(reflect(new B<num>()).type, []);
+  typeParameters(reflect(new B()).type, []);
   typeParameters(reflect(new C()).type, []);
   typeParameters(reflect(new D()).type, []);
   typeParameters(reflect(new E()).type, [#S]);
diff --git a/tests/lib/mirrors/method_mirror_properties_test.dart b/tests/lib/mirrors/method_mirror_properties_test.dart
index 834871f..950a2a8 100644
--- a/tests/lib/mirrors/method_mirror_properties_test.dart
+++ b/tests/lib/mirrors/method_mirror_properties_test.dart
@@ -12,7 +12,7 @@
 int get topGetter => _x;
 void set topSetter(x) { _x = x; }
 
-class AbstractC {
+abstract class AbstractC {
 
   AbstractC();
 
@@ -21,7 +21,7 @@
   set priv(value);
 }
 
-class C extends AbstractC {
+abstract class C extends AbstractC {
 
   static foo() {}
 
diff --git a/tests/lib/mirrors/method_mirror_returntype_test.dart b/tests/lib/mirrors/method_mirror_returntype_test.dart
index cd525bb..be55156 100644
--- a/tests/lib/mirrors/method_mirror_returntype_test.dart
+++ b/tests/lib/mirrors/method_mirror_returntype_test.dart
@@ -21,20 +21,20 @@
 main() {
   MethodMirror mm;
 
-  mm = reflect(intFunc).function;
+  mm = (reflect(intFunc) as ClosureMirror).function;
   Expect.equals(true, mm.returnType is TypeMirror);
   Expect.equals(#int, mm.returnType.simpleName);
   Expect.equals(true, mm.returnType.owner is LibraryMirror);
 
-  mm = reflect(dynamicFunc1).function;
+  mm = (reflect(dynamicFunc1) as ClosureMirror).function;
   Expect.equals(true, mm.returnType is TypeMirror);
   Expect.equals(#dynamic, mm.returnType.simpleName);
 
-  mm = reflect(dynamicFunc2).function;
+  mm = (reflect(dynamicFunc2) as ClosureMirror).function;
   Expect.equals(true, mm.returnType is TypeMirror);
   Expect.equals(#dynamic, mm.returnType.simpleName);
 
-  mm = reflect(voidFunc).function;
+  mm = (reflect(voidFunc) as ClosureMirror).function;
   Expect.equals(true, mm.returnType is TypeMirror);
   Expect.equals(const Symbol("void"), mm.returnType.simpleName);
 
diff --git a/tests/lib/mirrors/method_mirror_source_test.dart b/tests/lib/mirrors/method_mirror_source_test.dart
index 094e36d..2507915 100644
--- a/tests/lib/mirrors/method_mirror_source_test.dart
+++ b/tests/lib/mirrors/method_mirror_source_test.dart
@@ -7,11 +7,14 @@
 import "package:expect/expect.dart";
 
 expectSource(Mirror mirror, String source) {
+  MethodMirror methodMirror;
   if (mirror is ClosureMirror) {
-    mirror = mirror.function;
+    methodMirror = mirror.function;
+  } else {
+    methodMirror = mirror as MethodMirror;
   }
-  Expect.isTrue(mirror is MethodMirror);
-  Expect.equals(mirror.source, source);
+  Expect.isTrue(methodMirror is MethodMirror);
+  Expect.equals(methodMirror.source, source);
 }
 
 foo1() {}
diff --git a/tests/lib/mirrors/mixin_members_test.dart b/tests/lib/mirrors/mixin_members_test.dart
index 470f647..12c4192 100644
--- a/tests/lib/mirrors/mixin_members_test.dart
+++ b/tests/lib/mirrors/mixin_members_test.dart
@@ -10,7 +10,7 @@
 
 import 'stringify.dart';
 
-class Fooer {
+abstract class Fooer {
   foo1();
 }
 
diff --git a/tests/lib/mirrors/parameter_metadata_test.dart b/tests/lib/mirrors/parameter_metadata_test.dart
index f27a149..fdb1fc6 100644
--- a/tests/lib/mirrors/parameter_metadata_test.dart
+++ b/tests/lib/mirrors/parameter_metadata_test.dart
@@ -19,15 +19,15 @@
 }
 
 class B {
-  B.foo(int x);
-  factory B.bar(@m3 @m2 int z, x){}
+  B.foo(int x) {}
+  factory B.bar(@m3 @m2 int z, x) {}
 
-  baz(@m1 final int x, @m2 int y, @m3 final int z);
-  qux(int x, [@m3 @m2 @m1 int y= 3 + 1]);
-  quux(int x, {String str: "foo"});
-  corge({@m1 int x: 3 * 17, @m2 String str: "bar"});
+  baz(@m1 final int x, @m2 int y, @m3 final int z) {}
+  qux(int x, [@m3 @m2 @m1 int y= 3 + 1]) {}
+  quux(int x, {String str: "foo"}) {}
+  corge({@m1 int x: 3 * 17, @m2 String str: "bar"}) {}
 
-  set x(@m2 final value);
+  set x(@m2 final value) {}
 }
 
 main() {
@@ -38,18 +38,18 @@
   checkMetadata(cm.constructors[#B.bar].parameters[0], [m3, m2]);
   checkMetadata(cm.constructors[#B.bar].parameters[1], []);
 
-  checkMetadata(cm.members[#baz].parameters[0], [m1]);
-  checkMetadata(cm.members[#baz].parameters[1], [m2]);
-  checkMetadata(cm.members[#baz].parameters[2], [m3]);
+  checkMetadata(cm.methods[#baz].parameters[0], [m1]);
+  checkMetadata(cm.methods[#baz].parameters[1], [m2]);
+  checkMetadata(cm.methods[#baz].parameters[2], [m3]);
 
-  checkMetadata(cm.members[#qux].parameters[0], []);
-  checkMetadata(cm.members[#qux].parameters[1], [m3, m2, m1]);
+  checkMetadata(cm.methods[#qux].parameters[0], []);
+  checkMetadata(cm.methods[#qux].parameters[1], [m3, m2, m1]);
 
-  checkMetadata(cm.members[#quux].parameters[0], []);
-  checkMetadata(cm.members[#quux].parameters[1], []);
+  checkMetadata(cm.methods[#quux].parameters[0], []);
+  checkMetadata(cm.methods[#quux].parameters[1], []);
 
-  checkMetadata(cm.members[#corge].parameters[0], [m1]);
-  checkMetadata(cm.members[#corge].parameters[1], [m2]);
+  checkMetadata(cm.methods[#corge].parameters[0], [m1]);
+  checkMetadata(cm.methods[#corge].parameters[1], [m2]);
 
-  checkMetadata(cm.members[const Symbol('x=')].parameters[0], [m2]);
+  checkMetadata(cm.setters[const Symbol('x=')].parameters[0], [m2]);
 }
diff --git a/tests/lib/mirrors/private_symbol_test.dart b/tests/lib/mirrors/private_symbol_test.dart
index 52eaa09..7624531 100644
--- a/tests/lib/mirrors/private_symbol_test.dart
+++ b/tests/lib/mirrors/private_symbol_test.dart
@@ -109,7 +109,7 @@
   Expect.equals(#_F, tdm.simpleName);
   Expect.equals('_F', MirrorSystem.getName(tdm.simpleName));
 
-  ParameterMirror pm = cm.members[#m].parameters[0];
+  ParameterMirror pm = (cm.members[#m] as MethodMirror).parameters[0];
   Expect.equals(#_p, pm.simpleName);
   Expect.equals('_p', MirrorSystem.getName(pm.simpleName));
 
diff --git a/tests/lib/mirrors/reflect_class_test.dart b/tests/lib/mirrors/reflect_class_test.dart
index c556ba8..f1dff09 100644
--- a/tests/lib/mirrors/reflect_class_test.dart
+++ b/tests/lib/mirrors/reflect_class_test.dart
@@ -14,8 +14,5 @@
   Expect.throws(() => reflectClass(dynamic), expectedError);
   Expect.throws(() => reflectClass(1), expectedError);
   Expect.throws(() => reflectClass("string"), expectedError);
-
-  // reflectClass() on a function type should fail once typedefs are represented
-  // by TypedefMirrors instead of ClassMirrors.
-  // Expect.throws(() => reflectClass(FooFunction), expectedError);
+  Expect.throws(() => reflectClass(FooFunction), expectedError);
 }
diff --git a/tests/lib/mirrors/reflected_type_test.dart b/tests/lib/mirrors/reflected_type_test.dart
index df4e578..70ebcf3 100644
--- a/tests/lib/mirrors/reflected_type_test.dart
+++ b/tests/lib/mirrors/reflected_type_test.dart
@@ -9,8 +9,8 @@
 import 'package:expect/expect.dart';
 
 class A<T> {}
-class B extends A {}            // Same as class B extends A<dynamic>.
-class C extends A<num, int> {}  // Same as class C extends A<dynamic>.
+class B extends A {}
+class C extends A<num, int> {}  /// 01: static type warning
 class D extends A<int> {}
 class E<S> extends A<S> {}
 class F<R> extends A<int> {}
@@ -33,7 +33,7 @@
   // Declarations.
   expectReflectedType(reflectClass(A), null);
   expectReflectedType(reflectClass(B), B);
-  expectReflectedType(reflectClass(C), C);
+  expectReflectedType(reflectClass(C), C);  /// 01: continued
   expectReflectedType(reflectClass(D), D);
   expectReflectedType(reflectClass(E), null);
   expectReflectedType(reflectClass(F), null);
@@ -43,7 +43,7 @@
    // Instantiations.
   expectReflectedType(reflect(new A()).type, new A().runtimeType);
   expectReflectedType(reflect(new B()).type, new B().runtimeType);
-  expectReflectedType(reflect(new C()).type, new C().runtimeType);
+  expectReflectedType(reflect(new C()).type, new C().runtimeType);  /// 01: continued
   expectReflectedType(reflect(new D()).type, new D().runtimeType);
   expectReflectedType(reflect(new E()).type, new E().runtimeType);
   expectReflectedType(reflect(new F()).type, new F().runtimeType);
@@ -51,16 +51,15 @@
   expectReflectedType(reflect(new H()).type, new H().runtimeType);
 
   expectReflectedType(reflect(new A<num>()).type, new A<num>().runtimeType);
-  expectReflectedType(reflect(new B<num>()).type.superclass,
-                      new A<dynamic>().runtimeType);
-  expectReflectedType(reflect(new C<num>()).type.superclass,
-                      new A<dynamic>().runtimeType);
-  expectReflectedType(reflect(new D<num>()).type.superclass,
-                      new A<int>().runtimeType);
+  expectReflectedType(reflect(new B<num>()).type.superclass,  /// 02: static type warning
+                      new A<dynamic>().runtimeType);          /// 02: continued
+  expectReflectedType(reflect(new C<num>()).type.superclass,  /// 01: continued
+                      new A<dynamic>().runtimeType);          /// 01: continued
+  expectReflectedType(reflect(new D<num>()).type.superclass,  /// 03: static type warning
+                      new A<int>().runtimeType);              /// 03: continued
   expectReflectedType(reflect(new E<num>()).type, new E<num>().runtimeType);
-  // TODO(rmacnak): This requires some work to compute.
-  // expectReflectedType(reflect(new E<num>()).type.superclass,
-  //                     new A<num>().runtimeType);
+  expectReflectedType(reflect(new E<num>()).type.superclass,
+                      new A<num>().runtimeType);
   expectReflectedType(reflect(new F<num>()).type.superclass,
                       new A<int>().runtimeType);
   expectReflectedType(reflect(new F<num>()).type, new F<num>().runtimeType);
diff --git a/tests/lib/mirrors/type_argument_is_type_variable_test.dart b/tests/lib/mirrors/type_argument_is_type_variable_test.dart
index d503fed..abada7f 100644
--- a/tests/lib/mirrors/type_argument_is_type_variable_test.dart
+++ b/tests/lib/mirrors/type_argument_is_type_variable_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'generics_test.dart';
+import 'generics_helper.dart';
 
 class SuperSuper<SS> {}
 class Super<S> extends SuperSuper<S> {}
diff --git a/tests/lib/platform/environment_test.dart b/tests/lib/platform/environment_test.dart
deleted file mode 100644
index 3d2da6a..0000000
--- a/tests/lib/platform/environment_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem != null) {
-    expect(platform.environment, new isInstanceOf<Map<String, String>>());
-  } else {
-    expect(platform.environment, isNull);
-  }
-}
-
diff --git a/tests/lib/platform/executable_arguments_test.dart b/tests/lib/platform/executable_arguments_test.dart
deleted file mode 100644
index 8fbf032..0000000
--- a/tests/lib/platform/executable_arguments_test.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  expect(platform.executableArguments is List<String>, true);
-}
diff --git a/tests/lib/platform/executable_test.dart b/tests/lib/platform/executable_test.dart
deleted file mode 100644
index fee4539..0000000
--- a/tests/lib/platform/executable_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem != null) {
-    expect(platform.executable, contains('dart'));
-  } else {
-    expect(platform.executable, isNull);
-  }
-}
-
diff --git a/tests/lib/platform/import_test.dart b/tests/lib/platform/import_test.dart
deleted file mode 100644
index fcd326f..0000000
--- a/tests/lib/platform/import_test.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform";
-
-void main() {
-}
diff --git a/tests/lib/platform/isolate_test.dart b/tests/lib/platform/isolate_test.dart
deleted file mode 100644
index b53f088..0000000
--- a/tests/lib/platform/isolate_test.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "dart:isolate";
-import "package:unittest/unittest.dart";
-
-sendReceive(SendPort port, msg) {
-  var response = new ReceivePort();
-  port.send([msg, response.sendPort]);
-  return response.first;
-}
-
-main() {
-  test("platform in isolate", () {
-    var response = new ReceivePort();
-    Isolate.spawn(f, response.sendPort);
-    response.first.then(expectAsync1((sendPort) {
-      expect(sendReceive(sendPort, "platform.executable"),
-            completion(platform.executable));
-      if (platform.script != null) {
-        expect(sendReceive(sendPort, "platform.script").then((s) => s.path),
-              completion(endsWith('tests/lib/platform/isolate_test.dart')));
-      }
-      expect(sendReceive(sendPort, "platform.packageRoot"),
-            completion(platform.packageRoot));
-      expect(sendReceive(sendPort, "platform.executableArguments"),
-            completion(platform.executableArguments));
-    }));
-  });
-}
-
-void f(initialReplyTo) {
-  var port = new ReceivePort();
-  initialReplyTo.send(port.sendPort);
-  int count = 0;
-  port.listen((msg) {
-    var data = msg[0];
-    var replyTo = msg[1];
-    if (data == "platform.executable") {
-      replyTo.send(platform.executable);
-    }
-    if (data == "platform.script") {
-      replyTo.send(platform.script);
-    }
-    if (data == "platform.packageRoot") {
-      replyTo.send(platform.packageRoot);
-    }
-    if (data == "platform.executableArguments") {
-      replyTo.send(platform.executableArguments);
-    }
-    count++;
-    if (count == 4) {
-      port.close();
-    }
-  });
-}
diff --git a/tests/lib/platform/local_hostname_test.dart b/tests/lib/platform/local_hostname_test.dart
deleted file mode 100644
index 2095ce0..0000000
--- a/tests/lib/platform/local_hostname_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem != null) {
-    expect(platform.localHostname, new isInstanceOf<String>());
-    expect(platform.localHostname, isNot(''));
-  } else {
-    expect(platform.localHostname, isNull);
-  }
-}
diff --git a/tests/lib/platform/number_of_processors_test.dart b/tests/lib/platform/number_of_processors_test.dart
deleted file mode 100644
index 043914d..0000000
--- a/tests/lib/platform/number_of_processors_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem != null) {
-    expect(platform.numberOfProcessors, isPositive);
-  } else {
-    expect(platform.numberOfProcessors, isNull);
-  }
-}
diff --git a/tests/lib/platform/operating_system_test.dart b/tests/lib/platform/operating_system_test.dart
deleted file mode 100644
index b121833..0000000
--- a/tests/lib/platform/operating_system_test.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem != null) {
-    expect(platform.operatingSystem,
-           isIn(['linux', 'macos', 'windows', 'android']));
-  }
-}
diff --git a/tests/lib/platform/package_root_test.dart b/tests/lib/platform/package_root_test.dart
deleted file mode 100644
index 7d5de6a..0000000
--- a/tests/lib/platform/package_root_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem != null) {
-    expect(platform.packageRoot is String, true);
-    expect(platform.packageRoot, isNot(''));
-  } else {
-    expect(platform.packageRoot, isNull);
-  }
-}
diff --git a/tests/lib/platform/path_separator_test.dart b/tests/lib/platform/path_separator_test.dart
deleted file mode 100644
index 2a7a595..0000000
--- a/tests/lib/platform/path_separator_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem == 'windows') {
-    expect(platform.pathSeparator, '\\');
-  } else {
-    expect(platform.pathSeparator, isIn(['/', null]));
-  }
-}
diff --git a/tests/lib/platform/script_test.dart b/tests/lib/platform/script_test.dart
deleted file mode 100644
index e7ce111..0000000
--- a/tests/lib/platform/script_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
-  if (platform.operatingSystem != null) {
-    expect(platform.script.path,
-           endsWith('tests/lib/platform/script_test.dart'));
-  } else {
-    expect(platform.script, isNull);
-  }
-}
diff --git a/tests/lib/platform/uri_test.dart b/tests/lib/platform/uri_test.dart
deleted file mode 100644
index bca7b6d..0000000
--- a/tests/lib/platform/uri_test.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2013, 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.
-
-import "package:expect/expect.dart";
-import "dart:platform" as platform;
-
-main() {
-  if (platform.operatingSystem == 'windows') {
-    Expect.equals("a\\b", Uri.parse("a/b").toFilePath());
-    Expect.equals("a\\b\\", Uri.parse("a/b/").toFilePath());
-    Expect.equals("a b", Uri.parse("a%20b").toFilePath());
-    Expect.equals("\\a b", Uri.parse("file:///a%20b").toFilePath());
-    Expect.equals("\\a\\b", Uri.parse("file:///a/b").toFilePath());
-    Expect.equals("C:\\", Uri.parse("file:///C:").toFilePath());
-    Expect.equals("C:\\", Uri.parse("file:///C:/").toFilePath());
-    Expect.equals("\\\\host\\a\\b", Uri.parse("file://host/a/b").toFilePath());
-
-    Expect.equals("a\\b", new Uri.file("a/b").toFilePath());
-    Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
-    Expect.equals("\\a\\b", new Uri.file("/a/b").toFilePath());
-    Expect.equals("\\a\\b", new Uri.file("\\a\\b").toFilePath());
-    Expect.equals("\\a\\b", new Uri.file("\\a/b").toFilePath());
-    Expect.equals("\\a\\b", new Uri.file("/a\\b").toFilePath());
-  } else {
-    Expect.equals("a/b", Uri.parse("a/b").toFilePath());
-    Expect.equals("a/b/", Uri.parse("a/b/").toFilePath());
-    Expect.equals("a b", Uri.parse("a%20b").toFilePath());
-    Expect.equals("/a b", Uri.parse("file:///a%20b").toFilePath());
-    Expect.equals("/a/b", Uri.parse("file:///a/b").toFilePath());
-    Expect.equals("/C:", Uri.parse("file:///C:").toFilePath());
-    Expect.equals("/C:/", Uri.parse("file:///C:/").toFilePath());
-    Expect.throws(() => Uri.parse("file://host/a/b").toFilePath(),
-                  (e) => e is UnsupportedError);
-
-    Expect.equals("a/b", new Uri.file("a/b").toFilePath());
-    Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
-  }
-}
diff --git a/tests/standalone/io/directory_list_pause_test.dart b/tests/standalone/io/directory_list_pause_test.dart
index 9bb7d47e..c2beb00 100644
--- a/tests/standalone/io/directory_list_pause_test.dart
+++ b/tests/standalone/io/directory_list_pause_test.dart
@@ -43,6 +43,55 @@
   });
 }
 
+
+void testPauseResumeCancelList() {
+  asyncStart();
+  // TOTAL should be bigger the our directory listing buffer.
+  const int TOTAL = 128;
+  Directory.systemTemp.createTemp('dart_directory_list_pause').then((d) {
+    for (int i = 0; i < TOTAL; i++) {
+      new Directory("${d.path}/$i").createSync();
+      new File("${d.path}/$i/file").createSync();
+    }
+    var subscription;
+    subscription = d.list(recursive: true).listen((entity) {
+      subscription.pause();
+      subscription.resume();
+      void close() {
+        d.deleteSync(recursive: true);
+        asyncEnd();
+      }
+      var future = subscription.cancel();
+      if (future != null) {
+        future.whenComplete(close);
+      } else {
+        close();
+      }
+    }, onDone: () {
+      Expect.fail('the stream was canceled, onDone should not happend');
+    });
+  });
+}
+
+void testListIsEmpty() {
+  asyncStart();
+  // TOTAL should be bigger the our directory listing buffer.
+  const int TOTAL = 128;
+  Directory.systemTemp.createTemp('dart_directory_list_pause').then((d) {
+    for (int i = 0; i < TOTAL; i++) {
+      new Directory("${d.path}/$i").createSync();
+      new File("${d.path}/$i/file").createSync();
+    }
+    d.list(recursive: true).isEmpty.then((empty) {
+      Expect.isFalse(empty);
+      d.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
 void main() {
   testPauseList();
+  testPauseResumeCancelList();
+  testListIsEmpty();
 }
diff --git a/tests/standalone/io/file_system_watcher_test.dart b/tests/standalone/io/file_system_watcher_test.dart
index 4540b60..e76f719 100644
--- a/tests/standalone/io/file_system_watcher_test.dart
+++ b/tests/standalone/io/file_system_watcher_test.dart
@@ -7,11 +7,12 @@
 
 import "package:async_helper/async_helper.dart";
 import "package:expect/expect.dart";
+import "package:path/path.dart";
 
 
 void testWatchCreateFile() {
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
-  var file = new File(dir.path + '/file');
+  var file = new File(join(dir.path, 'file'));
 
   var watcher = dir.watch();
 
@@ -20,6 +21,7 @@
   sub = watcher.listen((event) {
     if (event is FileSystemCreateEvent &&
         event.path.endsWith('file')) {
+      Expect.isFalse(event.isDirectory);
       asyncEnd();
       sub.cancel();
       dir.deleteSync(recursive: true);
@@ -33,9 +35,34 @@
 }
 
 
+void testWatchCreateDir() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var subdir = new Directory(join(dir.path, 'dir'));
+
+  var watcher = dir.watch();
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event is FileSystemCreateEvent &&
+        event.path.endsWith('dir')) {
+      Expect.isTrue(event.isDirectory);
+      asyncEnd();
+      sub.cancel();
+      dir.deleteSync(recursive: true);
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  subdir.createSync();
+}
+
+
 void testWatchModifyFile() {
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
-  var file = new File(dir.path + '/file');
+  var file = new File(join(dir.path, 'file'));
   file.createSync();
 
   var watcher = dir.watch();
@@ -60,7 +87,7 @@
 
 void testWatchMoveFile() {
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
-  var file = new File(dir.path + '/file');
+  var file = new File(join(dir.path, 'file'));
   file.createSync();
 
   var watcher = dir.watch();
@@ -82,13 +109,13 @@
     throw e;
   });
 
-  file.renameSync(dir.path + '/file2');
+  file.renameSync(join(dir.path, 'file2'));
 }
 
 
 void testWatchDeleteFile() {
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
-  var file = new File(dir.path + '/file');
+  var file = new File(join(dir.path, 'file'));
   file.createSync();
 
   var watcher = dir.watch();
@@ -112,6 +139,9 @@
 
 
 void testWatchDeleteDir() {
+  // Windows keeps the directory handle open, even though it's deleted. It'll
+  // be flushed completely, once the watcher is closed as well.
+  if (Platform.isWindows) return;
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
   var watcher = dir.watch(events: 0);
 
@@ -131,7 +161,7 @@
 
 void testWatchOnlyModifyFile() {
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
-  var file = new File(dir.path + '/file');
+  var file = new File(join(dir.path, 'file'));
 
   var watcher = dir.watch(events: FileSystemEvent.MODIFY);
 
@@ -155,8 +185,8 @@
 
 void testMultipleEvents() {
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
-  var file = new File(dir.path + '/file');
-  var file2 = new File(dir.path + '/file2');
+  var file = new File(join(dir.path, 'file'));
+  var file2 = new File(join(dir.path, 'file2'));
 
   var watcher = dir.watch();
 
@@ -204,9 +234,9 @@
     Expect.throws(() => dir.watch(recursive: true));
     return;
   }
-  var dir2 = new Directory(dir.path + '/dir');
+  var dir2 = new Directory(join(dir.path, 'dir'));
   dir2.createSync();
-  var file = new File(dir.path + '/dir/file');
+  var file = new File(join(dir.path, 'dir/file'));
 
   var watcher = dir.watch(recursive: true);
 
@@ -229,9 +259,9 @@
 
 void testWatchNonRecursive() {
   var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
-  var dir2 = new Directory(dir.path + '/dir');
+  var dir2 = new Directory(join(dir.path, 'dir'));
   dir2.createSync();
-  var file = new File(dir.path + '/dir/file');
+  var file = new File(join(dir.path, 'dir/file'));
 
   var watcher = dir.watch(recursive: false);
 
@@ -256,9 +286,24 @@
 }
 
 
+void testWatchNonExisting() {
+  // MacOS allows listening on non-existing paths.
+  if (Platform.isMacOS) return;
+  asyncStart();
+  new Directory('__some_none_existing_dir__').watch()
+    .listen((_) {
+      Expect.fail('unexpected error');
+    }, onError: (e) {
+      asyncEnd();
+      Expect.isTrue(e is FileSystemException);
+    });
+}
+
+
 void main() {
   if (!FileSystemEntity.isWatchSupported) return;
   testWatchCreateFile();
+  testWatchCreateDir();
   testWatchModifyFile();
   testWatchMoveFile();
   testWatchDeleteFile();
@@ -266,4 +311,5 @@
   testWatchOnlyModifyFile();
   testMultipleEvents();
   testWatchNonRecursive();
+  testWatchNonExisting();
 }
diff --git a/tests/standalone/io/http_headers_state_test.dart b/tests/standalone/io/http_headers_state_test.dart
index 42e5384..deeb9cd 100644
--- a/tests/standalone/io/http_headers_state_test.dart
+++ b/tests/standalone/io/http_headers_state_test.dart
@@ -21,13 +21,23 @@
         response.headers.add("X-Response-Header", "value");
         if (body != null) {
           response.write(body);
+          // Cannot change state or reason when data has been sent.
+          Expect.throws(() => response.statusCode = 200,
+                        (e) => e is StateError);
+          Expect.throws(() => response.reasonPhrase = "OK",
+                        (e) => e is StateError);
           // Cannot mutate response headers when data has been sent.
-          Expect.throws(() => request.headers.add("X-Request-Header", "value2"),
+          Expect.throws(() => response.headers.add("X-Request-Header", "value2"),
                         (e) => e is HttpException);
         }
         response..close();
-        // Cannot mutate response headers when data has been sent.
-        Expect.throws(() => request.headers.add("X-Request-Header", "value3"),
+        // Cannot change state or reason after connection is closed.
+        Expect.throws(() => response.statusCode = 200,
+                      (e) => e is StateError);
+        Expect.throws(() => response.reasonPhrase = "OK",
+                      (e) => e is StateError);
+        // Cannot mutate response headers after connection is closed.
+        Expect.throws(() => response.headers.add("X-Request-Header", "value3"),
                       (e) => e is HttpException);
       });
     });
diff --git a/tests/standalone/io/uri_platform_test.dart b/tests/standalone/io/uri_platform_test.dart
index 586e7f3..cc67760 100644
--- a/tests/standalone/io/uri_platform_test.dart
+++ b/tests/standalone/io/uri_platform_test.dart
@@ -4,9 +4,39 @@
 
 import "package:expect/expect.dart";
 import "dart:io";
-import "dart:platform" as platform;
 
 main() {
+  if (Platform.isWindows) {
+    Expect.equals("a\\b", Uri.parse("a/b").toFilePath());
+    Expect.equals("a\\b\\", Uri.parse("a/b/").toFilePath());
+    Expect.equals("a b", Uri.parse("a%20b").toFilePath());
+    Expect.equals("\\a b", Uri.parse("file:///a%20b").toFilePath());
+    Expect.equals("\\a\\b", Uri.parse("file:///a/b").toFilePath());
+    Expect.equals("C:\\", Uri.parse("file:///C:").toFilePath());
+    Expect.equals("C:\\", Uri.parse("file:///C:/").toFilePath());
+    Expect.equals("\\\\host\\a\\b", Uri.parse("file://host/a/b").toFilePath());
+
+    Expect.equals("a\\b", new Uri.file("a/b").toFilePath());
+    Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("/a/b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("\\a\\b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("\\a/b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("/a\\b").toFilePath());
+  } else {
+    Expect.equals("a/b", Uri.parse("a/b").toFilePath());
+    Expect.equals("a/b/", Uri.parse("a/b/").toFilePath());
+    Expect.equals("a b", Uri.parse("a%20b").toFilePath());
+    Expect.equals("/a b", Uri.parse("file:///a%20b").toFilePath());
+    Expect.equals("/a/b", Uri.parse("file:///a/b").toFilePath());
+    Expect.equals("/C:", Uri.parse("file:///C:").toFilePath());
+    Expect.equals("/C:/", Uri.parse("file:///C:/").toFilePath());
+    Expect.throws(() => Uri.parse("file://host/a/b").toFilePath(),
+                  (e) => e is UnsupportedError);
+
+    Expect.equals("a/b", new Uri.file("a/b").toFilePath());
+    Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
+  }
+
   Expect.equals(Uri.base,
-                new Uri.file(Directory.current.path + platform.pathSeparator));
+                new Uri.file(Directory.current.path + Platform.pathSeparator));
 }
diff --git a/tests/standalone/issue14236_source.dart b/tests/standalone/issue14236_source.dart
index edb18a8..9b89cef 100644
--- a/tests/standalone/issue14236_source.dart
+++ b/tests/standalone/issue14236_source.dart
@@ -9,9 +9,9 @@
 // test.
 
 library test.issue14236;
-import 'dart:isolate';
+import "dart:isolate";
 import "package:expect/expect.dart";
-import "package:async_helper/async_helper.dart"; 
+import "package:async_helper/async_helper.dart";
 
 /*
 test(SendPort replyTo) {
diff --git a/tests/standalone/issue14236_test.dart b/tests/standalone/issue14236_test.dart
index 7790795..303eea6 100644
--- a/tests/standalone/issue14236_test.dart
+++ b/tests/standalone/issue14236_test.dart
Binary files differ
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 0b2316a..a293719 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -10,25 +10,10 @@
 package/invalid_uri_test: Fail, OK # CompileTimeErrors intentionally
 
 [ $runtime == vm && $system == windows ]
-io/file_system_watcher_test: Pass, Timeout # Issue 13228
 io/platform_test: Pass, Fail # Issue 14399
 
 [ $runtime == vm ]
 package/package_isolate_test: Fail # Issue 12474
-vmservice/isolate_bad_class_test: Skip # Issue 14448
-vmservice/isolate_bad_object_test: Skip # Issue 14448
-vmservice/isolate_class_field_test: Skip # Issue 14448
-vmservice/isolate_class_test: Skip # Issue 14448
-vmservice/isolate_code_test: Skip # Issue 14448
-vmservice/isolate_echo_test: Skip # Issue 14448
-vmservice/isolate_function_test: Skip # Issue 14448
-vmservice/isolate_library_test: Skip # Issue 14448
-vmservice/isolate_list_test: Skip # Issue 14448
-vmservice/isolate_stacktrace_command_test: Skip # Issue 14448
-vmservice/multiple_isolate_list_test: Skip # Issue 14448
-vmservice/unknown_command_test: Skip # Issue 14448
-vmservice/unknown_isolate_command_test: Skip # Issue 14448
-
 
 [ $runtime == vm && $checked ]
 # These tests have type errors on purpose.
@@ -93,7 +78,6 @@
 
 [ $compiler == dart2analyzer ]
 javascript_int_overflow_literal_test/01: fail, ok
-package/package_isolate_test: fail # issue 11647
 issue14236_test: Skip # Analyzer can't handle Script snapshots.
 
 # test issue https://code.google.com/p/dart/issues/detail?id=11518
@@ -135,6 +119,7 @@
 oom_error_stacktrace_test: RuntimeError, OK # (OOM on JS may produce a stacktrace).
 vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
 issue14236_test: Skip # dart2js does not deal with Script snapshots.
+io/platform_test: Pass, CompileTimeError # Issue 14603
 
 [ $compiler == dart2js && $jscl ]
 assert_test: RuntimeError, OK # Assumes unspecified fields on the AssertionError.
@@ -184,3 +169,17 @@
 [ $compiler == none && $runtime == dartium ]
 javascript_int_overflow_literal_test/01: Fail # Issue 13719: Please triage this failure.
 javascript_int_overflow_test: Fail # Issue 13719: Please triage this failure.
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+io/directory_invalid_arguments_test: StaticWarning
+io/process_invalid_arguments_test: StaticWarning
+io/raw_secure_server_socket_argument_test: StaticWarning
+io/secure_socket_argument_test: StaticWarning
+io/skipping_dart2js_compilations_test: CompileTimeError, StaticWarning
+io/stdout_bad_argument_test: StaticWarning
+io/test_runner_test: CompileTimeError, StaticWarning
+package/package1_test: StaticWarning
+package/package_test: StaticWarning
+typed_data_test: StaticWarning
+typed_data_view_test: StaticWarning
+
diff --git a/tests/standalone/vmservice/isolate_class_test.dart b/tests/standalone/vmservice/isolate_class_test.dart
index 9650443..086ae5e 100644
--- a/tests/standalone/vmservice/isolate_class_test.dart
+++ b/tests/standalone/vmservice/isolate_class_test.dart
@@ -28,10 +28,10 @@
   onRequestCompleted(Map reply) {
     Expect.equals('Library', reply['type']);
     Expect.equals('isolate_stacktrace_command_script', reply['name']);
-    Expect.equals(1, reply['classes'].length);
-    Expect.equals('@Class', reply['classes'][0]['type']);
-    Expect.equals('C', reply['classes'][0]['name']);
-    _classId = reply['classes'][0]['id'];
+    Expect.equals(2, reply['classes'].length);
+    Expect.equals('@Class', reply['classes'][1]['type']);
+    Expect.equals('C', reply['classes'][1]['name']);
+    _classId = reply['classes'][1]['id'];
   }
 }
 
diff --git a/tests/standalone/vmservice/test_helper.dart b/tests/standalone/vmservice/test_helper.dart
index 8157648..8e2b46c 100644
--- a/tests/standalone/vmservice/test_helper.dart
+++ b/tests/standalone/vmservice/test_helper.dart
@@ -18,13 +18,13 @@
       client = new HttpClient();
 
   Future makeRequest() {
+    print('** GET: $uri');
     return client.getUrl(uri)
       .then((HttpClientRequest request) => request.close())
       .then((HttpClientResponse response) {
         return response
             .fold(new BytesBuilder(), (b, d) => b..add(d))
             .then((builder) {
-              print('** GET: $uri');
               return _requestCompleted(builder.takeBytes(), response);
             });
       }).catchError((error) {
diff --git a/tests/utils/dart2js_test.dart b/tests/utils/dart2js_test.dart
index f7786fb..74d890cd 100644
--- a/tests/utils/dart2js_test.dart
+++ b/tests/utils/dart2js_test.dart
@@ -4,10 +4,6 @@
 
 // Test to ensure that dart2js is free of warnings.
 
-// Test annotation to let the test framework know that this file
-// should analyze without any warnings.
-// @static-clean
-
 import '../../sdk/lib/_internal/compiler/implementation/dart2js.dart'
     as dart2js;
 
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 95eb2c3..be55dba 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -16,8 +16,3 @@
 [ $compiler == none && $runtime == dartium ]
 dart2js_test: Skip # Uses dart:io.
 
-[ $compiler == dartanalyzer ]
-dart2js_test: fail # dart2js issue 13919 - excluded setter for final var
-
-[ $compiler == dart2analyzer ]
-dart2js_test: fail # dart2js issue 13919 - excluded setter for final var
diff --git a/tools/VERSION b/tools/VERSION
index 260a0bd..12474f0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 8
-BUILD 7
+BUILD 8
 PATCH 0
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index 947beed..bee7334 100644
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -99,9 +99,9 @@
     return '/'.join([self.editor_directory(revision),
       self.editor_zipfilename(system, arch)])
 
-  def editor_installer_zipfilepath(self, revision, system, arch, extension):
+  def editor_installer_filepath(self, revision, system, arch, extension):
     return '/'.join([self.editor_directory(revision),
-      self.editor_installer_zipfilename(system, arch, extension)])
+      self.editor_installer_filename(system, arch, extension)])
 
   def sdk_zipfilepath(self, revision, system, arch, mode):
     return '/'.join([self.sdk_directory(revision),
@@ -148,8 +148,8 @@
     return 'darteditor-%s-%s.zip' % (
         SYSTEM_RENAMES[system], ARCH_RENAMES[arch])
 
-  def editor_installer_zipfilename(self, system, arch, extension):
-    assert extension in ['dmg']
+  def editor_installer_filename(self, system, arch, extension):
+    assert extension in ['dmg', 'msi']
     return 'darteditor-installer-%s-%s.%s' % (
         SYSTEM_RENAMES[system], ARCH_RENAMES[arch], extension)
 
diff --git a/tools/copy_dart.py b/tools/copy_dart.py
index 9918e2e..6bd5725 100755
--- a/tools/copy_dart.py
+++ b/tools/copy_dart.py
@@ -106,11 +106,6 @@
           or dirname(lib).endswith('dom/src')):
         continue
 
-      if lib.endswith('json/json.dart'):
-        # TODO(jmesserly): Dartium interprets "json.dart" as "dart_json.dart",
-        # so we need that add dart_json.dart here. This is hacky.
-        lib = lib.replace('json.dart', 'dart_json.dart')
-
       library = parseLibrary(lib)
 
       # Ensure output directory exists
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index c6c83c6..0982ad2 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -203,7 +203,7 @@
                   join('html', 'dart2js'), join('html', 'dartium'),
                   join('html', 'html_common'),
                   join('indexed_db', 'dart2js'), join('indexed_db', 'dartium'),
-                  'js', 'math', 'mirrors', 'platform', 'typed_data',
+                  'js', 'math', 'mirrors', 'typed_data',
                   join('svg', 'dart2js'), join('svg', 'dartium'),
                   'utf',
                   join('web_audio', 'dart2js'), join('web_audio', 'dartium'),
diff --git a/tools/create_windows_installer.py b/tools/create_windows_installer.py
new file mode 100644
index 0000000..6566a5b
--- /dev/null
+++ b/tools/create_windows_installer.py
@@ -0,0 +1,387 @@
+#!/usr/bin/env python

+#

+# Copyright (c) 2013, 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.

+

+# A script to generate a windows installer for the editor bundle.

+# As input the script takes a zip file, a version and the location

+# to store the resulting msi file in.

+#

+# Usage: ./tools/create_windows_installer.py --version <version>

+#            --zip_file_location <zip_file> --msi_location <output>

+#            [--wix_bin <wix_bin_location>]

+#            [--print_wxs]

+#

+# This script assumes that wix is either in path or passed in as --wix_bin.

+# You can get wix from http://wixtoolset.org/.

+

+import optparse

+import os

+import shutil

+import subprocess

+import sys

+import utils

+import zipfile

+

+# This should _never_ change, please don't change this value.

+UPGRADE_CODE = '7bacdc33-2e76-4f36-a206-ea58220c0b44'

+

+# The content of the xml

+xml_content = []

+

+# The components we want to add to our feature.

+feature_components = []

+

+# Indentation level, each level is indented 2 spaces

+current_indentation = 0

+

+def GetOptions():

+  options = optparse.OptionParser(usage='usage: %prog [options]')

+  options.add_option("--zip_file_location",

+      help='Where the zip file including the editor is located.')

+  options.add_option("--input_directory",

+      help='Directory where all the files needed is located.')

+  options.add_option("--msi_location",

+      help='Where to store the resulting msi.')

+  options.add_option("--version",

+      help='The version specified as Major.Minor.Build.Patch.')

+  options.add_option("--wix_bin",

+      help='The location of the wix binary files.')

+  options.add_option("--print_wxs", action="store_true", dest="print_wxs",

+                    default=False,

+                    help="Prints the generated wxs to stdout.")

+  (options, args) = options.parse_args()

+  if len(args) > 0:

+    raise Exception("This script takes no arguments, only options")

+  ValidateOptions(options)

+  return options

+

+def ValidateOptions(options):

+  if not options.version:

+    raise Exception('You must supply a version')

+  if options.zip_file_location and options.input_directory:

+    raise Exception('Please pass either zip_file_location or input_directory')

+  if not options.zip_file_location and not options.input_directory:

+    raise Exception('Please pass either zip_file_location or input_directory')

+  if (options.zip_file_location and

+      not os.path.isfile(options.zip_file_location)):

+    raise Exception('Passed in zip file not found')

+  if (options.input_directory and

+      not os.path.isdir(options.input_directory)):

+    raise Exception('Passed in directory not found')

+

+def GetInputDirectory(options, temp_dir):

+  if options.zip_file_location:

+    ExtractZipFile(options.zip_file_location, temp_dir)

+    return os.path.join(temp_dir, 'dart')

+  return options.input_directory

+

+# We combine the build and patch into a single entry since

+# the windows installer does _not_ consider a change in Patch

+# to require a new install.

+# In addition to that, the limits on the size are:

+# Major: 256

+# Minor: 256

+# Build: 65536

+# To circumvent this we create the version like this:

+#   Major.Minor.X

+# where X is Build<<9 + Patch

+# Example version 1.2.4.14 will go to 1.2.2062

+def GetMicrosoftProductVersion(version):

+  version_parts = version.split('.')

+  if len(version_parts) is not 4:

+    raise Exception(

+      "Version string (%s) does not follow specification" % version)

+  (major, minor, build, patch) = map(int, version_parts)

+

+  if build > 127 or patch > 511:

+    raise Exception('Build/Patch can not be above 127/511')

+  if major > 255 or minor > 255:

+    raise Exception('Major/Minor can not be above 256')

+

+  combined = (build << 9) + patch

+  return '%s.%s.%s' % (major, minor, combined)

+

+# Append using the current indentation level

+def Append(data, new_line=True):

+  str = (('  ' * current_indentation) +

+         data +

+         ('\n' if new_line else ''))

+  xml_content.append(str)

+

+# Append without any indentation at the current position

+def AppendRaw(data, new_line=True):

+  xml_content.append(data + ('\n' if new_line else ''))

+

+def AppendComment(comment):

+  Append('<!--%s-->' % comment)

+

+def AppendBlankLine():

+  Append('')

+

+def GetContent():

+  return ''.join(xml_content)

+

+def XmlHeader():

+  Append('<?xml version="1.0" encoding="UTF-8"?>')

+

+def TagIndent(str, indentation_string):

+  return ' ' * len(indentation_string) + str

+

+def IncreaseIndentation():

+  global current_indentation

+  current_indentation += 1

+

+def DecreaseIndentation():

+  global current_indentation

+  current_indentation -= 1

+

+class WixAndProduct(object):

+  def __init__(self, version):

+    self.version = version

+    self.product_name = 'Dart Editor'

+    self.manufacturer = 'Google Inc.'

+    self.upgrade_code = UPGRADE_CODE

+

+  def __enter__(self):

+    self.start_wix()

+    self.start_product()

+

+  def __exit__(self, *_):

+    self.close_product()

+    self.close_wix()

+

+  def get_product_id(self):

+    # This needs to change on every install to guarantee that

+    # we get a full uninstall + reinstall

+    # We let wix choose. If we need to do patch releases later on

+    # we need to retain the value over several installs.

+    return '*'

+

+  def start_product(self):

+    product = '<Product '

+    Append(product, new_line=False)

+    AppendRaw('Id="%s"' % self.get_product_id())

+    Append(TagIndent('Version="%s"' % self.version, product))

+    Append(TagIndent('Name="%s"' % self.product_name, product))

+    Append(TagIndent('UpgradeCode="%s"' % self.upgrade_code,

+                     product))

+    Append(TagIndent('Language="1033"', product))

+    Append(TagIndent('Manufacturer="%s"' % self.manufacturer,

+                     product),

+           new_line=False)

+    AppendRaw('>')

+    IncreaseIndentation()

+

+  def close_product(self):

+    DecreaseIndentation()

+    Append('</Product>')

+

+  def start_wix(self):

+    Append('<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">')

+    IncreaseIndentation()

+

+  def close_wix(self):

+    DecreaseIndentation()

+    Append('</Wix>')

+

+class Directory(object):

+  def __init__(self, id, name=None):

+    self.id = id

+    self.name = name

+

+  def __enter__(self):

+    directory = '<Directory '

+    Append(directory, new_line=False)

+    AppendRaw('Id="%s"' % self.id, new_line=self.name is not None)

+    if self.name:

+      Append(TagIndent('Name="%s"' % self.name, directory), new_line=False)

+    AppendRaw('>')

+    IncreaseIndentation()

+

+  def __exit__(self, *_):

+    DecreaseIndentation()

+    Append('</Directory>')

+

+class Component(object):

+  def __init__(self, id):

+    self.id = 'CMP_%s' % id

+

+  def __enter__(self):

+    component = '<Component '

+    Append(component, new_line=False)

+    AppendRaw('Id="%s"' % self.id)

+    Append(TagIndent('Guid="*">', component))

+    IncreaseIndentation()

+

+  def __exit__(self, *_):

+    DecreaseIndentation()

+    Append('</Component>')

+    feature_components.append(self.id)

+

+class Feature(object):

+  def __enter__(self):

+    feature = '<Feature '

+    Append(feature, new_line=False)

+    AppendRaw('Id="MainFeature"')

+    Append(TagIndent('Title="Dart Editor"', feature))

+    # Install by default

+    Append(TagIndent('Level="1">', feature))

+    IncreaseIndentation()

+

+  def __exit__(self, *_):

+    DecreaseIndentation()

+    Append('</Feature>')

+

+def Package():

+  package = '<Package '

+  Append(package, new_line=False)

+  AppendRaw('InstallerVersion="301"')

+  Append(TagIndent('Compressed="yes" />', package))

+

+def MediaTemplate():

+  Append('<MediaTemplate EmbedCab="yes" />')

+

+def File(name, id):

+  file = '<File '

+  Append(file, new_line=False)

+  AppendRaw('Id="FILE_%s"' % id)

+  Append(TagIndent('Source="%s"' % name, file))

+  Append(TagIndent('KeyPath="yes" />', file))

+

+def Shortcut(id, name, ref):

+  shortcut = '<Shortcut '

+  Append(shortcut, new_line=False)

+  AppendRaw('Id="%s"' % id)

+  Append(TagIndent('Name="%s"' % name, shortcut))

+  Append(TagIndent('Target="%s" />' % ref, shortcut))

+

+def RemoveFolder(id):

+  remove = '<RemoveFolder '

+  Append(remove, new_line=False)

+  AppendRaw('Id="%s"' % id)

+  Append(TagIndent('On="uninstall" />', remove))

+

+def RegistryEntry(location):

+  registry = '<RegistryValue '

+  Append(registry, new_line=False)

+  AppendRaw('Root="HKCU"')

+  Append(TagIndent('Key="Software\\Microsoft\\%s"' % location, registry))

+  Append(TagIndent('Name="installed"', registry))

+  Append(TagIndent('Type="integer"', registry))

+  Append(TagIndent('Value="1"', registry))

+  Append(TagIndent('KeyPath="yes" />', registry))

+

+

+def MajorUpgrade():

+  upgrade = '<MajorUpgrade '

+  Append(upgrade, new_line=False)

+  down_message = 'You already have a never version installed.'

+  AppendRaw('DowngradeErrorMessage="%s" />' % down_message)

+

+

+# This is a very simplistic id generation.

+# Unfortunately there is no easy way to generate good names,

+# since there is a 72 character limit, and we have way longer

+# paths. We don't really have an issue with files and ids across

+# releases since we do full installs.

+counter = 0

+def FileToId(name):

+  global counter

+  counter += 1

+  return '%s' % counter

+

+def ListFiles(path):

+  for entry in os.listdir(path):

+    full_path = os.path.join(path, entry)

+    id = FileToId(full_path)

+    if os.path.isdir(full_path):

+      with Directory('DIR_%s' % id, entry):

+        ListFiles(full_path)

+    elif os.path.isfile(full_path):

+      # We assume 1 file per component, a File is always a KeyPath.

+      # A KeyPath on a file makes sure that we can always repair and

+      # remove that file in a consistent manner. A component

+      # can only have one child with a KeyPath.

+      with Component(id):

+        File(full_path, id)

+

+def ComponentRefs():

+  for component in feature_components:

+    Append('<ComponentRef Id="%s" />' % component)

+

+def ExtractZipFile(zip, temp_dir):

+  print 'Extracting files'

+  f = zipfile.ZipFile(zip)

+  f.extractall(temp_dir)

+  f.close()

+

+def GenerateInstaller(wxs_content, options, temp_dir):

+  wxs_file = os.path.join(temp_dir, 'installer.wxs')

+  wixobj_file = os.path.join(temp_dir, 'installer.wixobj')

+  print 'Saving wxs output to: %s' % wxs_file

+  with open(wxs_file, 'w') as f:

+    f.write(wxs_content)

+

+  candle_bin = 'candle.exe'

+  light_bin = 'light.exe'

+  if options.wix_bin:

+    candle_bin = os.path.join(options.wix_bin, 'candle.exe')

+    light_bin = os.path.join(options.wix_bin, 'light.exe')

+  print 'Calling candle on %s' % wxs_file

+  subprocess.check_call('%s %s -o %s' % (candle_bin, wxs_file,

+                                         wixobj_file))

+  print 'Calling light on %s' % wixobj_file

+  subprocess.check_call('%s %s -o %s' % (light_bin, wixobj_file,

+                                         options.msi_location))

+  print 'Created msi file to %s' % options.msi_location

+

+

+def Main(argv):

+  if sys.platform != 'win32':

+    raise Exception("This script can only be run on windows")

+  options = GetOptions()

+  version = GetMicrosoftProductVersion(options.version)

+  with utils.TempDir('installer') as temp_dir:

+    input_location = GetInputDirectory(options, temp_dir)

+    print "Generating wix XML"

+    XmlHeader()

+    with WixAndProduct(version):

+      AppendBlankLine()

+      Package()

+      MediaTemplate()

+      AppendComment('We always do a major upgrade, at least for now')

+      MajorUpgrade()

+

+      AppendComment('Directory structure')

+      with Directory('TARGETDIR', 'SourceDir'):

+        with Directory('ProgramFilesFolder'):

+          with Directory('RootInstallDir', 'Dart Editor'):

+            AppendComment("Add all files and directories")

+            print 'Installing files and directories in xml'

+            ListFiles(input_location)

+        AppendBlankLine()

+        AppendComment("Create shortcuts")

+        with Directory('ProgramMenuFolder'):

+          with Directory('ShortcutFolder', 'Dart Editor'):

+            with Component('shortcut'):

+              # When generating a shortcut we need an entry with

+              # a KeyPath (RegistryEntry) below - to be able to remove

+              # the shortcut again. The RemoveFolder tag is needed

+              # to clean up everything

+              Shortcut('editor_shortcut', 'Dart Editor',

+                       '[RootInstallDir]DartEditor.exe')

+              RemoveFolder('RemoveShortcuts')

+              RegistryEntry('DartEditor')

+      with Feature():

+        # We have only one feature and that consist of all the

+        # files=components we have listed above"

+        ComponentRefs()

+    xml = GetContent()

+    if options.print_wxs:

+      print xml

+    GenerateInstaller(xml, options, temp_dir)

+

+if __name__ == '__main__':

+  sys.exit(Main(sys.argv))

diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index a787d3c..82c6737 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -310,6 +310,37 @@
         ]
       }
     },
+    "Window": {
+      "comment": [
+        "/**",
+        " * Top-level container for the current browser tab or window.",
+        " *",
+        " * In a web browser, each window has a [Window] object, but within the context",
+        " * of a script, a [Window] object represents only the current window. In",
+        " * addition to the open window, each window, tab, and iframe has its own",
+        " * [Window] object. A [Window] contains a [Document] object, which contains this",
+        " * web page's content.",
+        " *",
+        " * Use `window` to access properties of the current window. For example:",
+        " *",
+        " *     // Draw a scene when the window repaints.",
+        " *     drawScene(num delta) {...}",
+        " *     window.animationFrame.then(drawScene);.",
+        " *",
+        " *     // Write to the console.",
+        " *     window.console.log('Jinkies!');",
+        " *     window.console.error('Jeepers!');",
+        " *",
+        " * **Note:** This class represents the current window, whereas [WindowBase] is",
+        " * a representation of any window, including other tabs, windows, and frames.",
+        " *",
+        " * ## Other resources",
+        " *",
+        " * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.",
+        " * * [Window](http://www.w3.org/TR/Window/) from the W3C.",
+        " */"
+      ]
+    },
     "XMLHttpRequest": {
       "members": {
         "abort": [
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index 8205dad..d549d98 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -445,9 +445,9 @@
     # TODO: Include all implemented interfaces, including other Lists.
     implements = []
     if self._interface_type_info.list_item_type():
-      item_type_info = self._type_registry.TypeInfo(
-          self._interface_type_info.list_item_type())
-      implements.append('List')
+      item_type = self._type_registry.TypeInfo(
+          self._interface_type_info.list_item_type()).dart_type()
+      implements.append('List<%s>' % item_type)
     return implements
 
   def Mixins(self):
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index a862cb4..0db0fee 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -62,6 +62,7 @@
     'WindowTimers': '_WindowTimers',
     'XMLHttpRequest': 'HttpRequest',
     'XMLHttpRequestUpload': 'HttpRequestUpload',
+    'XMLHttpRequestEventTarget': 'HttpRequestEventTarget',
 }, **typed_array_renames))
 
 # Interfaces that are suppressed, but need to still exist for Dartium and to
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 1684988..651900a 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -1208,6 +1208,7 @@
     e.Emit('    _DateTimeClassId,\n');
     e.Emit('    _JsObjectClassId,\n');
     e.Emit('    _JsFunctionClassId,\n');
+    e.Emit('    _JsArrayClassId,\n');
     e.Emit('    // New types that are not auto-generated should be added here.\n');
     e.Emit('\n');
     for interface in database.GetInterfaces():
@@ -1254,6 +1255,7 @@
     e.Emit('    { "DateTime", DartCoreLibraryId, -1, false, false, false },\n');
     e.Emit('    { "JsObject", DartJsLibraryId, -1, false, false, false },\n');
     e.Emit('    { "JsFunction", DartJsLibraryId, _JsObjectClassId, false, false, false },\n');
+    e.Emit('    { "JsArray", DartJsLibraryId, _JsObjectClassId, false, false, false },\n');
     e.Emit('    // New types that are not auto-generated should be added here.\n');
     e.Emit('\n');
     is_node_test = lambda interface: interface.id == 'Node'
diff --git a/tools/dom/src/CrossFrameTypes.dart b/tools/dom/src/CrossFrameTypes.dart
index 9353839..f8ed874 100644
--- a/tools/dom/src/CrossFrameTypes.dart
+++ b/tools/dom/src/CrossFrameTypes.dart
@@ -5,17 +5,16 @@
 part of html;
 
 /**
- * An object representing the top-level context object for web scripting.
+ * Top-level container for a browser tab or window.
  *
- * In a web browser, a [Window] object represents the actual browser window.
- * In a multi-tabbed browser, each tab has its own [Window] object. A [Window]
- * is the container that displays a [Document]'s content. All web scripting
- * happens within the context of a [Window] object.
+ * In a web browser, a [WindowBase] object represents any browser window.  This
+ * abstract class contains the state of the window and its relation to other
+ * windows, such as which window opened it.
  *
  * **Note:** This class represents any window, whereas [Window] is
- * used to access the properties and content of the current window.
+ * used to access the properties and content of the current window or tab.
  *
- * See also:
+ * ## Other resources
  *
  * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
  * * [Window](http://www.w3.org/TR/Window/) from the W3C.
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 7f0b364..2e787bd 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -5,6 +5,121 @@
 part of html;
 
 /**
+ * A factory to expose DOM events as Streams.
+ */
+class EventStreamProvider<T extends Event> {
+  final String _eventType;
+
+  const EventStreamProvider(this._eventType);
+
+  /**
+   * Gets a [Stream] for this event type, on the specified target.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
+   *
+   *     // Alternate method:
+   *     Element.keyDownEvent.forTarget(element).capture(...);
+   *
+   * Or for listening to an event which will bubble through the DOM tree:
+   *
+   *     MediaElement.pauseEvent.forTarget(document.body).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
+    new _EventStream(e, _eventType, useCapture);
+
+  /**
+   * Gets an [ElementEventStream] for this event type, on the specified element.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
+   *
+   *     // Alternate method:
+   *     Element.keyDownEvent.forElement(element).capture(...);
+   *
+   * Or for listening to an event which will bubble through the DOM tree:
+   *
+   *     MediaElement.pauseEvent.forElement(document.body).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
+    return new _ElementEventStreamImpl(e, _eventType, useCapture);
+  }
+
+  /**
+   * Gets an [ElementEventStream] for this event type, on the list of elements.
+   *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
+   * This may be used to capture DOM events:
+   *
+   *     Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
+   *
+   * See also:
+   *
+   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+   */
+  ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
+    return new _ElementListEventStreamImpl(e, _eventType, useCapture);
+  }
+
+  /**
+   * Gets the type of the event which this would listen for on the specified
+   * event target.
+   *
+   * The target is necessary because some browsers may use different event names
+   * for the same purpose and the target allows differentiating browser support.
+   */
+  String getEventType(EventTarget target) {
+    return _eventType;
+  }
+}
+
+/** A specialized Stream available to [Element]s to enable event delegation. */
+abstract class ElementStream<T extends Event> implements Stream<T> {
+  /**
+   * Return a stream that only fires when the particular event fires for
+   * elements matching the specified CSS selector.
+   *
+   * This is the Dart equivalent to jQuery's
+   * [delegate](http://api.jquery.com/delegate/).
+   */
+  Stream<T> matches(String selector);
+
+  /**
+   * Adds a capturing subscription to this stream.
+   *
+   * If the target of the event is a descendant of the element from which this
+   * stream derives then [onData] is called before the event propagates down to
+   * the target. This is the opposite of bubbling behavior, where the event
+   * is first processed for the event target and then bubbles upward.
+   *
+   * ## Other resources
+   *
+   * * [Event Capture]
+   * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
+   * from the W3C DOM Events specification.
+   */
+  StreamSubscription<T> capture(void onData(T event));
+}
+
+/**
  * Adapter for exposing DOM events as Dart streams.
  */
 class _EventStream<T extends Event> extends Stream<T> {
@@ -30,20 +145,6 @@
   }
 }
 
-/** A specialized Stream available to [Element]s to enable event delegation. */
-abstract class ElementStream<T extends Event> implements Stream<T> {
-  /**
-   * Return a stream that only fires when the particular event fires for
-   * elements matching the specified CSS selector.
-   *
-   * This is the Dart equivalent to jQuery's
-   * [delegate](http://api.jquery.com/delegate/).
-   */
-  Stream<T> matches(String selector);
-
-  StreamSubscription<T> capture(void onData(T event));
-}
-
 /**
  * Adapter for exposing DOM Element events as streams, while also allowing
  * event delegation.
@@ -110,6 +211,83 @@
   bool get isBroadcast => true;
 }
 
+class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
+  int _pauseCount = 0;
+  EventTarget _target;
+  final String _eventType;
+  var _onData;
+  final bool _useCapture;
+
+  _EventStreamSubscription(this._target, this._eventType, onData,
+      this._useCapture) : _onData = _wrapZone(onData) {
+    _tryResume();
+  }
+
+  void cancel() {
+    if (_canceled) return;
+
+    _unlisten();
+    // Clear out the target to indicate this is complete.
+    _target = null;
+    _onData = null;
+  }
+
+  bool get _canceled => _target == null;
+
+  void onData(void handleData(T event)) {
+    if (_canceled) {
+      throw new StateError("Subscription has been canceled.");
+    }
+    // Remove current event listener.
+    _unlisten();
+
+    _onData = _wrapZone(handleData);
+    _tryResume();
+  }
+
+  /// Has no effect.
+  void onError(Function handleError) {}
+
+  /// Has no effect.
+  void onDone(void handleDone()) {}
+
+  void pause([Future resumeSignal]) {
+    if (_canceled) return;
+    ++_pauseCount;
+    _unlisten();
+
+    if (resumeSignal != null) {
+      resumeSignal.whenComplete(resume);
+    }
+  }
+
+  bool get isPaused => _pauseCount > 0;
+
+  void resume() {
+    if (_canceled || !isPaused) return;
+    --_pauseCount;
+    _tryResume();
+  }
+
+  void _tryResume() {
+    if (_onData != null && !isPaused) {
+      _target.addEventListener(_eventType, _onData, _useCapture);
+    }
+  }
+
+  void _unlisten() {
+    if (_onData != null) {
+      _target.removeEventListener(_eventType, _onData, _useCapture);
+    }
+  }
+
+  Future asFuture([var futureValue]) {
+    // We just need a future that will never succeed or fail.
+    Completer completer = new Completer();
+    return completer.future;
+  }
+}
+
 /**
  * A stream of custom events, which enables the user to "fire" (add) their own
  * custom events to a stream.
@@ -223,160 +401,6 @@
   }
 }
 
-class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
-  int _pauseCount = 0;
-  EventTarget _target;
-  final String _eventType;
-  var _onData;
-  final bool _useCapture;
-
-  _EventStreamSubscription(this._target, this._eventType, onData,
-      this._useCapture) : _onData = _wrapZone(onData) {
-    _tryResume();
-  }
-
-  void cancel() {
-    if (_canceled) return;
-
-    _unlisten();
-    // Clear out the target to indicate this is complete.
-    _target = null;
-    _onData = null;
-  }
-
-  bool get _canceled => _target == null;
-
-  void onData(void handleData(T event)) {
-    if (_canceled) {
-      throw new StateError("Subscription has been canceled.");
-    }
-    // Remove current event listener.
-    _unlisten();
-
-    _onData = _wrapZone(handleData);
-    _tryResume();
-  }
-
-  /// Has no effect.
-  void onError(Function handleError) {}
-
-  /// Has no effect.
-  void onDone(void handleDone()) {}
-
-  void pause([Future resumeSignal]) {
-    if (_canceled) return;
-    ++_pauseCount;
-    _unlisten();
-
-    if (resumeSignal != null) {
-      resumeSignal.whenComplete(resume);
-    }
-  }
-
-  bool get isPaused => _pauseCount > 0;
-
-  void resume() {
-    if (_canceled || !isPaused) return;
-    --_pauseCount;
-    _tryResume();
-  }
-
-  void _tryResume() {
-    if (_onData != null && !isPaused) {
-      _target.addEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  void _unlisten() {
-    if (_onData != null) {
-      _target.removeEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  Future asFuture([var futureValue]) {
-    // We just need a future that will never succeed or fail.
-    Completer completer = new Completer();
-    return completer.future;
-  }
-}
-
-/**
- * A factory to expose DOM events as Streams.
- */
-class EventStreamProvider<T extends Event> {
-  final String _eventType;
-
-  const EventStreamProvider(this._eventType);
-
-  /**
-   * Gets a [Stream] for this event type, on the specified target.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
-   *
-   * Or for listening to an event which will bubble through the DOM tree:
-   *
-   *     MediaElement.pauseEvent.forTarget(document.body).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
-    new _EventStream(e, _eventType, useCapture);
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the specified element.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the list of elements.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
-   *
-   * See also:
-   *
-   * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
-   */
-  ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets the type of the event which this would listen for on the specified
-   * event target.
-   *
-   * The target is necessary because some browsers may use different event names
-   * for the same purpose and the target allows differentiating browser support.
-   */
-  String getEventType(EventTarget target) {
-    return _eventType;
-  }
-}
-
 /**
  * A factory to expose DOM events as streams, where the DOM event name has to
  * be determined on the fly (for example, mouse wheel events).
diff --git a/tools/dom/src/dart2js_KeyEvent.dart b/tools/dom/src/dart2js_KeyEvent.dart
index b8fcfa6..8c7b5fd 100644
--- a/tools/dom/src/dart2js_KeyEvent.dart
+++ b/tools/dom/src/dart2js_KeyEvent.dart
@@ -56,7 +56,7 @@
 
   /** Helper to statically create the dispatch record. */
   static _makeRecord() {
-    var interceptor = findInterceptorForType(KeyboardEvent);
+    var interceptor = JS_INTERCEPTOR_CONSTANT(KeyboardEvent);
     return makeLeafDispatchRecord(interceptor);
   }
 
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 51e9ced..46b4e71 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -535,6 +535,13 @@
 
 final _forwardingPrintClosure = _Utils.forwardingPrint;
 
+final _uriBaseClosure = () => Uri.parse(window.location.href);
+
+final _pureIsolateUriBaseClosure = () {
+  throw new UnimplementedError("Uri.base on a background isolate "
+                               "is not supported in the browser");
+};
+
  class _Timer implements Timer {
   var _canceler;
 
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 394f526..146645c 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -54,9 +54,9 @@
 import 'dart:_interceptors' show
     Interceptor, JSExtendableArray, findInterceptorConstructorForType,
     findConstructorForNativeSubclassType, getNativeInterceptor,
-    setDispatchProperty, findInterceptorForType;
+    setDispatchProperty;
 import 'dart:_isolate_helper' show IsolateNatives;
-import 'dart:_foreign_helper' show JS;
+import 'dart:_foreign_helper' show JS, JS_INTERCEPTOR_CONSTANT;
 
 export 'dart:math' show Rectangle, Point;
 
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 3bc56ef..e04ec31 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -259,7 +259,7 @@
 // ElementList as there are valid cases where a NodeList JavaScript object
 // contains Node objects that are not Elements.
 class _FrozenElementList<T extends Element> extends ListBase<T>
-    implements ElementList, NodeListWrapper {
+    implements ElementList<T>, NodeListWrapper {
   final List<Node> _nodeList;
   // The subset of _nodeList that are Elements.
   List<Element> _elementList;
diff --git a/tools/test.dart b/tools/test.dart
index d319bdae..0556662 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -29,7 +29,6 @@
 import "dart:math" as math;
 import "testing/dart/browser_controller.dart";
 import "testing/dart/http_server.dart";
-import "testing/dart/record_and_replay.dart";
 import "testing/dart/test_options.dart";
 import "testing/dart/test_progress.dart";
 import "testing/dart/test_runner.dart";
@@ -38,7 +37,6 @@
 
 import "../runtime/tests/vm/test_config.dart";
 import "../tests/co19/test_config.dart";
-import "../tests/lib/analyzer/test_config.dart";
 
 /**
  * The directories that contain test suites which follow the conventions
@@ -172,6 +170,11 @@
       // Safari does not allow us to run from a fresh profile, so we can only
       // use one browser.
       maxBrowserProcesses = 1;
+    } else if (conf['runtime'] == 'chrome' &&
+               conf['use_browser_controller'] &&
+               Platform.operatingSystem == 'macos') {
+      // Chrome on mac results in random timeouts.
+      maxBrowserProcesses = math.max(1, maxBrowserProcesses ~/ 2);
     }
 
     for (String key in selectors.keys) {
@@ -185,9 +188,6 @@
         if (key == 'analyze_library') {
           testSuites.add(new AnalyzeLibraryTestSuite(conf));
         }
-        if (key == 'analyze_tests') {
-          testSuites.add(new AnalyzeTestsTestSuite(conf));
-        }
       }
     }
 
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index f45263d..d661e84 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -75,8 +75,7 @@
   static const List<String> SUPPORTED_BROWSERS =
     const ['safari', 'ff', 'firefox', 'chrome', 'ie9', 'ie10', 'dartium'];
 
-  static const List<String> BROWSERS_WITH_WINDOW_SUPPORT =
-      const ['safari', 'ff', 'firefox', 'chrome'];
+  static const List<String> BROWSERS_WITH_WINDOW_SUPPORT = const [];
 
   // TODO(kustermann): add standard support for chrome on android
   static bool supportedBrowser(String name) {
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index b942437..197e850 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -229,7 +229,7 @@
       openedFile.writeStringSync(tests[key]);
       openedFile.closeSync();
       Set<String> outcome = outcomes[key];
-      bool enableFatalTypeErrors = outcome.contains('static type warning');
+      bool hasStaticWarning = outcome.contains('static type warning');
       bool hasRuntimeErrors = outcome.contains('runtime error');
       bool hasCompileError = outcome.contains('compile-time error');
       bool isNegativeIfChecked = outcome.contains('dynamic type error');
@@ -237,7 +237,7 @@
              hasCompileError,
              hasRuntimeErrors,
              isNegativeIfChecked: isNegativeIfChecked,
-             hasFatalTypeErrors: enableFatalTypeErrors,
+             hasStaticWarning: hasStaticWarning,
              multitestOutcome: outcome,
              multitestKey: key,
              originTestPath: filePath);
diff --git a/tools/testing/dart/status_file_parser.dart b/tools/testing/dart/status_file_parser.dart
index b69e6ac..6922687 100644
--- a/tools/testing/dart/status_file_parser.dart
+++ b/tools/testing/dart/status_file_parser.dart
@@ -22,6 +22,9 @@
   static Expectation MISSING_RUNTIME_ERROR = byName('MissingRuntimeError');
   static Expectation MISSING_COMPILETIME_ERROR =
       byName('MissingCompileTimeError');
+  static Expectation STATIC_WARNING = byName('StaticWarning');
+  static Expectation MISSING_STATIC_WARNING =
+      byName('MissingStaticWarning');
 
   // "meta expectations"
   static Expectation OK = byName('Ok');
@@ -61,6 +64,9 @@
       build("CompileTimeError", group: fail);
       build("RuntimeError", group: fail);
 
+      build("MissingStaticWarning", group: fail);
+      build("StaticWarning", group: fail);
+
       build("Skip", isMetaExpectation: true);
       build("SkipByDesign", isMetaExpectation: true);
       build("Ok", isMetaExpectation: true);
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index ff016e6..b1528ec 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -12,7 +12,7 @@
 List<String> defaultTestSelectors =
     const ['samples', 'standalone', 'corelib', 'co19', 'language',
            'isolate', 'vm', 'html', 'json', 'benchmark_smoke',
-           'utils', 'lib', 'pkg', 'analyze_library', 'analyze_tests'];
+           'utils', 'lib', 'pkg', 'analyze_library'];
 
 /**
  * Specification of a single test option.
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 5527d03..9f62c9c 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -339,23 +339,30 @@
 class AnalysisCommand extends Command {
   final String flavor;
 
+  // If [fileFilter] is given, only errors/warnings reported by the analyzer
+  // for which [fileFilter] returns [:true:] are considered.
+  final Function fileFilter;
+
   AnalysisCommand._(this.flavor,
                     String displayName,
                     String executable,
                     List<String> arguments,
-                    String configurationDir)
+                    String configurationDir,
+                    this.fileFilter)
       : super._(displayName, executable, arguments, configurationDir);
 
   void _buildHashCode(HashCodeBuilder builder) {
     super._buildHashCode(builder);
     builder.add(flavor);
+    builder.add(fileFilter);
   }
 
   bool _equal(Command other) {
     return
         other is AnalysisCommand &&
         super._equal(other) &&
-        flavor == other.flavor;
+        flavor == other.flavor &&
+        fileFilter == other.fileFilter;
   }
 }
 
@@ -434,9 +441,10 @@
 
   AnalysisCommand getAnalysisCommand(
       String displayName, executable, arguments, String configurationDir,
-      {String flavor: 'dartanalyzer'}) {
+      {String flavor: 'dartanalyzer', Function fileFilter: null}) {
     var command = new AnalysisCommand._(
-        flavor, displayName, executable, arguments, configurationDir);
+        flavor, displayName, executable, arguments, configurationDir,
+        fileFilter);
     return _getUniqueCommand(command);
   }
 
@@ -912,20 +920,14 @@
 }
 
 
-// The static analyzer does not actually execute code, so
-// the criteria for success now depend on the text sent
-// to stderr.
 class AnalysisCommandOutputImpl extends CommandOutputImpl {
   // An error line has 8 fields that look like:
   // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source.
   final int ERROR_LEVEL = 0;
   final int ERROR_TYPE = 1;
+  final int FILENAME = 3;
   final int FORMATTED_ERROR = 7;
 
-  bool alreadyComputed = false;
-  bool failResult;
-
-  // TODO(kustermann): Remove testCase from this class
   AnalysisCommandOutputImpl(command,
                             exitCode,
                             timedOut,
@@ -941,153 +943,95 @@
           time,
           compilationSkipped);
 
-  bool didFail(TestCase testCase) {
-    if (!alreadyComputed) {
-      failResult = _didFail(testCase);
-      alreadyComputed = true;
+  Expectation result(TestCase testCase) {
+    // TODO(kustermann): If we run the analyzer not in batch mode, make sure
+    // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings,
+    // no errors)
+
+    // Handle crashes and timeouts first
+    if (hasCrashed) return Expectation.CRASH;
+    if (hasTimedOut) return Expectation.TIMEOUT;
+
+    // Get the errors/warnings from the analyzer
+    List<String> errors = [];
+    List<String> warnings = [];
+    parseAnalyzerOutput(errors, warnings);
+
+    // Handle errors / missing errors
+    if (testCase.info.hasCompileError) {
+      if (errors.length > 0) {
+        return Expectation.PASS;
+      }
+      return Expectation.MISSING_COMPILETIME_ERROR;
     }
-    return failResult;
+    if (errors.length > 0) {
+      return Expectation.COMPILETIME_ERROR;
+    }
+
+    // Handle static warnings / missing static warnings
+    if (testCase.info.hasStaticWarning) {
+      if (warnings.length > 0) {
+        return Expectation.PASS;
+      }
+      return Expectation.MISSING_STATIC_WARNING;
+    }
+    if (warnings.length > 0) {
+      return Expectation.STATIC_WARNING;
+    }
+
+    assert (errors.length == 0 && warnings.length == 0);
+    assert (!testCase.info.hasCompileError &&
+            !testCase.info.hasStaticWarning);
+    return Expectation.PASS;
   }
 
-  bool _didFail(TestCase testCase) {
-    if (hasCrashed) return false;
+  void parseAnalyzerOutput(List<String> outErrors, List<String> outWarnings) {
+    AnalysisCommand analysisCommand = command;
+    Function fileFilter = analysisCommand.fileFilter;
+    if (fileFilter == null) {
+      // If no filter function was given, we don't filter the output at all.
+      fileFilter = (arg) => true;
+    }
 
-    List<String> errors = [];
-    List<String> staticWarnings = [];
+    // Parse a line delimited by the | character using \ as an escape charager
+    // like:  FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
+    List<String> splitMachineError(String line) {
+      StringBuffer field = new StringBuffer();
+      List<String> result = [];
+      bool escaped = false;
+      for (var i = 0 ; i < line.length; i++) {
+        var c = line[i];
+        if (!escaped && c == '\\') {
+          escaped = true;
+          continue;
+        }
+        escaped = false;
+        if (c == '|') {
+          result.add(field.toString());
+          field = new StringBuffer();
+          continue;
+        }
+        field.write(c);
+      }
+      result.add(field.toString());
+      return result;
+    }
 
-    // Read the returned list of errors and stuff them away.
-    var stderrLines = decodeUtf8(super.stderr).split("\n");
-    for (String line in stderrLines) {
+    for (String line in decodeUtf8(super.stderr).split("\n")) {
       if (line.length == 0) continue;
       List<String> fields = splitMachineError(line);
-      if (fields[ERROR_LEVEL] == 'ERROR') {
-        errors.add(fields[FORMATTED_ERROR]);
-      } else if (fields[ERROR_LEVEL] == 'WARNING') {
-        staticWarnings.add(fields[FORMATTED_ERROR]);
-      }
-      // OK to Skip error output that doesn't match the machine format
-    }
-    // FIXME(kustermann): This is wrong, we should give the expectations
-    // to Command
-    if (testCase.info != null
-        && testCase.info.optionsFromFile['isMultitest']) {
-      return _didMultitestFail(testCase, errors, staticWarnings);
-    }
-    return _didStandardTestFail(testCase, errors, staticWarnings);
-  }
-
-  bool _didMultitestFail(TestCase testCase, List errors, List staticWarnings) {
-    Set<String> outcome = testCase.info.multitestOutcome;
-    if (outcome == null) throw "outcome must not be null";
-    if (outcome.contains('compile-time error') && errors.length > 0) {
-      return true;
-    } else if (outcome.contains('static type warning')
-        && staticWarnings.length > 0) {
-      return true;
-    } else if (outcome.isEmpty
-        && (errors.length > 0 || staticWarnings.length > 0)) {
-      return true;
-    }
-    return false;
-  }
-
-  bool _didStandardTestFail(TestCase testCase, List errors, List staticWarnings) {
-    bool hasFatalTypeErrors = false;
-    int numStaticTypeAnnotations = 0;
-    int numCompileTimeAnnotations = 0;
-    var isStaticClean = false;
-    if (testCase.info != null) {
-      var optionsFromFile = testCase.info.optionsFromFile;
-      hasFatalTypeErrors = testCase.info.hasFatalTypeErrors;
-      for (Command c in testCase.commands) {
-        for (String arg in c.arguments) {
-          if (arg == '--fatal-type-errors') {
-            hasFatalTypeErrors = true;
-            break;
+      // We only consider errors/warnings for files of interest.
+      if (fields.length > FILENAME) {
+        if (fileFilter(fields[FILENAME])) {
+          if (fields[ERROR_LEVEL] == 'ERROR') {
+            outErrors.add(fields[FORMATTED_ERROR]);
+          } else if (fields[ERROR_LEVEL] == 'WARNING') {
+            outWarnings.add(fields[FORMATTED_ERROR]);
           }
         }
+        // OK to Skip error output that doesn't match the machine format
       }
-      numStaticTypeAnnotations = optionsFromFile['numStaticTypeAnnotations'];
-      numCompileTimeAnnotations = optionsFromFile['numCompileTimeAnnotations'];
-      isStaticClean = optionsFromFile['isStaticClean'];
     }
-
-    if (errors.length == 0) {
-      // If the analyzer has warnings it will exit 1.
-      // We should reconsider how we do this once we have landed a dart
-      // only version of the analyzer for stable use (as in not run in batch
-      // mode).
-      if (!hasFatalTypeErrors && exitCode != 0 && staticWarnings.length == 0) {
-        diagnostics.add("EXIT CODE MISMATCH: Expected error message:");
-        diagnostics.add("  command[0]:${testCase.commands[0]}");
-        diagnostics.add("  exitCode:${exitCode}");
-        return true;
-      }
-    } else if (exitCode == 0) {
-      diagnostics.add("EXIT CODE MISMATCH: Unexpected error message:");
-      diagnostics.add("  errors[0]:${errors[0]}");
-      diagnostics.add("  command[0]:${testCase.commands[0]}");
-      diagnostics.add("  exitCode:${exitCode}");
-      return true;
-    }
-    if (numStaticTypeAnnotations > 0 && isStaticClean) {
-      diagnostics.add("Cannot have both @static-clean and /// static "
-                      "type warning annotations.");
-      return true;
-    }
-
-    if (isStaticClean && (errors.isNotEmpty || staticWarnings.isNotEmpty)) {
-      diagnostics.add(
-          "@static-clean annotation found but analyzer returned problems.");
-      return true;
-    }
-
-    if (numCompileTimeAnnotations > 0
-        && numCompileTimeAnnotations < errors.length) {
-      // Expected compile-time errors were not returned.
-      // The test did not 'fail' in the way intended so don't return failed.
-      diagnostics.add("Fewer compile time errors than annotated: "
-          "$numCompileTimeAnnotations");
-      return false;
-    }
-
-    if (numStaticTypeAnnotations > 0 || hasFatalTypeErrors) {
-      // TODO(zundel): match up the annotation line numbers
-      // with the reported error line numbers
-      if (staticWarnings.length < numStaticTypeAnnotations) {
-        diagnostics.add("Fewer static type warnings than annotated: "
-            "$numStaticTypeAnnotations");
-        return true;
-      }
-      return false;
-    } else if (errors.length != 0) {
-      return true;
-    }
-    return false;
-  }
-
-  // Parse a line delimited by the | character using \ as an escape charager
-  // like:  FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
-  List<String> splitMachineError(String line) {
-    StringBuffer field = new StringBuffer();
-    List<String> result = [];
-    bool escaped = false;
-    for (var i = 0 ; i < line.length; i++) {
-      var c = line[i];
-      if (!escaped && c == '\\') {
-        escaped = true;
-        continue;
-      }
-      escaped = false;
-      if (c == '|') {
-        result.add(field.toString());
-        field = new StringBuffer();
-        continue;
-      }
-      field.write(c);
-    }
-    result.add(field.toString());
-    return result;
   }
 }
 
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index caa2c6e..298317b 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -37,7 +37,7 @@
                         bool hasCompileError,
                         bool hasRuntimeError,
                         {bool isNegativeIfChecked,
-                         bool hasFatalTypeErrors,
+                         bool hasStaticWarning,
                          Set<String> multitestOutcome,
                          String multitestKey,
                          Path originTestPath});
@@ -468,13 +468,13 @@
   bool hasCompileError;
   bool hasRuntimeError;
   bool isNegativeIfChecked;
-  bool hasFatalTypeErrors;
+  bool hasStaticWarning;
   Set<String> multitestOutcome;
   String multitestKey;
 
   TestInformation(this.filePath, this.optionsFromFile,
                   this.hasCompileError, this.hasRuntimeError,
-                  this.isNegativeIfChecked, this.hasFatalTypeErrors,
+                  this.isNegativeIfChecked, this.hasStaticWarning,
                   this.multitestOutcome,
                   {this.multitestKey, this.originTestPath}) {
     assert(filePath.isAbsolute);
@@ -693,7 +693,8 @@
     } else {
       createTestCase(filePath,
                      optionsFromFile['hasCompileError'],
-                     optionsFromFile['hasRuntimeError']);
+                     optionsFromFile['hasRuntimeError'],
+                     hasStaticWarning: optionsFromFile['hasStaticWarning']);
     }
   }
 
@@ -761,13 +762,6 @@
     if (info.hasRuntimeError && hasRuntime) {
       negative = true;
     }
-    if (configuration['analyzer']) {
-      // An analyzer can detect static type warnings by the
-      // format of the error line
-      if (info.hasFatalTypeErrors) {
-        negative = true;
-      }
-    }
     return negative;
   }
 
@@ -829,21 +823,26 @@
 
     case 'dartanalyzer':
     case 'dart2analyzer':
-      return <Command>[CommandBuilder.instance.getAnalysisCommand(
-          compiler, dartShellFileName, args, configurationDir,
-          flavor: compiler)];
+      return <Command>[makeAnalysisCommand(info, args)];
 
     default:
       throw 'Unknown compiler ${configuration["compiler"]}';
     }
   }
 
+  AnalysisCommand makeAnalysisCommand(TestInformation info,
+                                      List<String> arguments) {
+    return CommandBuilder.instance.getAnalysisCommand(
+        configuration['compiler'], dartShellFileName, arguments,
+        configurationDir, flavor: configuration['compiler']);
+  }
+
   CreateTest makeTestCaseCreator(Map optionsFromFile) {
     return (Path filePath,
             bool hasCompileError,
             bool hasRuntimeError,
             {bool isNegativeIfChecked: false,
-             bool hasFatalTypeErrors: false,
+             bool hasStaticWarning: false,
              Set<String> multitestOutcome: null,
              String multitestKey,
              Path originTestPath}) {
@@ -853,7 +852,7 @@
                                      hasCompileError,
                                      hasRuntimeError,
                                      isNegativeIfChecked,
-                                     hasFatalTypeErrors,
+                                     hasStaticWarning,
                                      multitestOutcome,
                                      multitestKey: multitestKey,
                                      originTestPath: originTestPath);
@@ -1412,11 +1411,6 @@
     RegExp packageRootRegExp = new RegExp(r"// PackageRoot=(.*)");
     RegExp multiHtmlTestRegExp =
         new RegExp(r"useHtmlIndividualConfiguration()");
-    RegExp staticTypeRegExp =
-        new RegExp(r"/// ([0-9][0-9]:){0,1}\s*static type warning");
-    RegExp compileTimeRegExp =
-        new RegExp(r"/// ([0-9][0-9]:){0,1}\s*compile-time error");
-    RegExp staticCleanRegExp = new RegExp(r"// @static-clean");
     RegExp isolateStubsRegExp = new RegExp(r"// IsolateStubs=(.*)");
     // TODO(gram) Clean these up once the old directives are not supported.
     RegExp domImportRegExp =
@@ -1431,7 +1425,6 @@
     List<List> result = new List<List>();
     List<String> dartOptions;
     String packageRoot;
-    bool isStaticClean = false;
 
     Iterable<Match> matches = testOptionsRegExp.allMatches(contents);
     for (var match in matches) {
@@ -1461,15 +1454,6 @@
       }
     }
 
-    matches = staticCleanRegExp.allMatches(contents);
-    for (var match in matches) {
-      if (isStaticClean) {
-        throw new Exception(
-            'More than one "// @static-clean=" line in test $filePath');
-      }
-      isStaticClean = true;
-    }
-
     List<String> otherScripts = new List<String>();
     matches = otherScriptsRegExp.allMatches(contents);
     for (var match in matches) {
@@ -1481,14 +1465,6 @@
     Match isolateMatch = isolateStubsRegExp.firstMatch(contents);
     String isolateStubs = isolateMatch != null ? isolateMatch[1] : '';
     bool containsDomImport = domImportRegExp.hasMatch(contents);
-    int numStaticTypeAnnotations = 0;
-    for (var i in staticTypeRegExp.allMatches(contents)) {
-      numStaticTypeAnnotations++;
-    }
-    int numCompileTimeAnnotations = 0;
-    for (var i in compileTimeRegExp.allMatches(contents)) {
-      numCompileTimeAnnotations++;
-    }
 
     // Note: This is brittle. It's the age-old problem of having a context free
     // language but the means to easily identify the construct is a regular
@@ -1509,15 +1485,13 @@
              "packageRoot": packageRoot,
              "hasCompileError": false,
              "hasRuntimeError": false,
-             "isStaticClean" : isStaticClean,
+             "hasStaticWarning" : false,
              "otherScripts": otherScripts,
              "isMultitest": isMultitest,
              "isMultiHtmlTest": isMultiHtmlTest,
              "subtestNames": subtestNames,
              "isolateStubs": isolateStubs,
-             "containsDomImport": containsDomImport,
-             "numStaticTypeAnnotations": numStaticTypeAnnotations,
-             "numCompileTimeAnnotations": numCompileTimeAnnotations };
+             "containsDomImport": containsDomImport };
   }
 
   List<List<String>> getVmOptions(Map optionsFromFile) {
@@ -1579,15 +1553,13 @@
       "packageRoot": null,
       "hasCompileError": hasCompileError,
       "hasRuntimeError": hasRuntimeError,
-      "isStaticClean" : !hasCompileError && !hasStaticWarning,
+      "hasStaticWarning" : hasStaticWarning,
       "otherScripts": <String>[],
       "isMultitest": isMultitest,
       "isMultiHtmlTest": false,
       "subtestNames": <String>[],
       "isolateStubs": '',
       "containsDomImport": false,
-      "numStaticTypeAnnotations": 0,
-      "numCompileTimeAnnotations": 0,
     };
   }
 }
@@ -1597,20 +1569,14 @@
 ///
 /// Usually, the result of a dartc run is determined by the output of
 /// dartc in connection with annotations in the test file.
-///
-/// If you want each file that you are running as a test to have no
-/// static warnings or errors you can create a DartcCompilationTestSuite
-/// with the optional allStaticClean constructor parameter set to true.
 class DartcCompilationTestSuite extends StandardTestSuite {
   List<String> _testDirs;
-  bool allStaticClean;
 
   DartcCompilationTestSuite(Map configuration,
                             String suiteName,
                             String directoryPath,
                             List<String> this._testDirs,
-                            List<String> expectations,
-                            {bool this.allStaticClean: false})
+                            List<String> expectations)
       : super(configuration,
               suiteName,
               new Path(directoryPath),
@@ -1632,16 +1598,45 @@
 
     return group.future;
   }
-
-  Map readOptionsFromFile(Path p) {
-    Map options = super.readOptionsFromFile(p);
-    if (allStaticClean) {
-      options['isStaticClean'] = true;
-    }
-    return options;
-  }
 }
 
+class AnalyzeLibraryTestSuite extends DartcCompilationTestSuite {
+  AnalyzeLibraryTestSuite(Map configuration)
+      : super(configuration,
+              'analyze_library',
+              'sdk',
+              ['lib'],
+              ['tests/lib/analyzer/analyze_library.status']);
+
+  List<String> additionalOptions(Path filePath, {bool showSdkWarnings}) {
+    var options = super.additionalOptions(filePath);
+    // NOTE: This flag has been deprecated.
+    options.add('--show-sdk-warnings');
+    return options;
+  }
+
+  bool isTestFile(String filename) {
+    var sep = Platform.pathSeparator;
+    // NOTE: We exclude tests and patch files for now.
+    return filename.endsWith(".dart") &&
+        !filename.endsWith("_test.dart") &&
+        !filename.contains("_internal/lib");
+  }
+
+  AnalysisCommand makeAnalysisCommand(TestInformation info,
+                                      List<String> arguments) {
+    bool fileFilter(String filepath) {
+      return filepath == "${info.originTestPath}";
+    }
+
+    return CommandBuilder.instance.getAnalysisCommand(
+        configuration['compiler'], dartShellFileName, arguments,
+        configurationDir, flavor: configuration['compiler'],
+        fileFilter: fileFilter);
+  }
+
+  bool get listRecursively => true;
+}
 
 class JUnitTestSuite extends TestSuite {
   String directoryPath;
diff --git a/tools/utils.py b/tools/utils.py
index 8833930..26d78ca 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -231,6 +231,13 @@
 def GetBaseDir():
   return BASE_DIR
 
+# Return the base part of the version, Major.Minor.Build.Patch,
+# without the _revision addition
+def GetShortVersion():
+  (major, minor, build, patch) = ReadVersionFile()
+  return '%s.%s.%s.%s' % (major, minor, build, patch)
+
+
 def GetVersion():
   version_tuple = ReadVersionFile()
   if not version_tuple:
diff --git a/utils/compiler/create_snapshot.dart b/utils/compiler/create_snapshot.dart
index 37920a3..3b6cbfd 100644
--- a/utils/compiler/create_snapshot.dart
+++ b/utils/compiler/create_snapshot.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-Future<String> getVersion(var options, var rootPath) {
+Future<String> getVersion(var rootPath) {
   var suffix = Platform.operatingSystem == 'windows' ? '.exe' : '';
   var printVersionScript = rootPath.resolve("tools/print_version.py");
   return Process.run("python$suffix",
@@ -16,25 +16,24 @@
   });
 }
 
-Future<String> getSnapshotGenerationFile(var options, var args, var rootPath) {
+Future<String> getSnapshotGenerationFile(var args, var rootPath) {
   var dart2js = rootPath.resolve(args["dart2js_main"]);
   var dartdoc = rootPath.resolve(args["dartdoc_main"]);
-  return getVersion(options, rootPath).then((version) {
+  return getVersion(rootPath).then((version) {
     var snapshotGenerationText =
 """
 import '${dart2js.toFilePath(windows: false)}' as dart2jsMain;
 import '${dartdoc.toFilePath(windows: false)}' as dartdocMain;
 import 'dart:io';
 
-void main() {
-  Options options = new Options();
-  if (options.arguments.length < 1) throw "No tool given as argument";
-  String tool = options.arguments.removeAt(0);
+void main(List<String> arguments) {
+  if (arguments.length < 1) throw "No tool given as argument";
+  String tool = arguments[0];
   if (tool == "dart2js") {
     dart2jsMain.BUILD_ID = "$version";
-    dart2jsMain.mainWithErrorHandler(options);
+    dart2jsMain.main(arguments.skip(1).toList());
   } else if (tool == "dartdoc") {
-    dartdocMain.mainWithOptions(options);
+    dartdocMain.main(arguments.skip(1).toList());
   }
 }
 
@@ -50,8 +49,8 @@
     writer.close();
 }
 
-Future createSnapshot(var options, var dart_file, var packageRoot) {
-  return Process.run(options.executable,
+Future createSnapshot(var dart_file, var packageRoot) {
+  return Process.run(Platform.executable,
                      ["--package-root=$packageRoot",
                       "--snapshot=$dart_file.snapshot",
                       dart_file])
@@ -67,12 +66,11 @@
  * --output_dir=val     The full path to the output_dir.
  * --dart2js_main=val   The path to the dart2js main script releative to root.
  */
-void main() {
-  Options options = new Options();
+void main(List<String> arguments) {
   var validArguments = ["--output_dir", "--dart2js_main", "--dartdoc_main",
                         "--package_root"];
   var args = {};
-  for (var argument in options.arguments) {
+  for (var argument in arguments) {
     var argumentSplit = argument.split("=");
     if (argumentSplit.length != 2) throw "Invalid argument $argument, no =";
     if (!validArguments.contains(argumentSplit[0])) {
@@ -85,12 +83,12 @@
   if (!args.containsKey("output_dir")) throw "Please specify output_dir";
   if (!args.containsKey("package_root")) throw "Please specify package_root";
 
-  var scriptFile = new Uri.file(new File(options.script).fullPathSync());
+  var scriptFile = new Uri.file(new File(Platform.script).fullPathSync());
   var path = scriptFile.resolve(".");
   var rootPath = path.resolve("../..");
-  getSnapshotGenerationFile(options, args, rootPath).then((result) {
+  getSnapshotGenerationFile(args, rootPath).then((result) {
     var wrapper = "${args['output_dir']}/utils_wrapper.dart";
     writeSnapshotFile(wrapper, result);
-    createSnapshot(options, wrapper, args["package_root"]);
+    createSnapshot(wrapper, args["package_root"]);
   });
 }